乐趣区

关于注册中心:Consul的基本使用与集群搭建

@[toc]

一、注册核心的概念

  • 概念
    可能注册微服务地址【ip: 端口】的组件就是注册核心。
    如图:
  • 目标
    保障微服务的动静伸缩性。

    二、注册核心的应用场景

  • 场景
    次要场景是在微服务中应用。
    如图:
  • 三、注册核心的技术选型

  • 类型

    • zookeeper
    • consul
    • etcd
    • eureka
  • 特点
    | Feature | Consul | zookeeper | etcd | euerka |
    | — | — | — | — | — |
    | 服务健康检查 | 服务状态,内存,硬盘等 | (弱)长连贯,keepalive | 连贯心跳 | 可配反对 |
    | 多数据中心 | 反对 | – | – | – |
    | kv 存储服务 | 反对 | 反对 | 反对 | – |
    | 一致性 | raft | paxos | raft | – |
    | cap | ca | cp | cp | ap |
    | 应用接口(多语言能力) | 反对 http 和 dns | 客户端 | http/grpc | http(sidecar)|
    | watch 反对 | 全量 / 反对 long polling | 反对 | 反对 long polling | polling 反对 long polling/ 大部分增量 |
    | 本身监控 | metrics | – | metrics | metrics |
    | 平安 | acl /https | acl | https 反对(弱)| – |
    | spring cloud 集成 | 反对 | 反对 | 反对 | 反对 |
  • Consul 的三个概念

    • server:存储微服务地址【ip:端口】
    • client:连贯 Consul
    • agent:后盾服务
  • 利用架构集成原理
    如图:

