JavaEE 企业级分布式高级架构师(十八)容器虚拟化技术(1)
发布日期:2021-06-28 21:08:30 浏览次数:2 分类:技术文章

本文共 12436 字,大约阅读时间需要 41 分钟。

Docker学习笔记

Docker入门篇

认识容器化技术

LXC

  • LXC 指的是 Linux Containers,其功能通过 Cgroups 以及 Linux Namespaces 实现。也是第一套完整的 Linux 容器管理实现方案。在 LXC 出现之前, Linux 上已经有了类似 Linux-Vserver、OpenVZ 和 FreeVPS。虽然这些技术都已经成熟,但是这些解决方案还没有将它们的容器支持集成到主流 Linux 内核。相较于其它容器技术,LXC 能够在无需任何额外补丁的前提下运行在原版 Linux 内核之上。目前 LXC 项目由 Canonical 有限公司负责赞助及托管。

在这里插入图片描述

Docker

  • Docker 项目最初是由一家名为 DotCloud 的平台即服务厂商所打造,其后该公司更名为 Docker。Docker 在起步阶段使用 LXC,而后利用自己的 Libcontainer 库将其替换下来。与其它容器平台不同,Docker 引入了一整套与容器管理相关的生态系统。其中包括一套高效的分层式容器镜像模型、一套全局及本地容器注册表、一个精简化 REST API 以及一套命令行界面等等。
  • 与 Docker 具有同样目标功能的另外一种容器技术就是 CoreOS 公司开发的 Rocket。Rocket 基于 App Container 规范并使其成为一项更为开放的标准。

在这里插入图片描述

Docker 原理

  • 容器是一种轻量级的虚拟化技术,因为它跟虚拟机比起来,它少了一层 hypervisor 层。先看一下下面这张图,这张图简单描述了一个容器的启动过程。
hypervisor:一种运行在物理服务器和操作系统之间的中间层软件,可以允许多个操作系统和应用共享一套基础物理硬件。可以将hypervisor看做是虚拟环境中的“元”操作系统,可以协调访问服务器上的所有物理设备和虚拟机,所以又称为虚拟机监视器(virtual machine monitor)。hypervisor是所有虚拟化技术的核心,非中断的支持多工作负载迁移是hypervisor的基本功能。当服务器启动并执行hypervisor时,会给每一台虚拟机分配适量的内存、cpu、网络和磁盘资源,并且加载所有虚拟机的客户操作系统。

在这里插入图片描述

  • 最下面是一个磁盘,容器的镜像是存储在磁盘上面的。上层是一个容器引擎,容器引擎可以是 docker,也可以是其它的容器引擎。引擎向下发一个请求,比如说创建容器,这时候它就把磁盘上面的容器镜像运行成在宿主机上的一个进程。
  • 对于容器来说,最重要的是怎么保证这个进程所用到的资源是被隔离和被限制住的,在 Linux 内核上面是由 cgroup 和 namespace 这两个技术来保证的。

Docker介绍

云服务的运营模式

Docker 是云时代的产物,它的诞生是一种必然。

  • IaaS(基础设施即服务):经营的是基础设施,比如阿里云服务器(只安装操作系统)
  • PaaS(平台即服务):经营的是平台,比如 MySQL 开发平台(安装在 linux里面现成的平台)、redis 开发平台。
  • SaaS(软件即服务):经营的是软件,比如公司的OA系统(部署到远程服务器中的 OA 软件)
  • Docker 就是伴随着 PaaS 产生的。

在这里插入图片描述

Docker是什么

  • Docker 就是一种虚拟化容器技术。通过 Docker 这种虚拟化容器技术,我们可以对物理机的资源进行更加合理有效的利用,可以将一台物理机器虚拟化出很多个拥有完整操作系统,并且相互独立的“虚拟计算机”

