系列导航及源代码

需求

应用健康检查在容器部署的微服务场景下非常常见,相比而言单体非容器部署的应用就不太关心这个特性,为了后续的内容我们在本文中简单介绍一下如何实现应用程序的健康检查功能。

目标

实现TodoList的健康检查功能。

原理与思路

.NET框架从.NET Core 2.2版本开始引入了相关的功能,同时AspNetCore.Diagnostics.HealthChecks包提供了更为丰富的健康检查功能,包括数据库,消息总线,Redis和ElasticSearch的健康检查。

健康检查探针(probe)分为三种:

  • readiness probes:应用程序就绪探针,判断当前应用程序是否已经启动。
  • liveness probes: 应用程序存活探针,判断当前应用程序是否出于活动状态。
  • startup probes:应用程序功能探针,一般我们用hc来表示其端口,可以用来判断应用程序内部功能是否正常(比如判断数据库连接是否正常,判断Redis连接是否正常之类)。

在本文中我们不过多地发散,通过创建一个自定义的健康检查对象来实现。

实现

自定义健康检查,实现IHealthCheck接口

Microsoft.Extensions.Diagnostics.HealthChecks

using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace TodoList.Application.Common;

public class ApplicationHealthCheck : IHealthCheck
{
private static readonly Random _rnd = new (); public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var result = _rnd.Next(5) == 0
? HealthCheckResult.Healthy()
: HealthCheckResult.Unhealthy("Failed random"); return Task.FromResult(result);
}
}

添加服务和中间件

首先在Application/DependencyInjection中添加健康检查服务:

  • DependencyInjection.cs
services.AddHealthChecks().AddCheck<ApplicationHealthCheck>("Random Health Check");

然后修改Program中间件配置如下:

  • Program.cs
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpLogging(); app.MapDefaultControllerRoute();
app.MapHealthChecks("/liveness");
app.MapHealthChecks("/ready");
app.MapHealthChecks("/hc");

验证

启动Api项目,执行健康检查的三个GET接口,截图我只贴其中一个,因为我们在实现健康检查的时候,采用了随机数返回Healthy或者Unhealthy的方式,所以多请求几次,应该能看到下面的响应:

一点扩展

关于Smart probes和Dumb probes

  • 所谓Smart probes最典型的目的就是为了验证应用程序是否能正确工作,像一开始所说的,它可以用来探测外部依赖如数据库、消息队列、甚至是其他API的连接是否正常,程序在这些地方是否可以按预期工作。
  • 相对而言,Dumb probes典型的应用目的是用来判断应用程序没有崩溃,它并不检查功能及依赖上的正确性,通常表现为HTTP的直接响应。

推荐的使用方式是:

  • 对于liveness检查,使用dumb probes就可以了,因为只要能够响应HTTP请求,就可以证明应用程序没有崩溃。
  • 对于startup或者称作真正的“健康”检查hc,使用smart probes,因为这时候不仅要保证程序没有崩溃,我们还需要某种程度的功能及依赖的健康检查,以证明程序能够按预期工作。
  • 对于readiness检查,需要根据实际的需求来看,如果我们没有定义特殊的应用程序“就绪”标准,使用dumb probes就可以;反之如果我们需要进行某种程度的逻辑检查来定义“就绪”,那么就需要使用smart probes

设置Dumb健康检查接口

修改中间件配置:

  • Program.cs
app.MapHealthChecks("/liveness", new HealthCheckOptions { Predicate = r => r.Name.Contains("self") });
app.MapHealthChecks("/ready", new HealthCheckOptions { Predicate = _ => false });

这时候我们再去请求健康检查,这两个接口已经固定返回Healthy结果了,hc接口依然按照我们之前设置的进行随机返回。

总结

本文我们简单地实现了健康检查接口,目前还不太能看得出来作用,但是当我们进行容器化部署,或是进行k8s部署时,健康检查探针的作用就比较明显了。关于健康检查,更多用法请参考官方文档:Health checks in ASP.NET Core

参考资料

  1. AspNetCore.Diagnostics.HealthChecks
  2. Adding health checks with Liveness, Readiness, and Startup probes
  3. Health checks in ASP.NET Core

