Asp .Net Core 系列: 集成 Consul 实现 服务注册与健康检查
什么是 Consul?
Consul 是一款开源的服务发现和配置管理工具,它能够监控应用程序和服务之间的通信,并提供了一组 API 和 Web UI,用于管理服务和配置。
Consul 是分布式的、高可用的、可横向扩展的,具备以下特性:
- 服务发现:Consul 通过 DNS 或者 HTTP 接口使服务注册和服务发现变得很容易,一些外部服务,例如 saas 提供的也可以一样注册。
- 健康检查:健康检测使 Consul 可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。
- 键/值存储:一个用来存储动态配置的系统。提供简单的 HTTP 接口,可以在任何地方操作。
- 多数据中心:无需复杂的配置,即可支持任意数量的区域。
Consul 的优势:
- 使用 Raft 算法来保证一致性,比复杂的 Paxos 算法更直接。
- 支持多数据中心,内外网的服务采用不同的端口进行监听。多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟、分片等情况等。
- 支持健康检查。
- 支持 http 和 dns 协议接口。
- 官方提供 web 管理界面。
- 安装和部署简单,使用起来也较为简单。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 实现服务注册和服务发现,可以按照以下步骤进行操作:
- 安装 Consul 客户端 SDK 和 Asp .Net Core 扩展包
首先,需要在 ASP.NET Core 应用程序中安装 Consul 客户端 SDK。可以通过 NuGet 包管理器来安装,在包管理器控制台中输入以下命令:
Install-Package Consul
Install-Package Consul.AspNetCore
- 配置服务注册
在应用程序启动时,需要将服务注册到 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 实现 服务注册与健康检查的更多相关文章
- ASP.NET CORE 使用Consul实现服务治理与健康检查(1)——概念篇
背景 笔者所在的公司正在进行微服务改造,这其中服务治理组件是必不可少的组件之一,在一番讨论之后,最终决定放弃 Zookeeper 而采用 Consul 作为服务治理框架基础组件.主要原因是 Consu ...
- SpringBoot系列: 使用 consul 作为服务注册组件
本文基本上摘自纯洁的微笑的博客 http://www.ityouknow.com/springcloud/2018/07/20/spring-cloud-consul.html . 感谢作者的付出. ...
- ASP.NET CORE 使用Consul实现服务治理与健康检查(2)——源码篇
题外话 笔者有个习惯,就是在接触新的东西时,一定要先搞清楚新事物的基本概念和背景,对之有个相对全面的了解之后再开始进入实际的编码,这样做最主要的原因是尽量避免由于对新事物的认知误区导致更大的缺陷,Bu ...
- asp.net core系列 61 Ocelot 构建服务发现简单示例
一.概述 Ocelot允许指定服务发现提供程序,如Consul或Eureka. 这二个中间件是用来实现:服务治理或秒服务发现,服务发现查找Ocelot正在转发请求的下游服务的主机和端口.目前Ocelo ...
- asp.net core 系列 3 依赖注入服务
一. 依赖注入概述 在软件设计的通用原则中,SOLID是非常流行的缩略语,它由5个设计原则的首字母构成:单一原则(S).开放封闭原则(O).里氏替换原则(L).接口分离原则(I).依赖反转原则(D). ...
- ASP.NET Core之跨平台的实时性能监控(2.健康检查)
前言 上篇我们讲了如何使用App Metrics 做一个简单的APM监控,最后提到过健康检查这个东西. 这篇主要就是讲解健康检查的内容. 没看过上篇的,请移步:ASP.NET Core之跨平台的实时性 ...
- asp.net core系列 60 Ocelot 构建服务认证示例
一.概述 在Ocelot中,为了保护下游api资源,用户访问时需要进行认证鉴权,这需要在Ocelot 网关中添加认证服务.添加认证后,ReRoutes路由会进行身份验证,并使用Ocelot的基于声明的 ...
- .net core grpc consul 实现服务注册 服务发现 负载均衡(二)
在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...
- .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡
本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
随机推荐
- hadoop集群搭建及编程实践
Hadoop集群搭建 前期准备及JDK,hadoop安装 设置主机名和添加主机映射 验证连通性 SSH无密码登录 配置集群/分布式环境 修改workers 修改文件core-site.xml 修改hd ...
- 低代码助力微信小程序对接,提升开发效率
摘要:本文由葡萄城技术团队原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 微信小程序相信大家都用过,相较于APP,微信小程序的优势在于其便 ...
- keycloak~为keycloak-services项目添加第三方模块(首创)
我们在对keycloak框架中的核心项目keycloak-services进行二次开发过程中,发现了一个问题,当时有这种需求,在keycloak-services中需要使用infinispan缓存,我 ...
- Null return value from advice does not match primitive return type for
1.org.springframework.aop.AopInvocationException:Null return value from advice does not match primit ...
- reverse--[HZNUCTF 2023 preliminary]easyAPK
首先这是一个apk文件,一开始我是用jadx打开的,发现要aes加密啥的,后面我用jeb打开,发现账号和密码都已经解密出来了 真的很方便,然后根据代码逻辑判断,这应该是安卓程序的一个登录界面,接下来我 ...
- BI 数据可视化平台建设(1)—交叉表组件演变实战
作者:vivo 互联网大数据团队 - Zhu Jianchen 本文是vivo互联网大数据团队<BI数据可视化平台建设>系列文章第1篇 - 交叉表组件. 交叉表在数据分析里应用广泛,通过本 ...
- STM32 定时器时钟配置技巧
众所周知 STM32 的时钟配置比较复杂,而定时器的时钟配置更是 '奇葩'. 如下图(截图自STM32F4编程手册)APB的预分频器分频系数如果不为1,则定时器的时钟就倍频了反而. 配置技巧 下面以S ...
- vue element ui 组件使用 -form 表单
表单验证rules 绑定是规则 也可以自定义规则,:model是表单的数据源 el-form-item 标签里面prop的名字要和数据源的名字一致,才能验证生效 ;提交时调用this.$refs[fo ...
- 基础练习:FJ的字符串
问题描述 FJ在沙盘上写了这样一些字符串: A1 = "A" A2 = "ABA" A3 = "ABACABA" A4 = "AB ...
- MySQL大表设计
存储大规模数据集需要仔细设计数据库模式和索引,以便能够高效地支持各种查询操作.在面对数亿条数据,每条数据包含数百个字段的情况下,以下是我能想到的在设计数据库的时候需要注意的内容,不足之处欢迎各位在评论 ...