那么,什么是虚拟化呢?

  • 在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。这些资源的新虚拟部份是不受现有资源的架设方式,地域或物理组态所限制。一般所指的虚拟化资源包括计算能力和资料存储。
  • 在实际的生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用,透明化底层物理硬件,从而最大化的利用物理硬件。
    在这里插入图片描述
  • ​虚拟化技术种类很多,例如:软件虚拟化、硬件虚拟化、内存虚拟化、网络虚拟化(vip)、桌面虚拟化、服务虚拟化、虚拟机等等。
  • 最常用的虚拟化技术有:全虚拟化和操作系统(OS)虚拟化。比如 VMware workstation 就是全虚拟化的实现。比如 Docker,就是基于操作系统虚拟化技术的一种实现。
    在这里插入图片描述
  • 基于操作系统创建出一些相互独立的、功能虚拟化技术有多种实现方式,有基于硬件进行虚拟化的技术,而 Docker 只是针对操作系统进行虚拟化,对于硬件资源的使用率更低。
  • 相对于 VMware 这种虚拟化技术,Docker 拥有着显著的优势:
    在这里插入图片描述
  • 启动速度快,Docker 容器启动操作系统在秒级就可以完成,而 VMware 却是达到分钟级。
  • 系统资源消耗低,一台 Linux 服务器可以运行成千上百个 Docker 容器,而VMware 大概只能同时运行 10 个左右。
  • 更轻松的迁移和扩展,由于 Docker 容器比 VMware 占用更少的硬盘空间,在需要搭建几套软件环境的情况下,对安装好的 Docker 容器进行迁移会更快捷,更方便。而且 Docker 容器几乎可以在任意的平台上运行,包括虚拟机、物理机、公有云,私有云,个人电脑等,这种兼容性,可以让用户将一个应用程序从一个平台直接迁移到另一个平台。

Docker能做什么

上手快

  • 用户只需要几分钟,就可以把自己的程序“Docker 化”。Docker 依赖于“写时复制”(copy-on-write)模型,使修改应用程序也非常迅速,可以说达到“随心所致,代码即改”的境界。
  • 随后,就可以创建容器来运行应用程序了。大多数 Docker 容器只需要不到 1 秒中即可启动。由于去除了管理程序的开销,Docker 容器拥有很高的性能,同时同一台宿主机中也可以运行更多的容器,使用户尽可能的充分利用系统资源。

项目职责的逻辑分类

  • 使用 Docker,开发人员只需要关心容器中运行的应用程序,而运维人员只需要关心如何管理容器。
  • Docker 设计的目的就是要加强开发人员写代码的开发环境与应用程序要部署的生产环境一致性。从而降低那种“开发时一切正常,肯定是运维的问题(测试环境都是正常的,上线后出了问题就归结为肯定是运维的问题)”

快速高效的开发生命周期

  • Docker 的目标之一就是缩短代码从开发、测试到部署、上线运行的周期,让你的应用程序具备可移植性,易于构建,并易于协作。
  • 通俗一点说,Docker 就像一个盒子,里面可以装很多物件,如果需要这些物件的可以直接将该大盒子拿走,而不需要从该盒子中一件件的取。

鼓励使用面向服务的架构(自动化部署)

  • Docker 还鼓励面向服务的体系结构和微服务架构。Docker 推荐单个容器只运行一个应用程序或进程,这样就形成了一个分布式的应用程序模型,在这种模型下,应用程序或者服务都可以表示为一系列内部互联的容器,从而使分布式部署应用程序,扩展或调试应用程序都变得非常简单,同时也提高了程序的内省性。(当然,可以在一个容器中运行多个应用程序)
  • 当然,Docker 的强大远远不至于此,而作为软件开发人员的我们,更关注的是如何利用它来搭建一套统一的软件开发环境。

Docker核心概念

Docker 包含四个基本概念:理解了这四个概念,就理解了 docker 的整个生命周期了!

  • 镜像(Image)
  • 容器(Container)
  • 仓库注册中心(Registry)
  • 仓库(Repository)
    在这里插入图片描述