四、注册核心的我的项目落地

  • 工具

    • Consul
      网盘下载地址:
      链接:https://pan.baidu.com/s/1zN4P…
      提取码:lnk7
    • demo 我的项目
  • 步骤

    • Consul 运行命令

       # 在根目录下启动运行 
        consul.exe agent -dev   #在开发模式下启动命令
        consul agent -server -bootstrap-expect [节点数据量]  -data-dir d:/consul/data  [数据存储地址]

      运行后果如下:

    • demo 我的项目

      • nuget 装置

          Consul
      • appsettings.json 增加配置信息

          {
            ......
            "ConsulRegistry": {
              "Name": "testService",
              "RegistryAddress": "http://127.0.0.1:8500",
              "HealthCheckAddress": "/HealthCheck"
            }
          } 
      • 新增配置实体类,通过 json 文件映射到实体配置类

          public class ServiceRegistryConfig
          {
              /// <summary>
              /// 服务 ID
              /// </summary>
              public string Id {get;set;}
              /// <summary>
              /// 服务名称
              /// </summary>
              public string Name {get;set;}   
              /// <summary>
              /// 服务标签
              /// </summary>
              public string[] Tags { get; set;}
              /// <summary>
              /// 服务地址
              /// </summary>
              public string Address {get; set;}
              /// <summary>
              /// 服务端口号
              /// </summary>
              public int Port {get; set;}
              /// <summary>
              /// 服务注册地址
              /// </summary>
              public string RegistryAddress {get; set;}
              /// <summary>
              /// 服务健康检查地址
              /// </summary>
              public string HealthCheckAddress {get; set;} 
            }
      • 微服务注册

        • 创立服务注册实现类

             public class ServiceRegistry : IServiceRegistry
              {public void Register(ServiceRegistryConfig serviceRegistryConfig)
                  {
                      //1 建设 consul 客户端的连贯
                      var consulClient = new ConsulClient(configuration =>
                      {configuration.Address = new Uri(serviceRegistryConfig.RegistryAddress);
                      });
                      //2 创立 consul 服务注册对象
                      var registration = new AgentServiceRegistration()
                      {
                          ID = serviceRegistryConfig.Id,
                          Name = serviceRegistryConfig.Name,
                          Address = serviceRegistryConfig.Address,
                          Port = serviceRegistryConfig.Port,
                          Tags = serviceRegistryConfig.Tags,
                          // 健康检查
                          Check = new AgentServiceCheck()
                          {
                              // 设置健康检查超时工夫
                              Timeout = TimeSpan.FromSeconds(10),
                              // 服务进行 5 秒后登记服务
                              DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(50),
                              // 健康检查地址
                              HTTP = serviceRegistryConfig.HealthCheckAddress,
                              // 健康检查间隔时间
                              Interval = TimeSpan.FromSeconds(10)
                          }
                      };
                      // 服务注册
                      consulClient.Agent.ServiceRegister(registration);
                      // 敞开连贯开释资源
                      consulClient.Dispose();}
                   /// <summary>
                   /// 注册核心登记
                   /// </summary>
                   /// <param name="serviceRegistryConfig"></param>
                  public void Deregister(ServiceRegistryConfig serviceRegistryConfig) 
                  {
                   var consulClient = new ConsulClient(configuration => {configuration.Address = new Uri(serviceRegistryConfig.Address);
                   });
                      consulClient.Agent.ServiceDeregister(serviceRegistryConfig.Id);
                  }
              }
        • 创立服务注册看接口类

              public interface IServiceRegistry
              {void Register(ServiceRegistryConfig serviceRegistryConfig);
                  void Deregister(ServiceRegistryConfig serviceRegistryConfig);
              }
        • 创立服务注册扩大类

          //consul 服务注册类
              public static class ConsulExtensions
              {
                 /// <summary>
                 /// 注册核心扩大
                 /// </summary>
                 /// <param name="services"></param>
                 /// <param name="Configuration"></param>
                 /// <returns></returns>
                  public static IServiceCollection AddConsul(this IServiceCollection services, IConfiguration Configuration) 
                  {
                      // 将 json 文件映射到实体类
                      services.Configure<ServiceRegistryConfig>(Configuration.GetSection("ConsulRegistry"));
                      services.AddSingleton<IServiceRegistry, ServiceRegistry>();
                      return services; 
                  }
              }
             // 服务启动时注册服务
             public static class ConsulApplicationBuilderExtension
              {public static IApplicationBuilder UseConsulRegistry(this IApplicationBuilder app)
                  {
                      // 获取配置信息
                      var serviceNode = app.ApplicationServices.GetRequiredService<IOptions<ServiceRegistryConfig>>().Value;
                      // 获取生命周期
                      var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
                      // 获取服务注册实力
                      var consulRegistry = app.ApplicationServices.GetRequiredService<IServiceRegistry>();
                      // 获取服务地址信息
                      var features = app.Properties["server.Features"] as FeatureCollection;
                      var address = features.Get<IServerAddressesFeature>().Addresses.First();
                      var uri = new Uri(address);
                      // 服务注册
                      serviceNode.Id = Guid.NewGuid().ToString();
                      serviceNode.Address = $"{uri.Scheme}://{uri.Host}";
                      serviceNode.Port = uri.Port;
                      serviceNode.HealthCheckAddress = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceNode.HealthCheckAddress}";
                      consulRegistry.Register(serviceNode);
                      // 服务器敞开时登记服务
                      lifetime.ApplicationStopping.Register(() => {consulRegistry.Deregister(serviceNode);
                      });
                      return app;
                  }
              }
           // 在 startup 类中 ConfigureServices 办法中注册服务 
              services.AddConsul(Configuration);
           // 在 startup 类中 Configure 办法启动服务
              app.UseConsulRegistry();

          运行后果如下:

      • 微服务发现

        • 在 appsettings.json 文件中新增 Consul 注册地址配置

               ......
                  "ConsulDiscoverys": {"RegistryAddress": "http://127.0.0.1:8500"}
              .....
        • 新建配置类

               public class ServiceDiscoveryConfig
              {public string RegistryAddress { get; set;}
              }
        • 新增服务发现接口类

               public interface IConsulDiscovery
              {Task<List<ServiceUrl>> Discovery(string  ServiceName);
              }  
        • 新增服务发现实现类

              public class ConsulDiscovery : IConsulDiscovery
              {
                  private readonly IConfiguration Configuration;
                  public ConsulDiscovery(IConfiguration _Configuration) {Configuration = _Configuration;}
                  /// <summary>
                  /// 服务发现 
                  /// </summary>
                  /// <param name="ServiceName"> 服务名称 </param>
                  /// <returns> 返回一个汇合 </returns>
                  public async Task<List<ServiceUrl>> Discovery(string ServiceName)
                  {List<ServiceUrl> list = new List<ServiceUrl>();
                      ServiceDiscoveryConfig serviceDiscoveryConfig = new ServiceDiscoveryConfig();
                      serviceDiscoveryConfig = Configuration.GetSection("ConsulDiscoverys").Get< ServiceDiscoveryConfig >();
                      //1 建设连贯
                      var consulClient = new ConsulClient(Options => {Options.Address = new Uri(serviceDiscoveryConfig.RegistryAddress);
                      });
                      // 2 依据服务名称获取注册的服务地址
                      var queryResult = await  consulClient.Catalog.Service("ServiceName");
                      // 3 将注册的地址注入汇合中
                      foreach (var item in queryResult.Response)
                      {list.Add(new ServiceUrl() {Url = item.Address+":"+ item.ServicePort});
                      }
                      return list;
                  }
              }
        • 在扩大类中新增发现服务的扩大

              public static IServiceCollection AddConsulDiscovery(this IServiceCollection services) 
              {services.AddSingleton<IConsulDiscovery, ConsulDiscovery>();
                  return services;
              }
        • 在 Startup 类 ConfigureServices 办法中进行注册

            // 服务发现
            services.AddConsulDiscovery();
        • 在控制器构造函数中注入下服务发现的接口

              private readonly IConsulDiscovery consulDiscovery;
              public HomeController(IConsulDiscovery _consulDiscovery) 
              {consulDiscovery = _consulDiscovery;}
              .....
              // 而后在其余办法中依据服务名称获取服务地址;留神:返回值是一个汇合。

