.net core微服务入门之Consul

Consul简介

  • Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,比如 Airbnb的SmartStack等相比,Consul的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等),使用起来也较为简单。
  • 要想利用Consul提供的服务实现服务的注册与发现,我们需要建立Consul Cluster。在Consul方案中,每个提供服务的节点上都要部署和运行Consul的Client Agent,所有运行Consul Agent节点的集合构成Consul Cluster。Consul Agent有两种运行模式:Server和Client。这里的Server和Client只是Consul集群层面的区分,与搭建在Cluster之上的应用服务无关。以Server模式运行的Consul Agent节点用于维护Consul集群的状态,官方建议每个Consul Cluster至少有3个或以上的运行在Server Mode的Agent,Client节点不限。
  • Consul支持多数据中心,每个数据中心的Consul Cluster都会在运行于Server模式下的Agent节点中选出一个Leader节点,这个选举过程通过Consul实现的raft协议保证,多个 Server节点上的Consul数据信息是强一致的。处于Client Mode的Consul Agent节点比较简单,无状态,仅仅负责将请求转发给Server Agent节点。
  • Consul的架构以及相关的角色,如下图所示:
    .net core微服务入门之Consul_第1张图片

安装Consul

  1. 官网下载consul安装包:https://www.consul.io/downloads.html
  2. 本文使用windows环境,下载64位win版本
  3. 解压文件,使用命令到consul.exe目录下,执行.\consul.exe agent -dev
    .net core微服务入门之Consul_第2张图片
  4. 访问:http://localhost:8500/ui/dc1/services
    .net core微服务入门之Consul_第3张图片

创建.net core 服务项目

  • 是用.net core 3.1 创建默认api项目模板代码,做简单的修改,这只是一个简单的api接口示例。
    [ApiController]
    [Route("[controller]")]
    public class WeatherController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        [HttpGet]
        public string Get()
        {
            var summary = $"天气:{Summaries[new Random().Next(Summaries.Length)]};服务地址:{Request.Host}";
            // 负载均衡时,打印出来方便看到调用了哪个服务
            Console.WriteLine(summary);
            return summary;
        }
  • Nuget添加Consul的引用
    .net core微服务入门之Consul_第4张图片
  • 添加配置文件consulconfig.json,以及对应的类
{
  "ConsulAddress": "http://127.0.0.1:8500",
  "ServiceName": "MicrServiceDemo",
  "HealthCheck": "/Health"
}
    // Consul配置模型类
    public class ConsulServiceOptions
    {
        // 服务注册地址(Consul的地址)
        public string ConsulAddress { get; set; }
        // 服务ID
        public string ServiceId { get; set; }
        // 服务名称
        public string ServiceName { get; set; }
        // 健康检查地址
        public string HealthCheck { get; set; }
    }
  • 添加健康监测及注入配置信息
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            // 添加健康监测
            services.AddHealthChecks();
            services.Configure<ConsulServiceOptions>(new ConfigurationBuilder()
                .AddJsonFile("consulconfig.json").Build());
        }
  • 添加服务注入代码
public static class ConsulRegistrationExtensions
    {
        public static IApplicationBuilder UseConsul(this IApplicationBuilder app, IConfiguration configuration)
        {
            // 获取主机生命周期管理接口
            var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

            // 获取服务配置项
            var serviceOptions = app.ApplicationServices.GetRequiredService<IOptions<ConsulServiceOptions>>().Value;

            // 服务ID必须保证唯一
            serviceOptions.ServiceId = Guid.NewGuid().ToString("N");

            var consulClient = new ConsulClient(configuration =>
            {
                //服务注册的地址,集群中任意一个地址
                configuration.Address = new Uri(serviceOptions.ConsulAddress);
            });

            // 获取当前服务地址和端口,配置方式,也可以用自动获取
            var features = app.Properties["server.Features"] as FeatureCollection;
            Uri uri = null;
            var address = features.Get<IServerAddressesFeature>().Addresses?.FirstOrDefault();
            if (address == null)
            {
                // 方便使用命令启用多个服务
                uri = new Uri(configuration["urls"]);
            }
            else
            {
                uri = new Uri(address);
            }
            // 节点服务注册对象
            var registration = new AgentServiceRegistration()
            {
                ID = serviceOptions.ServiceId,
                Name = serviceOptions.ServiceName,// 服务名
                Address = uri.Host,
                Port = uri.Port, // 服务端口
                Check = new AgentServiceCheck
                {
                    // 注册超时
                    Timeout = TimeSpan.FromSeconds(5),
                    // 服务停止多久后注销服务
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                    // 健康检查地址
                    HTTP = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceOptions.HealthCheck}",
                    // 健康检查时间间隔
                    Interval = TimeSpan.FromSeconds(10),
                }
            };

            // 注册服务
            consulClient.Agent.ServiceRegister(registration).Wait();

            // 应用程序终止时,注销服务
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(serviceOptions.ServiceId).Wait();
            });

            return app;
        }
    }
  • 在Startup.Configure方法中,添加以下代码
            // 获取consul的配置信息
            var serviceOptions = app.ApplicationServices.GetRequiredService<IOptions<ConsulServiceOptions>>();
            // 配置健康检测地址,.NET Core 内置的健康检测地址中间件
            app.UseHealthChecks(serviceOptions.Value.HealthCheck);
            app.UseConsul(Configuration);
  • 启动服务,查看服务是否注册成功,如下如所示,服务正常注册,且状态为健康状态。
    .net core微服务入门之Consul_第5张图片
  • 用不同的端口,启用多个服务,这里我是用命令启动:dotnet MicrServiceDemo.dll --urls=“http://localhost:6001”
    .net core微服务入门之Consul_第6张图片
  • 添加以下代码,发现已注册的健康服务
        [HttpGet]
        [Route("/GetAllServices")]
        public async Task<List<string>> GetAllServicesAsync()
        {
            var consuleClient = new ConsulClient(consulConfig =>
            {
                consulConfig.Address = new Uri("http://127.0.0.1:8500");
            });
            var queryResult = await consuleClient.Health.Service("MicrServiceDemo", "", true);
            var result = new List<string>();
            foreach (var service in queryResult.Response)
            {
                result.Add(service.Service.Address + ":" + service.Service.Port);
            }
            return result;
        }

.net core微服务入门之Consul_第7张图片
一个简单的Consul服务注册及发现代码示例已完成,下一篇更新配合Consul使用Ocelot。
示例代码

你可能感兴趣的:(微服务)