镜像

  • Docker 镜像(Image)就是一个只读的模板。
  • Docker 镜像可以用来创建 Docker 容器。
  • Docker 镜像和 Docker 容器的关系,类似于 java 中 class 类与对象之间的关系。
  • Docker 提供了一个很简单的机制来创建镜像或者更新已有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

容器

  • Docker 利用容器(Container)来运行应用。
  • 容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
  • 可以把容器看成是一个简易版的 Linux 环境(包括 ROOT 用户权限、进程空间、用户空间、网络等)和运行在其中的应用程序。

Registry&Repository

  • Registry 是集中存放镜像文件的场所。
  • Repository 是对于其中的镜像进行分类管理。
  • 一个 Registry 中会有多个 Repository。
  • 一个 Repository 中会有多个不同 tag 的 Image。
  • 比如名称为 centos 的 Repository 仓库下,有 tag 为 6 或者 7 的 Image 镜像。
  • Registry 分为公有(public)和私有(private)两种形式。
* 最大的公有Registry是DockerHub,存放了数量庞大的镜像供用户下载使用。* 国内的公开 Registry 包括 USTC、网易云、DaoCloud、AliCloud 等,可以供大陆用户更稳当快捷的访问。* 用户可以在本地创建一个私有 Registry。
  • 用户创建了自己的镜像之后就可以使用 push 命令将它上传的公有 Registry 或者私有 Registry 中,这样下次在另一台机器上使用这个镜像的时候,只需要从 Registry 上 pull 下来运行就可以了。

Docker应用实战篇

Docker安装

  • 安装docker:
yum install -y yum-utils device-mapper-persistent-data lvm2# 紧接着配置一个稳定(stable)的仓库、仓库配置会保存到/etc/yum.repos.d/docker-ce.repo文件中yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo# 或者使用阿里云的镜像源# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 更新Yum安装的相关Docke软件包&安装Docker CEyum update -y && yum install docker-ce# 安装好后查看版本docker --version  或  docker -v
  • 设置docker daemon文件:
# 创建/etc/docker目录mkdir /etc/docker# 更新daemon.json文件cat > /etc/docker/daemon.json <
  • 重启docker服务:
systemctl daemon-reload && systemctl restart docker && systemctl enable docker
  • 检测是否按照成功:
[root@centos108 ~]# docker imagesREPOSITORY   TAG       IMAGE ID   CREATED   SIZE

Docker镜像

搜索镜像

  • 如果你需要从网络中查找需要的镜像,可以通过以下命令搜索:
docker search centos

在这里插入图片描述

  • NAME:仓库名称
  • DESCRIPTION:镜像描述
  • STARS:用户评价,反应一个镜像的受欢迎程度
  • OFFICIAL:是否官方
  • AUTOMATED:自动构建,表示该镜像有 Docker Hub 自动构建流程创建的

拉取镜像

我们可以使用命令从一些公用仓库中拉取镜像到本地,下面就列举一些常用的公用仓库拉取镜像的方式

从Docker Hub拉取

  • Docker Hub 的网址:https://hub.docker.com/
  • 需求:从 Docker Hub 仓库下载一个 CentOS 7 版本的操作系统镜像
  • 命令如下:
docker pull centos:7

在这里插入图片描述

  • Docker Hub 是 docker 默认的公用 Registry,不过缺点是国内下载会比较慢。

从USTC拉取(建议使用)

  • 在宿主机器编辑文件:
vim /etc/docker/daemon.json
  • 在该配置文件中加入(没有该文件的话,请先建一个):
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]}
  • 最后,需要重启 docker 服务:
systemctl restart docker
  • 之后再使用 pull 命令拉取镜像,这时候是从 ustc 获取镜像,而且速度杠杠的:docker pull centos:7
[root@localhost ~]# docker pull centos:7Trying to pull repository docker.io/library/centos ... 7: Pulling from docker.io/library/centosd8d02d457314: Pull complete Digest: sha256:307835c385f656ec2e2fec602cf093224173c51119bbebd602c53c3653a3d6ebStatus: Downloaded newer image for docker.io/centos:7[root@localhost ~]#

