TERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#启动第3个Server节点,并加入集群
docker run -d --name=consul3 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#启动第4个Client节点,并加入集群
docker run -d --name=consul4 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=false --client=0.0.0.0 --join 172.17.0.2
第1个启动容器的IP一般是172.17.0.2,后边启动的几个容器IP会排着来:172.17.0.3、172.17.0.4、172.17.0.5。
这些Consul节点在Docker的容器内是互通的,他们通过桥接的模式通信。但是如果主机要访问容器内的网络,需要做端口映射。在启动第一个容器时,将Consul的8500端口映射到了主机的8900端口,这样就可以方便的通过主机的浏览器查看集群信息。
进入容器consul1:
docker exec -it consul1 /bin/sh
#执行ls后可以看到consul就在根目录
ls
输入exit可以跳出容器。
服务注册
自己写一个web服务,用最熟悉的开发语言就好了,不过需要在容器中能够跑起来,可能需要安装运行环境,比如python、java、.net core等的sdk及web服务器,需要注意的是Consul的docker镜像基于alpine系统,具体运行环境的安装请搜索一下。
这里写了一个hello服务,通过配置文件的方式注册到Consul,服务的相关信息:
- name:hello,服务名称,需要能够区分不同的业务服务,可以部署多份并使用相同的name注册。
- id:hello1,服务id,在每个节点上需要唯一,如果有重复会被覆盖。
- address:172.17.0.5,服务所在机器的地址。
- port:5000,服务的端口。
- 健康检查地址:http://localhost:5000/,如果返回HTTP状态码为200就代表服务健康,每10秒Consul请求一次,请求超时时间为1秒。
请将下面的内容保存成文件services.json,并上传到容器的/consul/config目录中。
{
"services": [
{
"id": "hello1",
"name": "hello",
"tags": [
"primary"
],
"address": "172.17.0.5",
"port": 5000,
"checks": [
{
"http": "http://localhost:5000/",
"tls_skip_verify": false,
"method": "Get",
"interval": "10s",
"timeout": "1s"
}
]
}
]
}
复制到consul config目录:
docker cp {这里请替换成services.json的本地路径} consul4:/consul/config
重新加载consul配置:
然后这个服务就注册成功了。可以将这个服务部署到多个节点,比如部署到consul1和consul4,并同时运行。
服务发现
服务注册成功以后,调用方获取相应服务地址的过程就是服务发现。Consul提供了多种方式。
HTTP API方式:
curl http://127.0.0.1:8500/v1/health/service/hello?passing=false
返回的信息包括注册的Consul节点信息、服务信息及服务的健康检查信息。这里用了一个参数passing=false,会自动过滤掉不健康的服务,包括本身不健康的服务和不健康的Consul节点上的服务,从这个设计上可以看出Consul将服务的状态绑定到了节点的状态。
如果服务有多个部署,会返回服务的多条信息,调用方需要决定使用哪个部署,常见的可以随机或者轮询。为了提高服务吞吐量,以及减轻Consul的压力,还可以缓存获取到的服务节点信息,不过要做好容错的方案,因为缓存服务部署可能会变得不可用。具体是否缓存需要结合自己的访问量及容错规则来确定。
上边的参数passing默认为false,也就是说不健康的节点也会返回,结合获取节点全部服务的方法,这里可以做到获取全部服务的实时健康状态,并对不健康的服务进行报警处理。
DNS方式:
hello服务的域名是:hello.service.dc1.consul,后边的service代表服务,固定;dc1是数据中心的名字,可以配置;最后的consul也可以配置。
官方在介绍DNS方式时经常使用dig命令进行测试,但是alpine系统中没有dig命令,也没有相关的包可以安装,但是有人实现了,下载下来解压到bin目录就可以了。
curl -L https://github.com/sequenceiq/docker-alpine-dig/releases/download/v9.10.2/dig.tgz|tar -xzv -C /usr/local/bin
然后执行dig命令:
dig @127.0.0.1 -p 8600 hello.service.dc1.consul. ANY
如果报错:parse of /etc/resolv.conf failed ,请将resolv.conf中的search那行删掉。
正常的话可以看到返回了服务部署的IP信息,如果有多个部署会看到多个,如果某个部署不健康了会自动剔除(包括部署所在节点不健康的情况)。需要注意这种方式不会返回服务的端口信息。
使用DNS的方式可以在程序中集成一个DNS解析库,也可以自定义本地的DNS Server。自定义本地DNS Server是指将.consul域的请求全部转发到Consul Agent,Windows上有DNS Agent,Linux上有Dnsmasq;对于非Consul提供的服务则继续请求原DNS;使用DNS Server时Consul会随机返回具体服务的多个部署中的一个,仅能提供简单的负载均衡。
DNS缓存问题:DNS缓存一般存在于应用程序的网络库