使用.NET 6开发TodoList应用(28)——实现应用程序健康检查的更多相关文章

  1. 使用.NET 6开发TodoList应用(3)——引入第三方日志库

    需求 在我们项目开发的过程中,使用.NET 6自带的日志系统有时是不能满足实际需求的,比如有的时候我们需要将日志输出到第三方平台上,最典型的应用就是在各种云平台上,为了集中管理日志和查询日志,通常会选 ...

  2. 使用.NET 6开发TodoList应用(1)——系列背景

    前言 想到要写这样一个系列博客,初衷有两个:一是希望通过一个实践项目,将.NET 6 WebAPI开发的基础知识串联起来,帮助那些想要入门.NET 6服务端开发的朋友们快速上手,对使用.NET 6开发 ...

  3. 使用.NET 6开发TodoList应用(2)——项目结构搭建

    为了不影响阅读的体验,我把系列导航放到文章最后了,有需要的小伙伴可以直接通过导航跳转到对应的文章 : P TodoList需求简介 首先明确一下我们即将开发的这个TodoList应用都需要完成什么功能 ...

  4. 使用.NET 6开发TodoList应用(4)——引入数据存储

    需求 作为后端CRUD程序员(bushi,数据存储是开发后端服务一个非常重要的组件.对我们的TodoList项目来说,自然也需要配置数据存储.目前的需求很简单: 需要能持久化TodoList对象并对其 ...

  5. 使用.NET 6开发TodoList应用(5)——领域实体创建

    需求 上一篇文章中我们完成了数据存储服务的接入,从这一篇开始将正式进入业务逻辑部分的开发. 首先要定义和解决的问题是,根据TodoList项目的需求,我们应该设计怎样的数据实体,如何去进行操作? 长文 ...

  6. 使用.NET 6开发TodoList应用(5.1)——实现Repository模式

    需求 经常写CRUD程序的小伙伴们可能都经历过定义很多Repository接口,分别做对应的实现,依赖注入并使用的场景.有的时候会发现,很多分散的XXXXRepository的逻辑都是基本一致的,于是 ...

  7. 使用.NET 6开发TodoList应用(6)——使用MediatR实现POST请求

    需求 需求很简单:如何创建新的TodoList和TodoItem并持久化. 初学者按照教程去实现的话,应该分成以下几步:创建Controller并实现POST方法:实用传入的请求参数new一个数据库实 ...

  8. 使用.NET 6开发TodoList应用文章索引

    系列导航 使用.NET 6开发TodoList应用(1)--系列背景 使用.NET 6开发TodoList应用(2)--项目结构搭建 使用.NET 6开发TodoList应用(3)--引入第三方日志 ...

  9. 使用.NET 6开发TodoList应用(7)——使用AutoMapper实现GET请求

    系列导航 使用.NET 6开发TodoList应用文章索引 需求 需求很简单:实现GET请求获取业务数据.在这个阶段我们经常使用的类库是AutoMapper. 目标 合理组织并使用AutoMapper ...

随机推荐

  1. Razor语法2

    语法名称 Razor 语法 Web Forms 等效语法 代码块 @{ int x = 123; string y = "because."; } <% int x = 12 ...

  2. java 编程基础 反射方式获取泛型的类型Fileld.getGenericType() 或Method.getGenericParameterTypes(); (ParameterizedType) ;getActualTypeArguments()

    引言 自从JDK5以后,Java Class类增加了泛型功能,从而允许使用泛型来限制Class类,例如,String.class的类型实际上是 Class 如果 Class 对应的类暂时未知,则使 C ...

  3. makefile 规则与原理

    target : prerequisites command Target 通常称作目标.它是一个目标文件,可以是Object File,也可以是执行文件.还可以是一个标签(Label).Prereq ...

  4. SpringBoot使用 MyBatis Plus 实现物理分页查询

    一.分页配置在MyBatis Plus 可以直接使用selectPage这样的分页,但返回的数据确实是分页后的数据,但在控制台打印的SQL语句其实并没有真正的物理分页,而是通过缓存来获得全部数据中再进 ...

  5. 使用.NET 6开发TodoList应用(7)——使用AutoMapper实现GET请求

    系列导航 使用.NET 6开发TodoList应用文章索引 需求 需求很简单:实现GET请求获取业务数据.在这个阶段我们经常使用的类库是AutoMapper. 目标 合理组织并使用AutoMapper ...

  6. 【九度OJ】题目1444:More is better 解题报告

    [九度OJ]题目1444:More is better 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1444 题目描述: ...

  7. 1276 - Very Lucky Numbers

    1276 - Very Lucky Numbers    PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 ...

  8. 浏览器Cookie无法删除问题

    1.写Cookie时添加路径: //写cookies,设置过期时间为30天,并设置path为根目录 function setPathCookie(name,value) { var Days = 30 ...

  9. 微信小程序-自定义菜单导航(实现楼梯效果)

    设计初衷 在开发页面时,往往需要实现,点击页面的导航菜单页面滚动到相应位置,滚动页面实现菜单选项的高亮.在html开发中,我们可以用到a标签锚点实现,jq的动画相结合实现类似效果.在框架中vant U ...

  10. vue中使用JSX报错,如何解决

    Support for the experimental syntax 'jsx' isn't currently enabled (32:12): 30 | }, 31 | render() { & ...