列出镜像

docker images

在这里插入图片描述

  • REPOSITORY:镜像所在仓库名称
  • TAG:镜像版本
  • IMAGE ID:镜像 ID
  • CREATED:镜像创建时间
  • SIZE:镜像大小

删除镜像

  • 删除指定镜像:
docker rmi repository:tagdocker rmi imageID
  • 删除所有镜像:
docker rmi $(docker images -q)
  • 注意:删除时,如果镜像的 image id 一致,则需要按照一定顺序进行删除,因为镜像之间有关联(reference)。

导入导出镜像(镜像迁移)

导出镜像

docker save repository:tag/imageId > /root/xx.tar.gzdocker save -o mynginx.tar mynginx
  • -o:输出到的文件
  • 执行后,运行 ls 命令即可看到打成的 tar 包

导入镜像

docker load < /root/xx.tar.gzdocker load -i mynginx.tar
  • -i:输入的文件
  • 执行后再次查看镜像,可以看到镜像已经恢复

Docker容器

创建并运行容器

创建容器命令:docker run,常用的参数说明如下:

  • -i:表示运行容器。
  • -t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端。
  • –name:为创建的容器命名。
  • -v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个 -v 做多个目录或文件的映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
  • -d:在 run 后面加上 -d 参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加-i -t 两个参数,创建后就会自动进去容器)。
  • -p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个 -p 做多个端口映射。
    在这里插入图片描述

以交互式运行容器

docker run -i -t --name 容器名称 repository:tag /bin/bashdocker run -it --name 容器名称 imageId /bin/bash

以守护进程方式运行容器

docker run -di --name 容器名称 repository:tagdocker run -di --name 容器名称 imageId
  • 注意:通过 run 创建并进入容器之后,如果使用 exit 命令退出容器,则容器停止。再次进入该容器,先使用 start 启动容器,再使用 exec/attach 命令进入容器。

启动容器

docker start 容器名称或者容器ID

进入容器

  • 进入正在运行的容器的命令如下:
docker exec -it 容器名称或者容器ID /bin/bashdocker attach 容器名称或者容器ID
  • 两者之间的区别:attach 进入容器之后,如果使用 exit 退出容器,则容器停止。exec 进入容器之后,使用 exit 退出容器,容器依然处于运行状态。

查看容器

docker ps:查看正在运行的容器docker ps -a:查看历史运行过的容器docker ps -l:查看最近运行过的容器

停止容器

docker stop 容器名称或者容器ID

删除容器

  • 删除指定容器:
docker rm 容器名称或者容器 ID
  • 删除所有容器:
docker rm 'docker ps -a -q'

复制文件

docker cp 源文件 目标文件

在这里插入图片描述

  • 比如:docker cp /root/boot.war my-centos:/usr/local/
  • /root/boot.war 是宿主机器的路径;my-centos 是容器的名称;/usr/local/ 是容器内的路径。
  • 注意:源文件可以是宿主机器也可以是容器中的文件,同样,目标文件可以是容器也可以是宿主机器的文件。

Docker应用

MySQL部署

拉取MySQL镜像

docker pull mysql:5.6

创建MySQL容器

docker run -di --name docker_mysql -p 33306:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.6
  • -p 代表端口映射,格式为 宿主机映射端口:容器运行端口
  • -e 代表添加环境变量 MYSQL_ROOT_PASSWORD 是 root 用户的登陆密码

进入MySQL容器,登录MySQL

  • 进入 mysql 容器
docker exec -it docker_mysql /bin/bash
  • 登录 mysql
mysql -uroot -p

远程登录MySQL

  • 在我们本机的电脑上去连接虚拟机 Centos 中的 Docker 容器,这里 192.168.254.120 是虚拟机操作系统的 IP
    在这里插入图片描述

查看容器IP地址

  • 我们可以通过以下命令查看容器运行的各种数据
