java swarm集群_[docker]使用swarm搭建分布式应用

ee8751ed851c788b48ce66885b1364b9.png

阅读本文前应简单了解dubbo、springboot、redis、zookeeper以及单机上操作docker的相关知识。欲部署的应用的架构图:

cedb095f216a54f13a48a1ef4305508d.png

其中hello-web的8080端口对外提供访问,且本身是provider工程的消费者,redis用于作缓存服务,两个provider工程实例是dubbo调用的生产者,zk做注册中心。

hello-web为springboot项目,只有一个controller,如下,代码很简单:

1fda178fc5cb3d860ce1bb1a25351ef2.png

其中NetService是dubbo接口,由provider工程提供实现:

c93276339f08b66c36e749b8317befd7.png

下面开始将上图的架构图在docker容器中来部署。

初始化环境

试验环境:192.168.0.106 192.168.0.104 两台虚拟机 默认106为swarm主节点 docker版本为18.09

首先需要在2台机器上拉取需要的镜像:

docker pull redis
docker pull zookeeper
docker pull centos

在106机器上初始化swarm:

docker swarm init --advertise-addr 192.168.0.106

0f6e3efa0fc3901ae7223ac4797af139.png

根据提示,在104机器上执行下面命令以加入swarm集群:

docker swarm join --token SWMTKN-1-3jx4s9pokfeuokjimty31mlfbz0ykwope5u25fbo75jkwrgjx1-8v5n1zgz05wz3z0bidvh792uw 192.168.0.106:2377

接着在106机器上执行 docker node ls 即可查看集群节点情况:

2233ceb950176cde59e836309ec26788.png

创建overlay网络

在106机器上执行如下命令,创建一个名为overlay_network的overlay网络:

docker network create -d overlay overlay_network

在swarm环境下,该网络配置会自动同步到其他节点(当其他节点部署service实例时开始同步),因此不必再在其他节点上创建该网络。

4cf41ecfe170e81bcc3c674ef9bbdaa0.png

启动redis和zk

在106机器上执行如下命令,关键是指定网络模式:

docker service create -d --name redis-service --network overlay_network redis
docker service create -d --name zk-service --network overlay_network zookeeper

d285c1da608f7a97dc319186912f0d19.png

可以看到,zk服务被swarm安排在了104这台机器上启动,redis在106上。

部署hello-web服务

在hello-web工程的配置文件中配置好redis的地址,由于服务的部署是由swarm来做的,因此我们并不知道最终工程会被部署到哪个机器上因此也就不知道工程的IP是多少(虽然你进到redis-service这个服务里可以看到ip,然后把这个ip填到hello-web工程中也可以,但这样毕竟麻烦,而且以后服务因为挂掉等原因在其他机器上又启动后,你将不得不重启动hello-web来修改redis的地址)。因此这里使用服务名作为地址,swarm会自动做好DNS解析(swarm下一个服务的多个实例对外暴露的是一个VIP),故application.properties的内容如下:

server.port=8080
#Redis配置
spring.redis.database=0
spring.redis.host=redis-service
spring.redis.port=6379
spring.redis.timeout=10000ms
#Dubbo 服务消费者配置
spring.dubbo.application.name=hello-web
spring.dubbo.registry.address=zookeeper://zk-service:2181
spring.dubbo.scan=com.example.helloweb.controller

将hello-web工程打包为一个可执行的jar文件(内嵌tomcat),然后通过ftp等手段上传到106虚拟机上,并准备好解压好的jdk以备制作镜像之用。

e46d01e3823609a7132bf8d7de110009.png

接着改写Dockerfile文件内容如下:

FROM centos
MAINTAINER wang
COPY jdk1.8.0 jdk1.8.0
ADD hello-web-0.0.1-SNAPSHOT.jar hello-web-0.0.1-SNAPSHOT.jar
ENV JAVA_HOME=/jdk1.8.0
ENV PATH=$JAVA_HOME/bin:$PATH
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/hello-web-0.0.1-SNAPSHOT.jar"]

主要的步骤就是拷贝jdk和工程文件到容器,设置jdk环境变量,以及暴露端口。接着完成镜像制作:

docker build -t wang/hello-web . 

执行下面命令启动hello-web服务:

docker service create -d --name hello-web --network overlay_network wang/hello-web

e5c3d4731abfb9b8023af3d45b13334b.png

在浏览器输入以下网址验证redis和hello-web之间的网络是否联通:

8ee3d7afe3e880fe1e8ee488cdbeb89d.png

部署dubbo提供者

基本过程同部署hello-web一样。

Dockerfile的内容如下:

FROM centos
MAINTAINER wang
COPY jdk1.8.0 jdk1.8.0
ADD provider-0.0.1-SNAPSHOT.jar provider-0.0.1-SNAPSHOT.jar
ENV JAVA_HOME=/jdk1.8.0
ENV PATH=$JAVA_HOME/bin:$PATH
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/provider-0.0.1-SNAPSHOT.jar"]

使用 docker build -t wang/provider . 完成镜像制作,在另一台机器上重复此操作制作镜像。执行下面命令启动provider服务,使用replicas参数设置启动2个provider服务实例:

docker service create -d --name provider --replicas 2 --network overlay_network wang/provider 

8be312c024a1a18a5b56141abe247a4e.png

从上面看,4个服务已经全部启动完成了。接下来验证dubbo调用是否正常:

c90eff4089ff60047aef95627abbef40.png

可以看到顺利的实现了dubbo远程调用以及负载均衡。

下图反映了现在的服务分布情况,其中hello-web和provider间的通信走的是直接ip(与VIP对应),其他服务之间的通信走的是VIP访问。

c81addd9d9bd4a84f76f3ebea35c8be9.png

我们通过 "docker exec -it zk的容器id sh" 进入zk,使用zkCli.sh查看生产者信息:

afc2cfc17804b1fa7fafb3f630566b11.png

可以看到zk上存储的是provider工程的ip而不是vip。但是如果ping一下provider工程,就能看到通过域名方式访问的话,走的是vip方式,因为这里的10.0.0.94不属于任意一个容器:

9f9b7d6e4c99487f6145655ab6aa3d4d.png

redis挂了怎么办?

前面我们看到我只部署了一个redis服务实例,它位于106机器。我们看看如果redis挂掉会发生什么情况。我们进到106机器执行以下命令停掉redis以模拟挂掉的情况:

docker container stop 6ce54c6541fe

然后我们重新发起访问,会发现hello-web工作的好好的:

89261662c7a2f76f810c1f5a045ffbbb.png

原因是swarm会自动将挂掉的服务恢复,如下图(可能是在另一台机器上),因此通过域名的方式来访问屏蔽了底层ip地址变动对我们的影响,因此类似hello-web这类无状态的应用很适合部署在docker容器里;当然,由于没有设置数据卷,因此挂掉的redis里的数据也就丢掉了。

58c31f06656ab5ea53e988d9de479d0c.png

最后使用:

docker service rm redis-service 

这样的命令来关闭服务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值