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

Consul 介绍

在分布式架构中,服务治理是必须面对的问题,如果缺乏简单有效治理方案,各服务之间只能通过人肉配置的方式进行服务关系管理,当遇到服务关系变化时,就会变得极其麻烦且容易出错。

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

Consul 架构

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

Consul 集群搭建

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

从 Docker Hub 拉取 Consul 镜像

docker pull consul

启动 3个 Server 节点 + 1 个 Client 节点

docker-compose.yaml 如下:

version: '3'

services:
  cs1: 
    image: consul
    command: agent -server -client=0.0.0.0 -bootstrap-expect=3 -node=cs1 -data-dir=/data
    volumes:
      - /usr/local/docker/consul/data/cs1:/data
  cs2:
    image: consul
    command: agent -server -client=0.0.0.0 -retry-join=cs1 -node=cs2 -data-dir=/data
    volumes:
      - /usr/local/docker/consul/data/cs2:/data
    depends_on:
      - cs1
  cs3:
    image: consul
    command: agent -server -client=0.0.0.0 -retry-join=cs1 -node=cs3 -data-dir=/data
    volumes:
      - /usr/local/docker/consul/data/cs3:/data
    depends_on:
      - cs1
  cc1:
    image: consul
    command: agent -client=0.0.0.0 -retry-join=cs1 -ui -node=cc1 -data-dir=/data  
    ports:
      - 8500:8500
    volumes:
      - /usr/local/docker/consul/data/cc1:/data
    depends_on:
      - cs2
      - cs3

主要参数说明:

参数名 解释
-server 设置为 Server 类型节点,不加则为 Client 类型节点
-client 注册或者查询等一系列客户端对它操作的IP,默认是127.0.0.1
-bootstrap-expect 集群期望的 Server 节点数,只有达到这个值才会选举 Leader
-node 指定节点名称
-data-dir 数据存放位置
-retry-join 指定要加入的节点地址(组建集群)
-ui 启用 UI 界面

集群状态

e002ca62ac24 为容器名称,可通过 docker ps | grep consul 查看,选择任意一个即可

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

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

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

当前为 cs1 为 leader,可以测试将 cs1 stop 观察 leader 的重新选举。

通过 http://192.168.124.9:8500 UI 界面查看 Consul 节点状态如下:(192.168.124.9 是 consul 容器外部访问 IP)

.NET Core 接入 Consul

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

  2. NuGet 安装 Consul

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

    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;
      }
    }
    
  4. 添加配置如下:

    "Consul": {
      "ServiceName": "service-a",
      "ServiceIP": "192.168.124.11",   // 当前服务访问 IP
      "ServicePort": 8000,
      "ServiceHealthCheck": "http://192.168.124.11:8000/healthCheck",
      "Address": "http://192.168.124.9:8500"
    }
    
  5. 注册成功结果如下:

  6. ServiceB 调用 ServiceA 接口

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

    using (var consulClient = new ConsulClient(a => a.Address = new Uri(_consulOption.Address)))
    {
      var services = consulClient.Catalog.Service("service-a").Result.Response;
      if (services != null && services.Any())
      {
        // 模拟随机一台进行请求,这里只是测试,可以选择合适的负载均衡框架
        var service = services.ElementAt(new Random().Next(services.Count()));
    
        var client = _httpClientFactory.CreateClient();
        var response = await client.GetAsync($"http://{service.ServiceAddress}:{service.ServicePort}/test/get");
        var result = await response.Content.ReadAsStringAsync();
        return result;
      }
    }
    
  7. 多次调用结果如下:

参考链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容