简介
在阅读本文前我想您应该对微服务架构有一个基本的或者模糊的了解
Consul 是一个服务管理软件, 它其实有很多组件, 包括服务发现配置共享键值对存储等
本文主要讲解 Consul 的服务注册服务发现以及集群的配置
参考资料:
- https://blog.csdn.net/younger_china/article/details/79462530
- https://www.cnblogs.com/shanyou/p/6286207.html
服务发现
假设有服务 A,B,C. 服务 A 需要调用服务 B 和 C, 传统的方式我们需要在服务 A 中记录服务 B 和 C 的 ip 及端口号. 这些配置一般写在配置文件等地方存储.
这种做法有两个显而易见的缺点: 1. 如果将来 B 的 ip 改变了就需要修改所有调用者的 ip 配置. 2. 难以做负载均衡
而服务发现就是用来解决这个问题的, 怎么解决呢? 请看下面这张图
这张图中在服务消费者和服务生产者之间加了一个服务注册中心的模块, 用上面的服务器 ABC 来举例, 服务 B 在发布的时候会在注册中心注册, 注册中心会记录服务 B 的名字及 ip 地址. 当服务 A 请求服务 B 的时候, 只需要带着服务 B 的名字来注册中心查询即可. 集群情况下, 注册中心会有多个服务 B. 同时注册中心会定期检查每一个服务否可以正常访问, 移除不可访问的服务.(健康检查)
总的来说, 服务发现就是通过一个标志来获取服务列表, 并且服务列表可随着每个服务的上线或下线动态变更
Consul 术语及解释
下面列出几个 consul 中出现频率较高的术语
Agent,Agent 是长期运行在每个 consul 集群成员节点上守护进程. 通过命令 consul agent 启动. Agent 有 client 和 server 两种模式. 由于每个节点都必须运行 agent, 所有节点要么是 client 要么是 server. 所有的 Agent 都可以可以调用 DNS 或 HTTP API, 并负责检查和维护服务同步.
client 运行 client 模式的 Agent, 将所有的 RPCs 转发到 Server.Client 是相对无状态的. Client 唯一所做的是在后台参与 LAN gossip pool. 只消耗少量的资源, 少量的网络带宽.
Server 运行 Server 模式的 Agent, 参与 Raft quorum, 维护集群的状态, 响应 RPC 查询, 与其他数据中心交互 WAN gossip, 转发查询到 Leader 或远程数据中心.
datacenter 数据中心的定义似乎是显而易见的, 有一些细节是必须考虑的. 例如, 在 EC2, 多个可用性区域是否被认为组成了单一的数据中心? 我们定义数据中心是在同一个网络环境中 -- 私有的, 低延迟, 高带宽. 这不包括基于公共互联网环境, 但是对于我们而言, 在同一个 EC2 的多个可用性区域会被认为是一个的数据中心.
关于 client 和 server 我搞了好久才搞明白, 实际上 client 不存储数据, 发送到 client 的请求, client 都会转发给它绑定的 server, 也就是说 client 必须绑定 server.server 会存储数据, 如果只有一个 server 并在上面注册了一个服务, 这个 server 挂了然后你又重启了, 那么这个服务的注册信息仍然保存在 server 上.
如果你在一台服务器上运行了一个 server, 它会默认有一个 client 绑定到 server 上, 并且地址是 127.0.0.1
consul 安装
consul 下载地址: https://www.consul.io/downloads.html
我用的 win10 系统, 所以下载的最后一个 windows64 位的, 下载下来有个 exe 文件, 随便放个到一个文件夹下就可以了.
进入 cmd, 转到 consul 的存放目录, 打命令就可以了.
或者可以把 consul 的目录路径加入到 Path 环境变量中, 就不用每次到目录下打命令了
启动 consul
上面说过, consul 可以以 client 和 server 的方式启动
- Server:consul agent -server -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist -client=0.0.0.0
- Client:consul agent -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist
把 - server 去掉就是 client 模式了
consul agent: 启动 consul 的命令, 要么是 server 要么是 client
-bootstrap-expect: 期望的 server 节点数目, 如果集群中的 server 节点小于这个数据, 集群则失效, 并且该 server 也失效, 一直等到集群中的数目达到相应的数量才生效, 如果是 1 的话, 代表一个 server 就可以了
-data-dir:data 存放的目录, server 会保存一些配置缓存等信息, 存在此目录下
-node: 该节点的名称, 急群众名称必须唯一
-client: 代表该 server 对外暴漏的 client 地址, 0.0.0.0 代表我可以通过: 127.0.0.1 和 192.168.3.233 访问, 不设置的话默认是: 127.0.0.1
-bind: 这是设置集群中 server 之间互相通信的地址, 必须可以互相访问到
-ui-dir: 设置 webui 的界面, 理论上通过命令可以查看到我们需要的任何信息, 但是通过 ui 来查看更直观
搭建集群
我开启了两台虚拟机和本机一共是三台机器, 所以我搭建了三个 server 节点
- Ser1:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node1 -bind=192.168.3.233 -client=0.0.0.0
- Ser2:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node2 -join=192.168.3.233 -bind=192.168.3.201 -client=0.0.0.0
- Ser3: consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node3 -join=192.168.3.233 -bind=192.168.3.243 -client=0.0.0.0
-join: 表示加入到哪个集群内, ser2 中我们指定加入到了 ser1 中, 这时候 ser1 和 ser2 组成了集群, ser3 我们可以指定加入到 ser1 和 ser2, 不管加入哪个最终这三个 server 都组成了一个集群, 最终三个 server 商量了一下选出了一个 leader
服务注册
可以通过命令来注册服务, 因为最终是要在. net core 上使用, 所以我就直接贴上. net core 中的相关代码
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifeTime)
- {
- string ip = Configuration["ip"];
- string port = Configuration["port"];
- string serviceName = "MsgService";
- string serviceId = serviceName + Guid.NewGuid();
- Action<ConsulClientConfiguration> ConsulConfig = (config) =>
- {
- config.Address = new Uri("http://192.168.3.201:8500"); // 服务注册的地址, 集群中任意一个地址
- config.Datacenter = "dc1";
- };
- using (var consulClient = new ConsulClient(ConsulConfig))
- {
- AgentServiceRegistration asr = new AgentServiceRegistration
- {
- Address = ip,
- Port = Convert.ToInt32(port),
- ID = serviceId,
- Name = serviceName,
- Check = new AgentServiceCheck
- {
- DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
- HTTP = $"http://{ip}:{port}/api/Health",// 健康检查访问的地址
- Interval = TimeSpan.FromSeconds(10), // 健康检查的间隔时间
- Timeout = TimeSpan.FromSeconds(5), // 多久代表超时
- },
- };
- consulClient.Agent.ServiceRegister(asr).Wait();
- }
- // 注销 Consul
- appLifeTime.ApplicationStopped.Register(() =>
- {
- using (var consulClient = new ConsulClient(ConsulConfig))
- {
- consulClient.Agent.ServiceDeregister(serviceId).Wait(); // 从 consul 集群中移除服务
- }
- });
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
- app.UseHsts();
- }
- app.UseHttpsRedirection();
- app.UseMvc();
- }
运行程序后向 consul 集群注册了一个服务, 访问集群的任何一个 ip 都可取到该服务的 ip. 客户端查询服务的代码如下:
- static void Main(string[] args)
- {
- using (var consul = new Consul.ConsulClient(c =>
- {
- c.Address = new Uri("http://192.168.3.233:8500"); //Consul 地址
- }))
- {
- var services = consul.Catalog.Service("MsgService").Result.Response;
- foreach (var s1 in services)
- {
- Console.WriteLine($"ID={s1.ServiceID},Service={s1.ServiceName},Addr={s1.Address},Port={s1.ServicePort}");
- }
- }
- }
这样我们一个基本的 consul 集群就可以正常使用了
对于 consul 和服务发现目前还只是刚刚开始接触. 还是有很多问题暂时没有搞明白.
比如客户端连接的 server 突然挂了怎么办如何切换到另一个 server? 以及一个服务下线了如何通知客户端删除缓存等等. 还请大家不吝赐教
来源: https://www.cnblogs.com/bluesummer/p/9415764.html