consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与 发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其 他工具(比如ZooKeeper等)。服务部署简单,只有一个可运行的二进制的包。每个节点都需要 运行agent,他有两种运行模式server和client。每个数据中心官方建议需要3或5个server节点以 保证数据安全,同时保证server-leader的选举能够正确的进行。
类似的工具还有:ZooKeeper,etcd等等。
1 . 2 . 为什么使用服务发现 防止硬编码、容灾、水平扩缩容、提高运维效率等等,只要你想使用服务发现总能找到合适的理由。 一般的说法是因为使用微服务架构。传统的单体架构不够灵活不能很好的适应变化,从而向微服务架构 进行转换。 而伴随着大量服务的出现,管理运维十分不便,于是开始搞一些自动化的策略,服务发现应运而生。所 以如果需要使用服务发现,你应该有一些对服务治理的痛点。 但是引入服务发现就可能引入一些技术栈,增加系统总体的复杂度,如果你只有很少的几个服务,比如 10 个以下,并且业务不怎么变化,吞吐量预计也很稳定,可能就没有必要使用服务发现。
1 . 3 . consul工作原理掌握原理前,需了解下consul的组成结构,即多数据中心
集群中的特性功能:
- 节点角色:leader(领导者)、Follower(跟随者)
- consul节点身份:server、client
- Agent:即节点内包含的一个后台处理程序
- 健康检查:由client的Agent来进行健康检查的功能
首先 Consul 支持多数据中心,在上图中有两个 DataCenter,他们通过 Internet 互联,同时请注意为了 提高通信效率,只有 Server 节点才加入跨数据中心的通信。
在单个数据中心中,Consul 分为 Client 和 Server 两种节点(所有的节点也被称为 Agent),Server 节 点保存数据,Client 负责健康检查及转发数据请求到 Server。
Server 节点有一个 Leader 和多个 Follower,Leader 节点会将数据同步到 Follower,Server 的数量推 荐是 3 个或者 5 个,在 Leader 挂掉的时候会启动选举机制产生一个新的 Leader。
集群内的 Consul 节点通过 gossip 协议(流言协议)维护成员关系,也就是说某个节点了解集群内现在 还有哪些节点,这些节点是 Client 还是 Server。
单个数据中心的流言协议同时使用 TCP 和 UDP 通信,并且都使用 8301 端口。跨数据中心的流言协议 也同时使用 TCP 和 UDP 通信,端口使用 8302。
集群内数据的读写请求既可以直接发到 Server,也可以通过 Client 使用 RPC 转发到 Server,请求最终 会到达 Leader 节点。
在允许数据轻微陈旧的情况下,读请求也可以在普通的 Server 节点完成,集群内数据的读写和复制都是 通过 TCP 的 8300 端口完成。
2 . consul服务发现原理 首先需要有一个正常的 Consul 集群,有 Server,有 Leader。这里在服务器 Server1、Server2、 Server3 上分别部署了 Consul Server。
假设他们选举了 Server2 上的 Consul Server 节点为 Leader。这些服务器上最好只部署 Consul 程序, 以尽量维护 Consul Server 的稳定。
然后在服务器 Server4 和 Server5 上通过 Consul Client 分别注册 Service A、B、C,这里每个 Service 分别部署在了两个服务器上,这样可以避免 Service 的单点问题。
服务注册到 Consul 可以通过 HTTP API(8500 端口)的方式,也可以通过 Consul 配置文件的方式。
Consul Client 可以认为是无状态的,它将注册信息通过 RPC 转发到 Consul Server,服务信息保存在 Server 的各个节点中,并且通过 Raft 实现了强一致性。
最后在服务器 Server6 中 Program D 需要访问 Service B,这时候 Program D 首先访问本机 Consul Client 提供的 HTTP API,本机 Client 会将请求转发到 Consul Server。
Consul Server 查询到 Service B 当前的信息返回,最终 Program D 拿到了 Service B 的所有部署的 IP 和端口,然后就可以选择 Service B 的其中一个部署并向其发起请求了。
如果服务发现采用的是 DNS 方式,则 Program D 中直接使用 Service B 的服务发现域名,域名解析请 求首先到达本机 DNS 代理,然后转发到本机 Consul Client,本机 Client 会将请求转发到 Consul Server。
Consul Server 查询到 Service B 当前的信息返回,最终 Program D 拿到了 Service B 的某个部署的 IP 和端口。
3 . consul集群 4 . consul集群搭建服务器ip | consul类型 | Node(节点名称) |
---|---|---|
192.168.48.128 | server | consul_server_1 |
192.168.48.129 | server | consul_server_2 |
192.168.48.132 | server | consul_server_3 |
192.168.48.134 | client | consul_client_4 |
docker pull consul:1.4.4
2 . 创建第一台consul_server_1,设置为leader
docker run -d -p 8500:8500 \
-v /docker/consul/data/server1:/docker/consul/data \
-v /docker/consul/conf/server1:/docker/consul/conf \
-h=node1 --net=host \
-e CONSUL_BIND_INTERFACE=ens33 \
--privileged=true \
--name consul_server_1 \
consul:1.4.4 agent \
-bind=192.168.48.128 \
-server=true -bootstrap-expect=3 -ui \
-node=consul_server_1 -client='0.0.0.0' \
-datacenter=xdp_dc \
-data-dir /docker/consul/data/ \
-config-dir /docker/consul/conf/
3 . 创建第二台consul_server_2,设置为跟随者
docker run -d -p 8500:8500 \
-v /docker/consul/data/server2:/docker/consul/data \
-v /docker/consul/conf/server2:/docker/consul/conf \
-h=node2 --net=host \
-e CONSUL_BIND_INTERFACE=ens33 \
--privileged=true \
--name consul_server_2 \
consul:1.4.4 agent \
-bind=192.168.48.129 \
-server=true -ui \
-node=consul_server_2 -client='0.0.0.0' \
-datacenter=xdp_dc \
-data-dir /docker/consul/data/ \
-config-dir /docker/consul/conf/ \
-join 192.168.48.128
4 . 创建第三台consul_server_3,设置为跟随者
docker run -d -p 8500:8500 \
-v /docker/consul/data/server3:/docker/consul/data \
-v /docker/consul/conf/server3:/docker/consul/conf \
-h=node3 --net=host \
-e CONSUL_BIND_INTERFACE=ens33 \
--privileged=true \
--name consul_server_3 \
consul:1.4.4 agent \
-bind=192.168.48.132 \
-server=true -ui \
-node=consul_server_3 -client='0.0.0.0' \
-datacenter=xdp_dc \
-data-dir /docker/consul/data/ \
-config-dir /docker/consul/conf/ \
-join 192.168.48.128
5 . 设置为客户端consul_client_4
docker run -d -p 8500:8500 \
-v /docker/consul/conf/client4:/docker/consul/conf \
-e CONSUL_BIND_INTERFACE=ens33 \
--name consul_client_4 -h=node4 --net=host \
--privileged=true consul:1.4.4 agent \
-node=consul_client_4 -config-dir=/docker/consul/conf \
-server=false -client=0.0.0.0 -datacenter=xdp_dc -join=192.168.48.128 -ui
6 . 查看投票状态
docker exec -it consul_name consul operator raft list-peers
7 . 查看集群成员
docker exec -it consul_name consul members
8 . 注意事项:关闭防火墙
systemctl status firewalld
systemctl stop firewalld
9 . 验证
http://192.168.48.128:8500/ui/xdp_dc/services/consul
这些 Consul 节点在 Docker 的容器内是互通的,他们通过桥接的模式通信。但是如果主机要访问容器内 的网络,需要做端口映射。
在启动容器时,将 Consul 的 8500 端口映射到了主机的 8500 端口,这样就可以方便的通过主机的浏览 器查看集群信息。
5 . Consul Client实例创建 1 . 创建services.json配置文件向Consul注册user,product API服务 (使用的时候去掉注释)
{
"services": [
{
//在192.168.48.129服务中创建一个user的tcp服务,端口为9501
"id": "core.user-/192.168.48.129:9501",
//consul服务名称
"name": "core.user",
//标签名称
"tags": [ "xdp-/core.user" ],
//绑定地址
"address": "192.168.48.129",
//绑定端口
"port": 9501,
//健康监测
"checks": [
{
//监测名称:自定义
"name": "core.user.check",
//监测地址,(这里区分tcp和http的类型)
//"http": "http://192.168.48.129:9501",
"tcp": "192.168.48.129:9501",
//心跳健康检测频率
"interval": "10s",
//检测超时时间
"timeout": "5s"
}
]
},
{
//在192.168.48.129服务中创建一个product的tcp服务,端口为9502
"id": "core.product-/192.168.48.129:9502",
"name": "core.product",
"tags": [ "xdp-/core.product" ],
"address": "192.168.48.129",
"port": 9502,
"checks": [
{
"name": "core.product.check",
"tcp": "192.168.48.129:9502",
"interval": "10s",
"timeout": "5s"
}
]
}
]
}
2 . 创建TCP服务
在192.168.48.129服务中分别创建user,product的tcp服务,端口分别为9501,9502
user.conf , product.conf (配置相同的功能)
server {
#监听端口
listen 9501;
proxy_connect_timeout 10s;
#设置客户端和代理服务之间的超时时间,如果5分钟内没 *** 作将自动断开。
proxy_timeout 300s;
proxy_pass cloudsocket;
}
upstream cloudsocket {
hash $remote_addr consistent;
server 172.17.0.3:9501 weight=5 max_fails=3 fail_timeout=30s;
}
创建tcp服务
UserService.php , ProductService.php (配置相同的功能)
//创建Server对象,监听 127.0.0.1:9501 端口
$server = new Swoole\Server('0.0.0.0', 9502);
//监听连接进入事件
$server->on('Connect', function ($server, $fd) {
echo "Hello: Product.\n";
});
//监听数据接收事件
$server->on('Receive', function ($server, $fd, $reactor_id, $data) {
$server->send($fd, "Server: {$data}");
});
//监听连接关闭事件
$server->on('Close', function ($server, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$server->start();
3 . 启动consul服务
将 services.json 文件 分别放到四个 sonsul 服务器 本地映射 /docker/consul/conf/ 下的 server1,server2 ,server3 , client4的目录中,测试结果如下
4 . 测试请求服务注册成功以后,调用方获取相应服务地址的过程就是服务发现。Consul 提供了多种方式。
HTTP API 方式
容器内:
curl http://127.0.0.1:8500/v1/health/service/core.user?passing=true
容器外:
http://192.168.48.128:8500/v1/health/service/core.user?passing=true
返回的信息包括注册的 Consul 节点信息、服务信息及服务的健康检查信息。
- passing=true //过滤不健康节点
- passing=false //不过滤
如果服务有多个部署,会返回服务的多条信息,调用方需要决定使用哪个部署,常见的可以随机或者轮 询。
为了提高服务吞吐量,以及减轻 Consul 的压力,还可以缓存获取到的服务节点信息,不过要做好容错 的方案,因为缓存服务部署可能会变得不可用。具体是否缓存需要结合自己的访问量及容错规则来确 定。
上边的参数 passing 默认为 false,也就是说不健康的节点也会返回,结合获取节点全部服务的方法,这 里可以做到获取全部服务的实时健康状态,并对不健康的服务进行报警处理。
6 . Consul的API *** 作: 6 . 1 . 本地请求:基于 Agent请求例子:
http://192.168.48.134:8500/v1/agnect/services
/v1/agent/checks --获取本地agent注册的所有检查(包括配置文件和http注册)
/v1/agent/services --获取本地agent注册的所有服务
/v1/agent/members --获取集群中的成员
/v1/agent/self --获取本地agent的配置和成员信息
/v1/agent/join/<address> --触发本地agent加入node
/vq/agent/force-leave/<node> --强制删除node
/v1/agent/check/register --在本地agent增加一个检查项,使用PUT
方法传输一个json格式的数据
/v1/agent/check/deregister/<checkID> --注销一个本地agent的检查项
/v1/agent/check/pass/<checkID> --设置一个本地检查项的状态为passing
/v1/agent/check/warn/<checkID> --设置一个本地检查项的状态为warning
/v1/agent/check/fail<checkID> --设置一个本地检查项的状态为critical
/v1/agent/service/deregister/<serviceID> --注销一个本地agent的服务项
/v1/agent/service/register --在本地agent增加一个新的服务项,使用PUT方法传输一个json格式的数据
6 . 2 . 数据中心请求:基于 catalog 类型
/v1/catalog/register --注册一个新的service、node、check
/v1/catalog/deregister --注销一个service、node、check
/v1/catalog/datacenters --列出知道的数据中心
/v1/catalog/nodes --在给定的数据中心列出node
/v1/catalog/services --在给定的数据中心列出service
/v1/catalog/service/<service> --查看某个服务的信息
/v1/catalog/node/<node>
6 . 3 . 注册服务:(注意,需要请求consul_client的服务进行注册)
注:consul中注册服务与编辑服务的信息都是相同的接口
method: PUT
http://192.168.48.134:8500/v1/agent/service/register
{
"id": "core.order-/192.168.48.129:9503",
"name": "core.order",
"tags": [ "xdp-/core.order" ],
"address": "192.168.48.129",
"port": 9503,
"checks": [
{
"name": "core.order.check",
//"http": "http://192.168.48.129:9503",
"tcp": "192.168.48.129:9503",
"interval": "10s",
"timeout": "5s"
}
]
}
6 . 4 . 查询服务:
6 . 4 . 1 本地请求(Agent)
HTTP-API请求:查询本地节点下所有的注册服务
method: GET
http://192.168.48.134:8500/v1/agent/services
HTTP-API请求:查询指定本地节点下的服务
语法:/v1/agent/service/{serviceID}
method: GET
http://192.168.48.134:8500/v1/agent/service/core.user-/192.168.48.129:9501
单机性能压测如下
测试的机器性能比较差,也能如此并发,因此实际开发过程中,接口调用consul获取服务配置信息,不用担心性能与并发的问题,也无需做redis数据缓存(也可以缓存起来),只管调用即可。
6 . 4 . 2 数据中心(catalog)的查询方式:/v1/catalog/services --在给定的数据中心列出service
/v1/catalog/service/ --查看某个服务的信息
HTTP-API:查询当前数据中心下的注册的服务
method:GET
http://192.168.48.134:8500/v1/catalog/services
HTTP-API:查询指定本地节点下的服务
语法:/v1/catalog/service/{name}
method:GET
http://192.168.48.134:8500/v1/catalog/service/core.user
6 .5 删除服务:
注销任意节点和服务:/v1/catalog/deregister
注销当前节点的服务:/v1/agent/service/deregister/{serviceID}
method: PUT
http://192.168.48.134:8500/v1/agent/service/deregister/core.order-/192.168.48.129:9503
注意:如果注销的服务还在运行,则会再次同步到 catalog 中,因此应该只在 Agent 不可用时才使用 catalog 的注销 API。
节点在宕机时状态会变为 failed,默认情况下 72 小时后会被从集群移除。
停止代理:
如果某个节点不继续使用了,也可以在本机使用 consul leave 命令。
或者在其他节点使用 consul force-leave 故障节点 id,则节点上的服务和健康检查全部注销。
7 . Consul 集群之负载均衡创建三台consul服务器,端口分别为 8510,8520,8530。
可以通过Nginx建了一个 TCP 负载均衡入口,即通过 8500 访问到 8510、8520、8530 三台consul服务器中。
server {
listen 8500;
location / {
proxy_pass http://xdpconsul;
proxy_redirect default;
}
}
upstream xdpconsul {
server 127.0.0.1:8510 weight=2;
server 127.0.0.1:8520 weight=1;
server 127.0.0.1:8530 weight=1;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)