docker inspect docker_mysql
  • 运行效果如下:可以看到我们的数据库服务器的 IP 是 172.17.0.2
    在这里插入图片描述

Tomcat部署

拉取tomcat镜像

docker pull tomcat:7-jre7

创建tomcat容器

  • 创建容器 -p 表示地址映射
docker run -di --name docker_tomcat -p 9000:8080 tomcat:7-jre7
  • docker启动报错:WARNING: IPv4 forwarding is disabled. Networking will not work. 需要做如下配置:
vim /usr/lib/sysctl.d/00-system.conf添加如下代码:net.ipv4.ip_forward=1重启network服务systemctl restart network

测试

浏览器访问:http://192.168.254.120:9000/

在这里插入图片描述

Nginx部署

拉取nginx镜像

docker pull nginx

创建nginx容器

docker run -di --name docker_nginx -p 9080:80 nginx# 进入容器并启动nginx[root@localhost ~]# docker exec -it docker_nginx /bin/bashroot@69473e62ad1d:/# /usr/sbin/nginx

测试nginx

curl 'http://192.168.254.120:9080'

在这里插入图片描述

Redis部署

拉取镜像

docker pull redis

创建redis容器

docker run -di --name docker_redis -p 16379:6379 redis

客户端测试

在这里插入图片描述

搭建Tomcat服务并部署web应用

命令

docker run -di --name my-tomcat -v /root/webapps: /usr/local/tomcat/webapps -p8888:8080 imageID

或者

docker run -ti --name my-tomcat -v /opt/webapps:/opt/tomcat/webapps -p 8888:8080imageID /bin/bash
  • 容器内的 tomcat 目录:/usr/local/tomcat/webapps

参数说明

  • –name:该参数的作用是给容器起一个名字,名字要唯一。
  • -v:该参数的作用是进行目录映射,具体指的是宿主机器和容器之间的目录映射。
/kkb/webapps:宿主机器的目录/usr/local/tomcat/webapps:容器中的目录
  • -p:该参数的作用是进行端口映射,具体指的是宿主机器和容器之间的端口映射。8888 端口是宿主机的端口,8080 端口是容器内的端口。

部署

  • 创建目录:mkdir /kkb/webapps
  • 运行命令:
docker run -di --name docker-tomcat-web -v /kkb/webapps:/usr/local/tomcat/webapps -p 8888:8080 --privileged=true tomcat:7-jre7# --privileged=true 给容器访问目录授权
  • 进入容器查看:
[root@localhost ~]# docker exec -it docker-tomcat-web /bin/bashroot@e6b5068a9f6c:/usr/local/tomcat# cd /usr/local/tomcat/wwebapps/ work/    root@e6b5068a9f6c:/usr/local/tomcat# cd /usr/local/tomcat/webapps/root@e6b5068a9f6c:/usr/local/tomcat/webapps# lsroot@e6b5068a9f6c:/usr/local/tomcat/webapps# ps -ef | grep tomcatroot         1     0  2 14:33 ?        00:00:02 /docker-java-home/jre/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap startroot        55    48  0 14:35 ?        00:00:00 grep tomcatroot@e6b5068a9f6c:/usr/local/tomcat/webapps#
  • 拷贝部署 war 包到指定的宿主机目录:将自动完成热部署
cp kkb-docker.war /kkb/webapps/
  • 访问测试:http://192.168.254.120:8888/kkb-docker/test

在这里插入图片描述

制作镜像

纯手工制作镜像

需求

制作一个 tomcat 镜像

步骤

  • 下载基础镜像(centos7)
docker pull centos:7(注意:jdk 要和 os 的位数一致)
  • 安装 64 位 jdk
vim /etc/profileexport JAVA_HOME=/opt/jdkexport PATH=$JAVA_HOME/bin:$PATHsource /etc/profile
  • 安装 tomcat
  • 生成新的镜像
docker commit 容器名称或者容器 ID 新镜像名称

Dockerfile

