适宜读者人群
准备使用Consul, 或者对服务发现感兴趣的开发者
追求高质量高可用的服务架构体系的人群
本文目录
Consul 简介
**Consul Glossary(术语) **
Consul Architecture(架构图)
Consul 与 应用集成的几种姿势
Docker registrator详解
Consul 与 Nginx集成的几种姿势
Consul 搭建配置中心
Consul 简介
Consul 四大特性
Service Discovery (服务发现)
Health Check (健康检查)
Multi Datacenter (多数据中心)
Key/Value Storage
Consul Glossary(术语)
Agent
Agent 是一个守护进程
运行在Consul集群的每个成员上
有Client 和 Server 两种模式
所有Agent都可以被调用DNS或者HTTP API,并负责检查和维护同步
Client
Client 将所有RPC请求转发至Server
Client 是相对无状态的
Client 唯一做的就是参与LAN Gossip Pool
Client 只消耗少量的资源和少量的网络带宽
Server
参与 Raft quorum(一致性判断)
响应RPC查询请求
维护集群的状态
转发查询到Leader 或 远程数据中心
Datacenter
顾名思义其为数据中心, 如何定义数据中心呢? 需要以下三点
私有的
低延迟
高带宽
故: 可以简单的理解为同属一个内网环境, 如北京机房和香港机房就不一定满足以上三个条件
Consensus (一致性)
Consul 使用consensus protocol 来提供CAP(一致性,高可用,分区容错性)
Gossip
一种协议: 用来保证 最终一致性 用来向集群广播消息
LAN Gossip
Local Area Network Gossip, 位于同一个局域网或者数据中心的节点
WAN Gossip
Wide Area Network Gossip, 只用于Server之间, 分部在不同的数据中心或广域网
上面说了那么多名词, 可能有点晕, 下面来看Consul集群的架构图
Consul Architecture 架构图
image.png
如上架构图可以看出几个关键点
Client和Client之间的LAN Gossip
Client将RPC请求发至Server, Follower Server将请求转发至Leader节点
Server之间的选举行为
Datacenter之间的WAN Gossip
Consul 与应用集成的几种姿势
首先来说说完整集成服务发现需要做哪些事:
应用启动时需要向Consul 注册服务
定时上报当前服务的状态
应用销毁时需要De-Register 注销自身服务
当Consul数据变化时需要修改本地配置
看上去很麻烦, 那么下面我们具体介绍三种姿势
应用本身作为一个Agent , 适用于SDK相对完善的语言, 如有Spring-Cloud-Consul 的Java
应用旁边(同一台主机)跑一个Client Agent
使用Docker registrator
以上三种方式该如何选择呢?
使用了Docker的话, 就用Docker registrator, 优点: 不用修改程序代码
如果没有用Docker的话, 尽量选择同一台主机下起一个Client模式的Consul agent, 程序本身集成的话, 可能会造成一些不良的反应, 同时有可能还得为服务宕掉背黑锅
Docker registrator详解
下面来说说Docker registrator 是怎么一回事, registrator 自身为一个Container, 运行在其他容器身边(可以理解为同一台主机)
首先是运行时有这么三个步骤:
启动Consul Server集群
启动registrator container
启动应用container
Docker Registrator 原理
Registrator is designed to be run once on every host, 也就是说同一台主机上只需要运行一个registrator即可, 并不用为每一个container起一个registrator
Registrator 会向consul集群register,deregister等操作
Registrator 通过读取同主机其他container的环境变量进行服务注册, 健康检查定义等操作
Docker Registrator 使用
集成方式很简单, 就是为你的应用添加需要的环境变量, 注意不是Registrator 的环境变量哦
Service Definition (服务定义)
环境变量Key
环境变量Value
说明
SERVICE_ID
web-001
可以为GUID或者可读性更强变量, 保证不重复
SERVICE_NAME
web
如果ID没有设置, Consul会将name作为id, 则有可能注册失败
SERVICE_TAGS
nodejs,web
服务的标签, 用逗号分隔,开发者可以根据标签来查询一些信息
SERVICE_IP
内网IP
要使用Consul 可访问的IP
SERVICE_PORT
50001
应用的IP, 如果应用监听了多个端口, 理应被视为多个应用
SERVICE_IGNORE
Boolean
是否忽略本Container, 可以为一些不需要注册的Container添加此属性
Health Check Definition (健康检查定义)
配置原则为: SERVICE_XX_* , 如果你的应用监听的是5000端口, 则改为SERVICE_5000_CHECK_HTTP, 其他变量同理
环境变量Key
环境变量Value
说明
--- 以下为HTTP模式
---
---
SERVICE_80_CHECK_HTTP
/path_to_health_check
你的健康状态检查的路径如 /status
SERVICE_80_CHECK_INTERVAL
15s
15秒检查一次
SERVICE_80_CHECK_TIMEOUT
2s
状态检查超时时间
--- 以下为HTTPS模式
---
---
SERVICE_443_CHECK_HTTPS
/path_to_health_check
你的健康状态检查的路径如 /status
SERVICE_443_CHECK_INTERVAL
15s
15秒检查一次
SERVICE_443_CHECK_TIMEOUT
2s
状态检查超时时间
--- 以下为TCP模式
---
---
SERVICE_443_CHECK_TCP
/path_to_health_check
你的健康状态检查的路径如 /status
SERVICE_443_CHECK_INTERVAL
15s
15秒检查一次
SERVICE_443_CHECK_TIMEOUT
2s
状态检查超时时间
--- 使用脚本检查
---
---
SERVICE_CHECK_SCRIPT
curl --silent --fail example.com
如官方例子中的check_redis.py
-- 其他
---
---
SERVICE_CHECK_INITIAL_STATUS
passing
Consul默认注册后的服务为failed
Consul 与 Nginx集成的几种姿势
目标: 添加 或移除 后端实例时, 不需要运维人员再去手动去修改Nginx.conf文件
DNS
consul-template
nginx-upsync-module
Lua实现
1. DNS模式
如你的应用name=myweb, 再次*强调* 如果id不配置, consu会将name作为默认id, 所以定义服务时id务必要设置
upstream backend {
server myweb.service.consul:20000; #Service Name为myweb, 端口为20000
}
server {
resolver consul_host:8600; # 告诉Nginx DNS解析使用consul的DNS查询
listen 80;
location / {
proxy_pass http://myweb/;
}
}
DNS模式配置简单, 但在运行时会损耗一定性能
2. consul-template
首先consul-template是一个可执行程序, 而不是简单的模板
consul-template的特点
可监听consul的事件, 当已注册service列表或key/value 发生变化时, consul-template会修改配置文件同时可执行一段shell, 如 nginx reload
如下模板文件:
apache {{range services}} upstream {{.Name}} { least_conn;{{range service .Name}} server {{.Address}}:{{.Port}};{{end}} } {{end}}
如下执行consul-template命令
consul-template \
-template "/tmp/nginx.hcl:/var/nginx/nginx.conf:service nginx reload" \
consul-template模式配置相对复杂, 性能相对较好, 仅需要reload nginx, 如果连接量小的话, 不会造成性能影响
3. 使用 nginx-upsync-module
nginx-upsync-module 可以同步consul的服务列表或key/value存储
安装步骤如下, 需要重新编译nginx
wget 'http://nginx.org/download/nginx-1.8.0.tar.gz'
tar -xzvf nginx-1.8.0.tar.gz
cd nginx-1.8.0/
./configure --add-module=/path/to/nginx-upsync-module
make
make install
完成以上步骤后, nginx配置如下
http {
upstream test {
# 先占个位子, 否则nginx在启动时会报错
server 127.0.0.1:11111;
# 所有的后端服务列表会从consul拉取, 并删除上面的占位server
upsync 127.0.0.1:8500/v1/catelog/service/test upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;
# 备份的地址, 保证nginx不强依赖consul
upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf;
}
server {
listen 8080;
location = /proxy_test {
proxy_pass http://test;
}
# 输出目前指定的所有后端服务
location = /upstream_show {
upstream_show;
}
}
}
使用nginx-upsync-module 不需要reload nginx, 所以性能有保障, 同时配置相比consul-template相对简单
4. Lua实现
此方式适合熟悉openresty的同学, 相对nginx-upsync-module, 可以加入更多自己的逻辑, 毕竟lua语法普通程序员学习一两天就可以写, 具体步骤如下:
init_*_by_lua 阶段通过http api 获取服务列表载入Nginx 内存, 并设置timer轮训更新列表
balancer_by_lua 阶段 读取内存的列表, 设置后端服务器
Lua实现 同样可以不reload nginx, 相比nginx-upsync-module 来说更加可扩展, 但缺点就是目前的版本的openresty中init_by_lua 和 init_worker_by_lua只能使用luasocket(阻塞), 不能使用cosocket, 所以在timer轮训时, 会造成一定性能下降
Consul 搭建配置中心
目标: 配置统一管理, 无需运维人员手动修改应用配置
方式: Consul + consul-template
第一步: 将应用配置分类
调用其他服务的URL,如内部短信接口API, 配置为Service列表,这里还需要分两种情况
有API网关(如Nginx), consul-template 应配置为网关service
无API网关, 则需要程序内随机访问service列表
应用自身配置参数, 如七牛key, 每天找回密码限制次数等
利用consul 的key/value 作为存储
第二步: 另外程序本身需要提供一个url, 用来刷新配置
如应用的配置为json文件, 则模板类似如下:
{
sms_url: [
{{range service "myweb"}}
"{{.Address}}: {{ .Port }}",
{{end}}
,
app: {{ key "myweb" }}
}
可利用consul提供的web ui 来管理配置, 可自由控制配置的颗粒度, 可以按需要将整个配置文件作为value或者某个单独的配置项作为value, 如下图:
image.png
参考链接: