Consul之服务注册
前言
在分布式架构中,服务治理是必须面对的问题,如果缺乏简单有效治理方案,各服务之间只能通过人肉配置的方式进行服务关系管理,当遇到服务关系变化时,就会变得极其麻烦且容易出错。
Consul 是一个用来实现分布式系统服务发现与配置的开源工具。
环境:Win10 +VS2022 +.NET5.0 + Consul 1.6.1.1
1 Consul简介
Consul内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper 等),使用起来也较为简单。由 HashiCorp 公司用 Go 语言开发。
地址:https://www.consul.io/
Consul的下载:
https://www.consul.io/downloads.html
2 Consul 架构
Consul 集群支持多数据中心。在单个数据中心中,Consul 分为 Client 和 Server 两种节点(所有的节点也被称为 Agent),Server 节点保存数据,Client 负责健康检查及转发数据请求到 Server,本身不保存注册信息;Server 节点有一个 Leader 和多个 Follower,Leader 节点会将数据同步到 Follower,Server 节点的数量推荐是3个或者5个,在 Leader 挂掉的时候会启动选举机制产生一个新 Leader。
下面这张图来源于Consul官网,很好的解释了Consul的工作原理,先大致看一下。
3 Consul 集群搭建
这里使用 Docker 搭建 3个 Server 节点 + 1 个 Client 节点,API 服务通过 Client 节点进行服务注册和发现。
从 Docker Hub 拉取 Consul 镜像
docker pull consul |
启动4个Consul Agent,3个Server(会选举出一个leader),1个Client。
#启动第1个Server节点,集群要求要有3个Server,将容器8500端口映射到主机8900端口,同时开启管理界面 docker run -d --name=consul1 -p 8900:8500 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --bootstrap-expect=3 --client=0.0.0.0 -ui
#启动第2个Server节点,并加入集群 docker run -d --name=consul2 -e CONSUL_BIND_INTERFACE=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 |
查看节点状态和类型
docker exec -t cs1 consul members |
当前为3 个 Server 类型节点 ,1 个 Client 类型节点。
查看 Server 节点类型
docker exec -t cs1 consul operator raft list-peers
|
第1个启动容器的IP一般是172.17.0.2,后边启动的几个容器IP会排着来:172.17.0.3、172.17.0.4、172.17.0.5。
这些Consul节点在Docker的容器内是互通的,他们通过桥接的模式通信。但是如果主机要访问容器内的网络,需要做端口映射。在启动第一个容器时,将Consul的8500端口映射到了主机的8900端口,这样就可以方便的通过主机的浏览器查看集群信息。
输入exit可以跳出容器。
进入容器consul1:
docker exec -it consul1 /bin/sh #执行ls后可以看到consul就在根目录ls
|
4 项目实现
4.1 新建WebAPI服务项目
新建一个WebAPI接口,命名为“Yak.Ocelot.Api”,修改启动端口为“6000”。
"Yak.Ocelot.Api": { "commandName": "Project", "dotnetRunMessages": "true", "launchBrowser": true, "launchUrl": "weatherforecast", "applicationUrl": "http://localhost:6000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } |
4.2 添加Consul依赖
添加Consul依赖后,Yak.Ocelot.Api.csproj项目文件下添加了下面代码。
<ItemGroup> <PackageReference Include="Consul" Version="1.6.1.1" /> </ItemGroup> |
4.3 添加健康检查接口
添加Health控制器,代码:
[Route("[controller]/[action]")] [ApiController] public class HealthController : ControllerBase { [HttpGet("/healthCheck")] public IActionResult Check() => Ok("ok"); } |
4.4 把服务注册到Consul
- 项目中添加Consul 注册发现相关参数类ConsulOption。
/// <summary> /// Consul 注册发现相关参数 /// </summary> public class ConsulOption { /// <summary> /// 服务名称 /// </summary> public string ServiceName { get; set; }
/// <summary> /// 服务IP /// </summary> public string ServiceIP { get; set; }
/// <summary> /// 服务端口 /// </summary> public int ServicePort { get; set; }
/// <summary> /// 服务健康检查地址 /// </summary> public string ServiceHealthCheck { get; set; }
/// <summary> /// Consul 地址 /// </summary> public string Address { get; set; } } |
- 添加Consul注册发现扩展类ConsulBuilderExtensions。
public static class ConsulBuilderExtensions { public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption) { var consulClient = new ConsulClient(x => { x.Address = new Uri(consulOption.Address); });
var registration = new AgentServiceRegistration() { ID = Guid.NewGuid().ToString(), Name = consulOption.ServiceName,// 服务名 Address = consulOption.ServiceIP, // 服务绑定IP Port = consulOption.ServicePort, // 服务绑定端口 Check = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔 HTTP = consulOption.ServiceHealthCheck,//健康检查地址 Timeout = TimeSpan.FromSeconds(5) } };
// 服务注册 consulClient.Agent.ServiceRegister(registration).Wait();
// 应用程序终止时,服务取消注册 lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); }); return app; } } |
- 添加Consul配置,修改appsettings.json文件。
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Consul": { "ServiceName": "service-a", "ServiceIP": "127.0.0.1", "ServicePort": 6000, "ServiceHealthCheck": "http://192.168.142.1:6000/healthCheck", "Address": "http://127.0.0.1:8500" } } |
- 修改Startup。
public void ConfigureServices(IServiceCollection services) { services.AddSingleton(Configuration.GetSection("Consul").Get<ConsulOption>()); services.AddControllers(); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ConsulOption consulOption) { ......... // 注册 app.RegisterConsul(lifetime, consulOption); ........... } |
4.5 启动Consul
这里是Win10系统,下载相应的Consul后,在文件夹下创建启动BAT文件用于启动Consul,双击启动。
浏览器中输入:http://localhost:8500/
BAT文件:
consul agent -dev |
4.6 服务发现
启动项目,查看到服务已经注册到Consul中。
5 总结
通过这节我们学习了Consul及怎样把服务注册到Consul中,下节中介绍结合Ocelot发现服务,访问服务。
6 鸣谢
https://www.cnblogs.com/bossma/p/9756809.html
https://www.cnblogs.com/edisonchou/p/9124985.html
7 源码
https://github.com/yandaniugithub/Yak.Ocelot.Demo.git