什么是Dockerfile

  • Dockerfile是由一系列参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。
  • 对于开发人员:可以为开发团队提供一个完全一致的开发环境。
  • 对于测试人员:可以直接拿开发时所构建的镜像或者通过 Dockerfile 文件构建一个新的镜像开始工作。
  • 对于运维人员:在部署时,可以实现应用的无缝移植。

常用命令

命令 作用
FROM Image_name:tag 定义了使用哪个基础镜像启动构建流程
MAINTAINER user_name 声明镜像的创建者
ENV key value 设置环境变量(可以写多条)
RUN command 是 Dockerfile 的核心部分(可以写多条)
ADD source_dir/file dest_dir/file 将宿主机的文件复制到容器内,如果是一个压缩文件,
将会在复制后自动解压
COPY source_dir/file dest_dir/file 和 ADD 相似,但是如果有压缩文件并不能压缩
WORKDIR path_dir 设置工作目录
EXPOSE port1 port2 用来指定端口,使容器内的应用可以通过端口和外界交互
CMD argument 在构建容器时使用,会被 docker run 后的 argument 覆盖
ENTRYPOINT argument 和 CMD 相似,但是并不会被 docker run 指定的参数覆盖
VOLUME 将本地文件夹或者其他容器的文件挂载到容器中

使用脚本创建镜像

创建JDK1.8镜像
  • 创建目录:在本地 linux 机器创建一个工作目录
mkdir -p /usr/apps/docker_workspace
  • 下载 jdk-8u241-linux-x64.tar.gz 并上传到服务器中的 /usr/apps/docker_workspace 目录

在这里插入图片描述

  • 创建 Dockerfile 文件:
# 第一套配置:# 依赖镜像名称和IDFROM centos:latest# 指定镜像创建者信息MAINTAINER veli# 切换工作目录WORKDIR /java# ADD 是相对路径jar,把java添加到容器中ADD jdk-8u241-linux-x64.tar.gz /java# 配置java环境变量ENV JAVA_HOME /java/jdk1.8.0_241ENV PATH $JAVA_HOME/bin:$PATH# 第二套配置,前面一直报错,因此用了第二套,但是经过测试时镜像构建编码问题,和JDK无关。因此第一个和第二个配置都是OK的# 依赖镜像名称和IDFROM centos:latest# 指定镜像创建者信息MAINTAINER veli# 切换工作目录WORKDIR /java# ADD 是相对路径jar,把java添加到容器中ADD jdk-8u241-linux-x64.tar.gz /java# 配置java环境变量ENV JAVA_HOME /java/jdk1.8.0_241ENV JRE_HOME $JAVA_HOME/jreENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATHENV PATH $JAVA_HOME/bin:$PATH
  • 执行命令构建镜像:
# 构建镜像 -t: -tag 指定镜像的名称版本docker build -t='jdk1.8' .# 命令变形docker build -t jdk1.8 .# 命令变形docker build -t jdk1.8:v1 .

在这里插入图片描述

  • 查看镜像是否建立完成:

在这里插入图片描述

  • 创建容器:
docker run -it --name=myjdk jdk1.8:v1 /bin/bash

在这里插入图片描述

制作jar包镜像
  • 我就用之前 spring cloud alibaba 项目中的一个提供者 01-provider-8081 工程的jar包
  • 创建Dockerfile:
FROM jdk1.8:v1VOLUME /tmpADD 01-provider-8081-1.0.jar /usr/localENTRYPOINT ["java", "-jar", "/usr/local/01-provider-8081-1.0.jar"]
  • 创建镜像:
docker build -t='01-provider-8081:1.0' .

在这里插入图片描述

  • 创建容器:
docker run -di --name=01-provider -p 8888:8081 01-provider-8081:1.0

在这里插入图片描述

  • 测试发现好使啦!!

转载地址:https://blog.csdn.net/yangwei234/article/details/97831360 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:并发编程之二
下一篇:JavaEE 企业级分布式高级架构师(十七)ElasticSearch全文检索(4)

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月28日 03时15分22秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章