.NET Core + Consul 服务注册与发现

Consul

Consul:服务治理、配置中心
Polly:服务熔断
Ocelot:API网关

简介

Consul是一个用来实现分布式系统服务发现与配置的开源工具。内置了服务注册与发现框架、分布式一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。

Consul架构

在这里插入图片描述

Consul集群支持多数据中心,在上图中有两个DataCenter,通过Internet互联,为了提高通信效率,只有Server节点才能加入跨数据中心的通信。在单个数据中心中,Consul分为ClientServer两个节点(所有的节点也被称为Agent),Server节点保存数据,Client负责健康检查及转发数据请求到Server,本身不保存注册信息;Server节点有一个Leader和多个FollowerLeader节点会将数据同步到FollowerServer节点的数量推荐是3个或者5个,在Leader挂掉的时候会启动选举机制产生一个新Leader

Consul集群搭建

这里使用 Docker 搭建 3个 Server 节点 + 1 个 Client 节点,API 服务通过 Client 节点进行服务注册和发现。

从 Docker Hub 拉取 Consul 镜像
docker pull consul
启动 3个 Server 节点 + 1 个 Client 节点
// Server  节点 1
docker run --name cs1 -p 8500:8500  -v /data/cs1:/data consul agent -server -bind 172.17.0.2 -node consul-server-1  -data-dir /data -bootstrap-expect 3 -client 0.0.0.0 -ui
// Server  节点 2
docker run --name cs2 -p 7500:8500  -v /data/cs2:/data consul agent -server -bind 172.17.0.3 -node consul-server-2  -data-dir /data -bootstrap-expect 3 -client 0.0.0.0 -ui -join 172.17.0.2
// Server  节点 3
docker run --name cs3 -p 6500:8500 -v /data/cs3:/data consul agent -server -bind 172.17.0.4 -node consul-server-3  -data-dir /data -bootstrap-expect 3 -client 0.0.0.0 -ui -join 172.17.0.2
// Client 节点 1
docker run --name cc1 -p 5500:8500 -v /data/cc1:/data consul agent -bind 172.17.0.5 -node consul-client-1 -data-dir /data -client 0.0.0.0 -ui -join 172.17.0.2

参数说明(–name、-p、-v 为 Docker 相关参数):

参数名解释
–nameDocker 容器名称(每个 Consul 节点一个容器)
-p容器内部 8500 端口映射到当前主机端口,因为使用的同一台主机,所以这里每个容器内的 8500 端口映射到当前主机的不同端口
-v将节点相关注册数据挂载到当前主机的指定位置,否则重启后会丢失
-server设置为 Server 类型节点,不加则为 Client 类型节点
-bind指定节点绑定的地址
-node指定节点名称
-data-dir数据存放位置
-bootstrap-expect集群期望的 Server 节点数,只有达到这个值才会选举 Leader
-client注册或者查询等一系列客户端对它操作的IP,默认是127.0.0.1
-ui启用 UI 界面
-join指定要加入的节点地址(组建集群)
集群状态

cs1 为容器名称,任意一个即可

查看节点状态和类型
docker exec -t cs1 consul members


当前为3 个 Server 类型节点 ,1 个 Client 类型节点。

查看 Server 节点类型
docker exec -t cs1 consul operator raft list-peers

在这里插入图片描述

当前为 consul-server-1leader,可以测试将 consul-server-1 kill 观察 leader 的重新选举。

通过 http://192.168.124.8:8500 UI 界面查看 Consul 节点状态如下:
:7500、:6500、:5500均可,192.168.124.8 是当前主机网络的 IPv4 地址

在这里插入图片描述

.NET Core 接入Consul

service discovery

  1. 创建 .NET Core WebAPI 服务 ServiceA(2个实例) 和 ServiceB

  2. NuGet 安装 Consul

  3. 注册到 Consul 的核心代码如下(源码下载):

   public static class ConsulBuilderExtensions
   {
     public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, ConsulOption consulOption)
     {
       var consulClient = new ConsulClient(x =>
       {
         // consul 服务地址
         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;
     }
   }
  1. 添加配置如下:
   "ServiceName": "ServiceA",
   "ServiceIP": "192.168.124.8",
   "ServicePort": 8000,
   "ServiceHealthCheck": "http://192.168.124.8:8000/healthCheck",
   "ConsulAddress": "http://192.168.124.8:8500"
  1. 注册成功结果如下:
    service register
  2. ServiceB 调用 ServiceA 接口

ServiceB 通过 ConsulClient 进行服务发现,获取到 ServiceA 的地址,然后随机任意一台进行请求,核心代码如下:

   var url = _configuration["ConsulAddress"].ToString();
   
   using (var consulClient = new ConsulClient(a => a.Address = new Uri(url)))
   {
     var services = consulClient.Catalog.Service("ServiceA").Result.Response;
     if (services != null && services.Any())
     {
       // 模拟随机一台进行请求,这里只是测试,可以选择合适的负载均衡工具或框架
       Random r = new Random();
       int index = r.Next(services.Count());
       var service = services.ElementAt(index);
   
       using (HttpClient client = new HttpClient())
       {
         var response = await client.GetAsync($"http://{service.ServiceAddress}:{service.ServicePort}/values/test");
         var result = await response.Content.ReadAsStringAsync();
         return result;
       }
     }
   }
  1. 多次调用 ServiceB 接口结果如下:
    在这里插入图片描述
    result-2
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值