五、注册核心 Consul 的高可用

  • 集群搭建【最好有 3 个实例】

    • 步骤

      • 节点 1

         # 1、新建配置文件,门路:D:/Assembly/Consul/node1/basic.json
         {"datacenter": "dc1",  "data_dir": "D:/Assembly/Consul/node1",  "log_level": "INFO",  "server": true,  "node_name": "node1",  "ui": true,  "bind_addr": "127.0.0.1",  "client_addr": "127.0.0.1",  "advertise_addr": "127.0.0.1",  "bootstrap_expect": 3,  "ports":{    "http": 8500,    "dns": 8600,    "server": 8300,    "serf_lan": 8301,    "serf_wan": 8302}}
         # 2、运行命令
         # 2、切换到 consul 根目录下:consul.exe agent -config-file=D:/Assembly/Consul/node1/basic.json
      • 节点 2

         # 1、新建配置文件,门路:D:/Assembly/Consul/node2/basic.json
         {"datacenter": "dc1",  "data_dir": "D:/Assembly/Consul/node2",  "log_level": "INFO",  "server": true,  "node_name": "node2",  "bind_addr": "127.0.0.1",  "client_addr": "127.0.0.1",  "advertise_addr": "127.0.0.1",  "ports":{    "http": 8510,    "dns": 8610,    "server": 8310,    "serf_lan": 8311,    "serf_wan": 8312}} 
          # 2、切换到 consul 根目录下:consul.exe agent -config-file=D:/Assembly/Consul/node2/basic.json -retry-join=127.0.0.1:8301
      • 节点 3

         # 1、新建配置文件,门路:文件地址:D:/Assembly/Consul/node3/basic.json
         {"datacenter": "dc1",  "data_dir": "D:/Assembly/Consul/node3",  "log_level": "INFO",  "server": true,  "node_name": "node3",  "bind_addr": "127.0.0.1",  "client_addr": "127.0.0.1",  "advertise_addr": "127.0.0.1",  "ports":{    "http": 8520,    "dns": 8620,    "server": 8320,    "serf_lan": 8321,    "serf_wan": 8322}}
         # 2、切换到 consul 根目录下:consul.exe agent -config-file=D:/Assembly/Consul/node3/basic.json -retry-join=127.0.0.1:8301

        运行后果如图:



    • 查看主节点

       #切换到 consul 根目录下
       consul.exe info
    • 集群搭建命令

          -bind:为该节点绑定一个地址
          -enable-script-checks=true:设置查看服务为可用
          -join:退出到已有的集群中
          -server 示意以后应用的 server 模式
          -node:指定以后节点在集群中的名称 
          -config-file - 要加载的配置文件
          -config-dir:指定配置文件,定义服务的,默认所有以.json 结尾的文件都会读
          -datacenter: 数据中心没名称,不设置的话默认为 dc
          -client: 客户端模式
          -ui: 应用 consul 自带的 ui 界面 
          -data-dir consul 存储数据的目录
          -bootstrap:用来管制一个 server 是否在 bootstrap 模式,在一个 datacenter 中只能有一个 server 处于 bootstrap 模式,当一个 server 处于 bootstrap 模式时,能够本人选举为 raft leader。-bootstrap-expect:在一个 datacenter 中冀望提供的 server 节点数目,当该值提供的时候,consul 始终等到达到指定 sever 数目的时候才会疏导整个集群,该标记不能和 bootstrap 专用
          
          这两个参数非常重要,二选一,如果两个参数不应用的话,会呈现就算你应用 join 将 agent 退出了集群依然会报 
          2018/10/14 15:40:00 [ERR] agent: failed to sync remote state: No cluster leader
    • 配置文件参数

          ui: 相当于 -ui 命令行标记。acl_token:agent 会应用这个 token 和 consul server 进行申请
          acl_ttl:管制 TTL 的 cache,默认是 30s
          addresses:一个嵌套对象,能够设置以下 key:dns、http、rpc
          advertise_addr:等同于 -advertise
          bootstrap:等同于 -bootstrap
          bootstrap_expect:等同于 -bootstrap-expect
          bind_addr:等同于 -bindca_file:提供 CA 文件门路,用来查看客户端或者服务端的链接
          cert_file:必须和 key_file 一起
          check_update_interval:client_addr:等同于 -client
          datacenter:等同于 -dc
          data_dir:等同于 -data-dir
          disable_anonymous_signature:在进行更新查看时禁止匿名签名
          enable_debug:开启 debug 模式
          enable_syslog:等同于 -syslog
          encrypt:等同于 -encrypt
          key_file:提供私钥的门路
          leave_on_terminate:默认是 false,如果为 true,当 agent 收到一个 TERM 信号的时候,它会发送 leave 信息到集群中的其余节点上。log_level:等同于 -log-level node_name: 等同于 -node 
          ports:这是一个嵌套对象,能够设置以下 key:dns(dns 地址:8600)、http(http api 地址:8500)、rpc(rpc:8400)、serf_lan(lan port:8301)、serf_wan(wan port:8302)、server(server rpc:8300) 
          protocol:等同于 -protocol
          rejoin_after_leave:等同于 -rejoin
          retry_join:等同于 -retry-join
          retry_interval:等同于 -retry-interval 
          server:等同于 -server
          syslog_facility:当 enable_syslog 被提供后,该参数管制哪个级别的信息被发送,默认 Local0
          ui_dir:等同于 -ui-dir
退出移动版