0
点赞
收藏
分享

微信扫一扫

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/1zN4PiFVuNAPysMabKdDkzg
      提取码: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; } 
        }
    • 微服务注册

      • 创建服务注册实现类
        ```C#
        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
举报

相关推荐

0 条评论