Health Check(健康状态检查)不仅是对自己应用程序内部检测各个项目之间的健康状态(各项目的运行情况、项目之间的连接情况等),还包括了应用程序对外部或者第三方依赖库的状态检测。
现在我们的项目越来越多的从单体多层架构转换成多项目多层架构即现在流行的微服务架构。
原来我们的 App 把各个模块分层分项目处理,比如 Users 项目仅仅处理 User 的一些业务需求,但在整个项目使用的时候,我们仅仅需要引用其类库即可,不用担心项目与类库之间的不兼容问题,如果不兼容在编译期已经会有提示。但如今,业务规模越来越庞大的时候,我们单独把 Users 作为一个 service 来做,所有一切都在其内部处理,对于外部来说仅仅公开几个 api 即可,但与项目之间的连接就从单纯的物理引用关系转换成了网络调用关系。
当我们架构从单体架构到微服务架构的时候,我们会发现越来越多的引用从物理转向了网络,在原来我们不需要考虑之间是否调用成功,但现在我们必须考虑进去,网络因素、服务器因素、其他因素等都会影响各服务之间的调用,因此 Health Check 孕育而生,它在微服务架构中是举足轻重的。
Health Check 的功能有哪些?在微服务架构中很简单,就是检查各 services 的运行状态是否正常。在微服务的架构中,所有的一切都是 service,db is service,rabbitmq is service,auth is service, shoppingcart is server…… 我们的架构能够根据业务需求,横向的扩容,多个 db,多个 rabbitmq,多个 auth,多个 shoppingcart。我们总结下,微服务架构下的 Health Check 是通过网络检查各 services 是否正常运行,它的功能是:
1、提供外部调用 Health Check 接口,反馈自身状态
2、检测相关 service 状态是否正常(比如 db server,能否连接到 db,能否打开数据库等)
3、UnHealthly 时处理机制
之前我们一直都在介绍 eShop 是微软基于微服务架构的. Net Core Demo,为了保障各个 services 之间的调用正常,所以 Health Check 是必不可少的。
在 Demo 中,我们可以在各个 services 中都能看到 HealthCheck,可以说是无处不在,在系列【二】和【三】中我们都有见过。在 eShop 项目中,我们可以看到有个 HealthChecks 目录,其中包含了与 HealthChecks 相关的几个项目:
Microsoft.Extensions.HealthChecks ------------ Health Check 的核心代码
Microsoft.AspNetCore.HealthChecks ------------ Asp.Net Core 注册扩展类库
Microsoft.Extensions.HealthChecks.AzureStorage ----- 扩展对 Azure Blob Storage 的支持
Microsoft.Extensions.HealthChecks.SqlServer ------ 扩展对 MsSql Server 的支持
通过代码了解,在 eShop 中实现了对各 Api 的通讯检测和 SqlServer、AzureBlobStorage 的检测,但其中并没有看到对重试机制和 UnHealthy 时的处理,相信以后会加入这些,目前微软已经单独为 HealthChecks 开了一个 Repository,这样你就可以单独引用到自己的项目中,非常棒的东西。
在项目中,我们一般只会在 Program.cs 和 Startup.cs 看到跟 HealthChecks 相关的代码。目前仅在客户端(其他 service 或者我们的 app)请求我们的 HealthChecks 的时候,我们会进行相关 service 的检测,然后再返回自身的一个状态码。
接下来我们看下在 eShop 中代码是如何使用的,我们以 Identity.Api 为例,在之前的文章中我们提到过, 在 Program.cs 中,有一段 UseHealthChecks("/hc"),我们跟踪下代码,你会看到它会先判断 path 是否负责规则,如果符合的话就会通过 IwebHostBuilder 注册一个 HealthCheckStartupFilter,Filter 则会把相应的 HealthCheckMiddleware 注册到管道中,我们看下主要源码:
- public async Task Invoke(HttpContext context) {
- if (IsHealthCheckRequest(context)) {
- var timeoutTokenSource = new CancellationTokenSource(_timeout);
- var result = await _service.CheckHealthAsync(timeoutTokenSource.Token);
- var status = result.CheckStatus;
- if (status != CheckStatus.Healthy) context.Response.StatusCode = 503;
- context.Response.Headers.Add("content-type", "application/json");
- await context.Response.WriteAsync(JsonConvert.SerializeObject(new {
- status = status.ToString()
- }));
- return;
- } else {
- await _next.Invoke(context);
- }
- }
- private bool IsHealthCheckRequest(HttpContext context) {
- if (_port.HasValue) {
- var connInfo = context.Features.Get();
- if (connInfo.LocalPort == _port) return true;
- }
- if (context.Request.Path == _path) {
- return true;
- }
- return false;
- }
它会先检测这个请求是不是 HealthCheck 请求,如果不是则走下面的步骤,如果是,则会进一步进行对相关 service 的 HealthChecks。对相关 service 的 Config 实在 Startup.cs 中进行的:
- services.AddHealthChecks(checks = >{
- var minutes = 1;
- if (int.TryParse(Configuration["HealthCheck:Timeout"], out
- var minutesParsed)) {
- minutes = minutesParsed;
- }
- checks.AddSqlCheck("Identity_Db", Configuration.GetConnectionString("DefaultConnection"), TimeSpan.FromMinutes(minutes));
- });
这里可以看到,在 Identity.Api 中,仅仅配置了对数据库的检测。
ok,我们非常简单的在项目中引用了 HealthCheck,当我们的 api 运行后,我们只需要通过 http://xxx/hc 就能对这个 api 进行 Health Check 了。
今天我们了解了 Health Check,并简单看了它在 eShop 中的使用。目前看来还不是很完善,只在其他 service 或者 app 调用其 Health Check 接口的时候才能进行检测,当然我们可以改造下,使其在程序运行的时候先检测一次。在 eShop 中我们并没有看到在 UnHealth 的时候的处理,这个扩展起来很简单,你可以通过自身需求,进行日志,email,短信都可以,后面可以找机会实现下。
乘着不忙的时候赶紧学习,如果大家有兴趣学习. Net Core 的话,可以加 QQ 群:376248054(通关密码:cnblogs)。另外喜欢微服务的朋友可以看下园中大神 Savorboard 的微服务系列
来源: http://www.cnblogs.com/inday/p/healthchecks-in-eshop.html