微服务实施笔记(四)——部署服务发现
上回书搭建了3个待用的服务。用来模拟实际中的服务。接下来就是把这几个服务注册到一个服务管理中心了。
使用consul搭建服务管理中心
在这里选用consul来做服务管理中心。consul是采用golang开发的,CAP中满足CP的一款服务管理系统。选择它的原因就是它足够简单。简单到什么程度呢,一行代码搞定:
sudo docker run -d \
-e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' \
--name=node1 -p 8300:8300 -p 8301:8301 -p 8301:8301/udp \
-p 8302:8302/udp -p 8302:8302 -p 8400:8400 -p 8500:8500 \
-p 53:53/udp -h consul_node1 \
consul agent -server -bootstrap \
-node=node1 -client 0.0.0.0 -ui
执行后在浏览器中查看 http://localhost:8500/ui
就是如此简单,而且自带ui。好的软件都应如此简单。
Consul 四大特性
- Service Discovery (服务发现)
- Health Check (健康检查)
- Multi Datacenter (多数据中心)
- Key/Value Storage(KV键值存储)
下文在介绍如何利用这四大特性。
这下,待发现的服务有了,可以注册服务的管理中心也有了,接下来怎么办呢,怎么把服务注册到服务中心呢。
自动注册服务
服务注册可以分为“自注册” 与 “第三方注册”两种方式。
以下内容引用自http://blog.csdn.net/jek123456/article/details/78083618
1.自注册:服务内部启动客户端,连接注册中心,写入服务信息。
好处:
- 没有引入第三方,进程数量少,少依赖。
问题:
- 服务代码对注册中心进行了硬编码,若更换了注册中心,服务代码也必须跟着调整;
- 注册中心必须与每个服务都保持通信,来做心跳检测。如果服务很多时,对注册中心也是一种额外的开销;
2.第三方注册(本文采用方式):采用协同进程的方式,监听服务进程的变化,将服务信息写入注册中心。
- 好处:做到了服务与注册中心的解耦,对服务而言,完成了服务的自动化注册;
- 问题:协同进程本身也要考虑高可用,否则将成为单点故障的风险点;
第三方注册需要一个注册工具,这里使用Registrator
Registrator:一个由Go语言编写的,针对docker使用的,通过检查本机容器进程在线或者停止运行状态,去注册服务的工具。所以我们要做的实验,所有的工具都是在docker上运行的,就是因为registrator是通过检查docker容器的状态来判断服务状态的,这样就和我们的代码实现完全解耦了,对上层透明化,无感知。它有如下特点
- 通过docker socket直接监听容器event,根据容器启动/停止等event来注册/注销服务
- 每个容器的每个exposed端口对应不同的服务
- 支持可插拔的registry backend,默认支持Consul, etcd and SkyDNS
- 自身也是docker化的,可以容器方式启动
- 用户可自定义配置,如服务TTL(time-to-live)、服务名称、服务tag等
依然是一行代码搞定:
docker run -d \
--name=registrator \
--net=host \
--volume=/var/run/docker.sock:/tmp/docker.sock \
gliderlabs/registrator:latest \
consul://localhost:8500
这样启动的服务会有一个问题,就是registrator无法准确取到IP地址,所以最好把本地IP地址指定给registrator。方法就是使用docker-compose。新建一个docker-compose.yml文件,内容如下:
version: '2'
services:
registrator1:
image: gliderlabs/registrator
restart: always
network_mode: "host"
name: registrator
volumes:
- /var/run/docker.sock:/tmp/docker.sock
command: "-ip 192.168.1.231 consul://192.168.1.231:8500"
其中最后一行ip后面就是容器运行的宿主机的本地ip地址。然后在docker-compose.yml文件所在目录下执行docker-compose ip -d命令。
运行之后刷新下浏览器看看:
注册成功。但是这里只用到了consul四大特性中的第一个服务发现,它的另一个重要特性健康检查并没有被利用起来。健康检查会按照配置的时间间隔和方式检查服务的健康状态。这样就可以及时的剔除无法对外提供服务的服务了。那么怎么为服务配置健康检查呢?修改服务程序本身当然可以,但是这样的话就违背解耦合的初衷了。引入docker层就是为了解耦合用的,所以可以通过对dockerfile的配置来实现。
怎么用呢,可以使用dockerfile的lable或者环境变量来进行配置。
对于server1服务的docker配置如下(详细可以参考https://gliderlabs.com/registrator/latest/user/services/ 和 https://gliderlabs.com/registrator/latest/user/backends/):
以下是修改后的server1的daockerfile,其中通过环境变量增加了支持consul服务特性的配置项。
FROM microsoft/aspnetcore:2.0
LABEL Name=lizpen/server1 Version=0.0.1
#以下环境变量用来定义consul的服务属性
ENV SERVICE_NAME=server1
ENV SERVICE_ID=server1.001
ENV SERVICE_TAGS=server1
#以下环境变量用来定义consul的服务检查特性
ENV SERVICE_CHECK_HTTP=/api/values
ENV SERVICE_CHECK_INTERVAL=15s
ENV SERVICE_CHECK_TIMEOUT=10s
ARG source=.
WORKDIR /app
EXPOSE 3000
COPY $source/bin/Debug/netcoreapp2.0/ .
ENTRYPOINT dotnet server1.dll
先删除掉正在运行的容器,vscode侧边栏中的docker工具提供了这些功能,及其好用:
然后重新build docker镜像,并运行生成好的镜像。然后刷新consul的管理网站可以看到tags和健康检查都上线了。
至此,服务发现在单机运行成功。
接下来就是把这套东西部署到搭建好的虚拟环境中去。