什么是 Consul?

官网:https://www.consul.io/

Consul 是一款开源的服务发现和配置管理工具,它能够监控应用程序和服务之间的通信,并提供了一组 API 和 Web UI,用于管理服务和配置。

Consul 是分布式的、高可用的、可横向扩展的,具备以下特性:

  1. 服务发现:Consul 通过 DNS 或者 HTTP 接口使服务注册和服务发现变得很容易,一些外部服务,例如 saas 提供的也可以一样注册。
  2. 健康检查:健康检测使 Consul 可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。
  3. 键/值存储:一个用来存储动态配置的系统。提供简单的 HTTP 接口,可以在任何地方操作。
  4. 多数据中心:无需复杂的配置,即可支持任意数量的区域。

Consul 的优势:

  1. 使用 Raft 算法来保证一致性,比复杂的 Paxos 算法更直接。
  2. 支持多数据中心,内外网的服务采用不同的端口进行监听。多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟、分片等情况等。
  3. 支持健康检查。
  4. 支持 http 和 dns 协议接口。
  5. 官方提供 web 管理界面。
  6. 安装和部署简单,使用起来也较为简单。Consul 使用 Go 语言编写,因此具有天然可移植性(支持 Linux、windows 和 Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合 。

安装和运行 Consul

下载地址:https://developer.hashicorp.com/consul/install?product_intent=consul#Windows

运行 consul,指定为开发环境

consul agent -dev

web 界面:http://localhost:8500/ui

Asp .Net Core 如何集成 Consul 实现服务注册和健康检查

要在 ASP.NET Core 应用程序中集成 Consul 实现服务注册和服务发现,可以按照以下步骤进行操作:

  1. 安装 Consul 客户端 SDK 和 Asp .Net Core 扩展包

首先,需要在 ASP.NET Core 应用程序中安装 Consul 客户端 SDK。可以通过 NuGet 包管理器来安装,在包管理器控制台中输入以下命令:

Install-Package Consul
Install-Package Consul.AspNetCore
  1. 配置服务注册

    在应用程序启动时,需要将服务注册到 Consul 中。这通常在 Startup 类的 ConfigureServices 方法中完成。首先,示例代码如下:
        /// <summary>
/// 向容器中添加Consul必要的依赖注入
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddMCodeConsul(this IServiceCollection services)
{
var configuration = services.BuildServiceProvider().GetRequiredService<IConfiguration>();
// 配置consul服务注册信息
var consulOptions = configuration.GetSection("Consul").Get<ConsulOptions>();
// 通过consul提供的注入方式注册consulClient
services.AddConsul(options => options.Address = new Uri($"http://{consulOptions.ConsulIP}:{consulOptions.ConsulPort}")); // 通过consul提供的注入方式进行服务注册
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔
HTTP = $"http://{consulOptions.IP}:{consulOptions.Port}/health",//健康检查地址
Timeout = TimeSpan.FromSeconds(10)
}; // Register service with consul
services.AddConsulServiceRegistration(options =>
{
options.Checks = new[] { httpCheck };
options.ID = Guid.NewGuid().ToString();
options.Name = consulOptions.ServiceName;
options.Address = consulOptions.IP;
options.Port = consulOptions.Port;
options.Meta = new Dictionary<string, string>() { { "Weight", consulOptions.Weight.HasValue ? consulOptions.Weight.Value.ToString() : "1" } };
options.Tags = new[] { $"urlprefix-/{consulOptions.ServiceName}" }; //添加
}); return services;
}

ConsulOptions 配置类

    public class ConsulOptions
{
/// <summary>
/// 当前应用IP
/// </summary>
public string IP { get; set; } /// <summary>
/// 当前应用端口
/// </summary>
public int Port { get; set; } /// <summary>
/// 当前服务名称
/// </summary>
public string ServiceName { get; set; } /// <summary>
/// Consul集群IP
/// </summary>
public string ConsulIP { get; set; } /// <summary>
/// Consul集群端口
/// </summary>
public int ConsulPort { get; set; } /// <summary>
/// 权重
/// </summary>
public int? Weight { get; set; }
}

appsettings.json

{
"Consul": {
"ConsulIP": "127.0.0.1",
"ConsulPort": "8500",
"ServiceName": "ConsulDemoService",
"Ip": "localhost",
"Port": "5014",
"Weight": 1
}
}

Consul.AspNetCore 中的 AddConsul 和 AddConsulServiceRegistration 方法 究竟做了什么?

AddConsul 方法

可以看到通过 ConsulClientFactory 类创建和配置 Consul 的客户端实例,ConsulClientFactory 通过 IOptionsMonitor 读取应用程序的配置更改

IOptionsMonitor: 是 ASP.NET Core 的一个接口,它提供了一种方式来观察和监视应用程序的配置更改。通过实现 IOptionsMonitor 接口,你可以创建自定义的配置监视器,以便在配置更改时自动更新应用程序的设置

