zoukankan      html  css  js  c++  java
  • 我的第一个微服务系列(四):使用Consul来做服务注册与发现

      Consul是一种提供具有服务发现,配置和分段功能的全功能控制平面的服务网格解决方案,其主要功能有:

    1. 服务发现:Consul的客户端可以注册服务,例如api或mysql,其他客户端可以使用Consul来发现给定服务的提供者。使用DNS或HTTP,应用程序可以轻松找到它们所依赖的服务。
    2. 健康监测:Consul客户端可以提供与给定服务相关的任意数量的健康检查,可以使用此信息来监控集群运行状况,服务发现组件使用该信息将流量路由远离不健康的主机。
    3. 键值存储:应用程序可以将Consul的分层键/值存储用于任何目的,包括动态配置,功能标记,协调,领导者选举等。简单的HTTP API使其易于使用。
    4. Secure Service Communication: Consul可以为服务生成和分发TLS证书,以建立相互的TLS连接。意图可用于定义允许哪些服务进行通信。可以使用可以实时更改的意图轻松管理服务分段,而不是使用复杂的网络拓扑和静态防火墙规则。
    5. 多数据中心:Consul支持多个数据中心。这意味着Consul的用户不必担心构建额外的抽象层以扩展到多个区域。

      具体关于Consul的介绍可以查看官网:https://www.consul.io/docs/index.html 。这里介绍在我们的项目中使用到的服务注册与发现功能。

       首先下载对应平台的consul进行安装,笔者使用windows 64位,具体下载链接:https://www.consul.io/downloads.html 。windows下载下来就是一个consul.exe文件,可以运行下面的命令来启动consul服务。

    consul.exe agent --dev

      浏览器访问 http://localhost:8500/ui/dc1/services 可以看到Consul的界面

      安装完Consul之后,如何在User.Identity中找到User.Api呢,接着往下看。

      要让User.Identity找到,需要将User.Api注册到Consul中,首先在User.Api项目中添加Consul的Nuget包。

    install-package Consul 

      在appsettings.json中添加配置

     "ServiceDiscovery": {
        "ServiceName": "userapi",
        "Consul": {
          "HttpEndpoint": "http://127.0.0.1:8500",
          "DnsEndpoint": {
            "Address": "127.0.0.1",
            "Port": 8600
          }
        }
      }

      为了读取到该配置,需要创建一个ServiceDiscoveryOptions、ConsulOptions、DnsEndpoint来建立映射。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Threading.Tasks;
    
    namespace User.API.Dtos
    {
        public class DnsEndpoint
        {
            public string Address { get; set; }
    
            public int Port { get; set; }
    
            public IPEndPoint ToIPEndPoint()
            {
                return new IPEndPoint(IPAddress.Parse(Address), Port);
            }
        }
    }
    namespace User.API.Dtos
    {
        public class ConsulOptions
        {
            public string HttpEndpoint { get; set; }
    
            public DnsEndpoint DnsEndpoint { get; set; }
        }
    }
    namespace User.API.Dtos
    {
        public class ServiceDiscoveryOptions
        {
            public string ServiceName { get; set; }
    
            public ConsulOptions Consul { get; set; }
        }
    }

      接着在Startup.cs中添加注入

    services.AddOptions();
    services.Configure<ServiceDiscoveryOptions>(Configuration.GetSection("ServiceDiscovery"));
    services.AddSingleton<IConsulClient>(p => new ConsulClient(cfg =>
    {
         var serviceConfiguration = p.GetRequiredService<IOptions<ServiceDiscoveryOptions>>().Value;
    
         if (!string.IsNullOrEmpty(serviceConfiguration.Consul.HttpEndpoint))
         {
              // if not configured, the client will use the default value "127.0.0.1:8500"
              cfg.Address = new Uri(serviceConfiguration.Consul.HttpEndpoint);
         }
    }));

      最后就是在User.Api启动时将其注册到Consul中,停止时删除注册了,代码如下

            public void Configure(IApplicationBuilder app
                ,IHostingEnvironment env
                ,IApplicationLifetime applicationLifetime
                ,ILoggerFactory loggerFactory
                ,IOptions<ServiceDiscoveryOptions> serviceOptions
                ,IConsulClient consul)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }//启动时向consul注册服务
                applicationLifetime.ApplicationStarted.Register(()=> {
                    RegisterService(app, serviceOptions, consul, applicationLifetime);
                });
    
                app.UseMvc();
            }
    
            /// <summary>
            /// 注册服务
            /// </summary>
            /// <param name="app"></param>
            /// <param name="serviceOptions"></param>
            /// <param name="consul"></param>
            /// <param name="applicationLifetime"></param>
            private void RegisterService(IApplicationBuilder app,
                IOptions<ServiceDiscoveryOptions> serviceOptions,
                IConsulClient consul,
                IApplicationLifetime applicationLifetime)
            {
                var features = app.Properties["server.Features"] as FeatureCollection;
                var addresses = features.Get<IServerAddressesFeature>()
                    .Addresses
                    .Select(p => new Uri(p));
    
                foreach (var address in addresses)
                {
                    var serviceId = $"{serviceOptions.Value.ServiceName}_{address.Host}:{address.Port}";
    
                    var httpCheck = new AgentServiceCheck()
                    {
                        DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1),
                        Interval = TimeSpan.FromSeconds(30),
                        HTTP = new Uri(address, "HealthCheck").OriginalString
                    };
    
                    var registration = new AgentServiceRegistration()
                    {
                        Checks = new[] { httpCheck },
                        Address = address.Host,
                        ID = serviceId,
                        Name = serviceOptions.Value.ServiceName,
                        Port = address.Port
                    };
    
                    consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult();
    
                    //停止时向consul清除该服务
                    applicationLifetime.ApplicationStopping.Register(() =>
                    {
                        DeRegisterService(consul, serviceId);
                    });
                }
            }
    
            /// <summary>
            /// 清除服务
            /// </summary>
            /// <param name="consul"></param>
            /// <param name="serviceId"></param>
            private void DeRegisterService(IConsulClient consul,string serviceId)
            {
                consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult();
            }

      为了consul可以监控user.api的运行情况,在User.Api中创建一个controller

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    
    namespace User.API.Controllers
    {
        [Route("[Controller]")]
        public class HealthCheckController : Controller
        {
            [HttpGet("")]
            [HttpHead("")]
            public void Get()
            {
                
            }
        }
    }

      到这里,User.Api注册成功了,接下来就是要在User.Identity中调用User.Api了,我们将用到Polly做熔断重试,下篇再讲。

      

      

      

  • 相关阅读:
    常用数据结构之字符串
    c++知识点总结--友元&运算符重载
    c++知识点总结-模板特化
    c++知识点总结--new的一些用法
    linux socket c/s上传文件
    STL之算法使用简介
    【bzoj2733】 HNOI2012—永无乡
    【bzoj3132】 Sdoi2013—森林
    【bzoj1483】 HNOI2009—梦幻布丁
    【bzoj3091】 城市旅行
  • 原文地址:https://www.cnblogs.com/jesen1315/p/11534340.html
Copyright © 2011-2022 走看看