public static class ServiceCollectionExtensions
{
public static IServiceCollection AddConsul(this IServiceCollection services)
{
return services.AddConsul(delegate
{
});
} public static IServiceCollection AddConsul(this IServiceCollection services, Action<ConsulClientConfiguration> configure)
{
return services.AddConsul(Options.DefaultName, configure);
} public static IServiceCollection AddConsul(this IServiceCollection services, string name, Action<ConsulClientConfiguration> configure)
{
services.Configure(name, configure);
services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
services.TryAddSingleton((IServiceProvider sp) => sp.GetRequiredService<IConsulClientFactory>().CreateClient(name));
return services;
}
。。。
} public class ConsulClientFactory : IConsulClientFactory
{
private readonly IOptionsMonitor<ConsulClientConfiguration> _optionsMonitor; public ConsulClientFactory(IOptionsMonitor<ConsulClientConfiguration> optionsMonitor)
{
_optionsMonitor = optionsMonitor;
} public IConsulClient CreateClient()
{
return CreateClient(Options.DefaultName);
} public IConsulClient CreateClient(string name)
{
return new ConsulClient(_optionsMonitor.Get(name));
}
}

AddConsulServiceRegistration 方法

可以看出使用 AgentServiceRegistrationHostedService 类定义应用程序的后台服务,用于注册和取消注册 Consul 实例

public static class ServiceCollectionExtensions
{
public static IServiceCollection AddConsulServiceRegistration(this IServiceCollection services, Action<AgentServiceRegistration> configure)
{
AgentServiceRegistration agentServiceRegistration = new AgentServiceRegistration();
configure(agentServiceRegistration);
return services.AddSingleton(agentServiceRegistration).AddHostedService<AgentServiceRegistrationHostedService>();
}
} public class AgentServiceRegistrationHostedService : IHostedService
{
private readonly IConsulClient _consulClient; private readonly AgentServiceRegistration _serviceRegistration; public AgentServiceRegistrationHostedService(IConsulClient consulClient, AgentServiceRegistration serviceRegistration)
{
_consulClient = consulClient;
_serviceRegistration = serviceRegistration;
} public Task StartAsync(CancellationToken cancellationToken)
{
return _consulClient.Agent.ServiceRegister(_serviceRegistration, cancellationToken);
} public Task StopAsync(CancellationToken cancellationToken)
{
return _consulClient.Agent.ServiceDeregister(_serviceRegistration.ID, cancellationToken);
}
}

配置 Consul 检查服务

        /// <summary>
/// 配置Consul检查服务
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseConsulCheckService(this IApplicationBuilder app)
{
app.Map("/health", app =>
{
app.Run(async context =>
{
await Task.Run(() => context.Response.StatusCode = 200);
});
}); return app;
}

封装成扩展

        /// <summary>
/// 向容器中添加Consul必要的依赖注入
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static IServiceCollection AddMCodeConsul(this IServiceCollection services)
{
var configuration = services.BuildServiceProvider().GetRequiredService<IConfiguration>();
// 配置consul服务注册信息
var consulOptions = configuration.GetSection("Consul").Get<ConsulOptions>();
// 通过consul提供的注入方式注册consulClient
services.AddConsul(options => options.Address = new Uri($"http://{consulOptions.ConsulIP}:{consulOptions.ConsulPort}")); // 通过consul提供的注入方式进行服务注册
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔
HTTP = $"http://{consulOptions.IP}:{consulOptions.Port}/health",//健康检查地址
Timeout = TimeSpan.FromSeconds(10)
}; // Register service with consul
services.AddConsulServiceRegistration(options =>
{
options.Checks = new[] { httpCheck };
options.ID = Guid.NewGuid().ToString();
options.Name = consulOptions.ServiceName;
options.Address = consulOptions.IP;
options.Port = consulOptions.Port;
options.Meta = new Dictionary<string, string>() { { "Weight", consulOptions.Weight.HasValue ? consulOptions.Weight.Value.ToString() : "1" } };
options.Tags = new[] { $"urlprefix-/{consulOptions.ServiceName}" }; //添加
}); //var applicationLifetime =services.BuildServiceProvider().GetRequiredService<Microsoft.Extensions.Hosting.IHostApplicationLifetime>(); //var consulClient = services.BuildServiceProvider().GetRequiredService<IConsulClient>(); //var agentServiceRegistration = services.BuildServiceProvider().GetRequiredService<AgentServiceRegistration>(); ////程序停止时取消注册Consul
//applicationLifetime.ApplicationStopping.Register(async () =>
//{
// await consulClient.Agent.ServiceDeregister(agentServiceRegistration.ID);
//}); return services;
} /// <summary>
/// 配置Consul检查服务
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseConsulCheckService(this IApplicationBuilder app)
{
app.Map("/health", app =>
{
app.Run(async context =>
{
await Task.Run(() => context.Response.StatusCode = 200);
});
}); return app;
}

效果

Asp .Net Core 系列: 集成 Consul 实现 服务注册与健康检查的更多相关文章

  1. ASP.NET CORE 使用Consul实现服务治理与健康检查(1)——概念篇

    背景 笔者所在的公司正在进行微服务改造,这其中服务治理组件是必不可少的组件之一,在一番讨论之后,最终决定放弃 Zookeeper 而采用 Consul 作为服务治理框架基础组件.主要原因是 Consu ...

  2. SpringBoot系列: 使用 consul 作为服务注册组件

    本文基本上摘自纯洁的微笑的博客 http://www.ityouknow.com/springcloud/2018/07/20/spring-cloud-consul.html . 感谢作者的付出. ...

  3. ASP.NET CORE 使用Consul实现服务治理与健康检查(2)——源码篇

    题外话 笔者有个习惯,就是在接触新的东西时,一定要先搞清楚新事物的基本概念和背景,对之有个相对全面的了解之后再开始进入实际的编码,这样做最主要的原因是尽量避免由于对新事物的认知误区导致更大的缺陷,Bu ...

  4. asp.net core系列 61 Ocelot 构建服务发现简单示例

    一.概述 Ocelot允许指定服务发现提供程序,如Consul或Eureka. 这二个中间件是用来实现:服务治理或秒服务发现,服务发现查找Ocelot正在转发请求的下游服务的主机和端口.目前Ocelo ...

  5. asp.net core 系列 3 依赖注入服务

    一. 依赖注入概述 在软件设计的通用原则中,SOLID是非常流行的缩略语,它由5个设计原则的首字母构成:单一原则(S).开放封闭原则(O).里氏替换原则(L).接口分离原则(I).依赖反转原则(D). ...

  6. ASP.NET Core之跨平台的实时性能监控(2.健康检查)

    前言 上篇我们讲了如何使用App Metrics 做一个简单的APM监控,最后提到过健康检查这个东西. 这篇主要就是讲解健康检查的内容. 没看过上篇的,请移步:ASP.NET Core之跨平台的实时性 ...

  7. asp.net core系列 60 Ocelot 构建服务认证示例

    一.概述 在Ocelot中,为了保护下游api资源,用户访问时需要进行认证鉴权,这需要在Ocelot 网关中添加认证服务.添加认证后,ReRoutes路由会进行身份验证,并使用Ocelot的基于声明的 ...

  8. .net core grpc consul 实现服务注册 服务发现 负载均衡(二)

    在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...

  9. .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡

    本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...

  10. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

随机推荐

  1. java数组的定义和使用规范

    java数组 三种定义方式 1.数组类型[] 数组名字 = new 数组类型[数组长度] String[] str = new String[n]; //这里n代表数组的长度可变 //另外上面这种写法 ...

  2. Linux 下 C语言 open() 和 fopen() 区别

    Linux 下 C语言 open() 和 fopen() 区别   fopen() #include <stdio.h> FILE *fopen(const char *path, con ...

  3. 【matplotlib 实战】--柱状图

    柱状图,是一种使用矩形条,对不同类别进行数值比较的统计图表.在柱状图上,分类变量的每个实体都被表示为一个矩形(通俗讲即为"柱子"),而数值则决定了柱子的高度. 1. 主要元素 柱状 ...

  4. BizSpring在线商城常见问题

    一.什么是BizSpring在线商城? BizSpring在线商城是一个用java语言开发的完全开源的网络商城平台.该项目已经经历多次迭代升级是一个的成熟的在线商城解决方案,它具有轻量级,易于维护,操 ...

  5. 2023_10_10_MYSQL_DAY_02_笔记

    2023_10_10_MYSQL_DAY_02_笔记 #在 FROM 子句中使用子查询 SELECT a.ename, a.sal, a.deptno, b.salavg FROM emp a, (S ...

  6. 传纸条 luoguP1006

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排坐成一个 mm 行 nn 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈 ...

  7. 使用 Alacritty 替代 Gnome-Terminal 解决 Ubuntu 中终端的行间距问题

    我之前发了一篇随笔新版 Ubuntu 中 gnome-terminal 可恶的行间距问题逼我退回了 Ubuntu 20.04,描述了新版 Ubuntu 中终端的行间距问题.评论中给出了一个解决办法,那 ...

  8. 掌握 Kubernetes 故障排除:有效维护集群的最佳实践和工具

    Kubernetes 是一款管理容器化应用程序的强大工具.然而,与任何复杂的系统一样,使用它时也可能出错.当问题出现时, 掌握有效的故障排除技术和工具非常重要. 本文将介绍以下步骤,助您了解事件收集的 ...

  9. Java面向对象(高级)

    1.类变量 类变量是被类的所有实例共享的. 类变量具体放的位置在哪?在内存中的那个区域,这和jdk的版本是有关的 静态变量在类加载的时候就生成了,即使没有创建类实例也能访问,当然通过实例来实现 类变量 ...

  10. 昇腾迁移丨4个TensorFlow模型训练案例解读

    本文分享自华为云社区<TensorFlow模型训练常见案例>,作者: 昇腾CANN. 基于TensorFlow的Python API开发的训练脚本默认运行在CPU/GPU/TPU上,为了使 ...