.NET Core 3.1之深入源码理解HealthCheck(二)

写在前面

前文讨论了HealthCheck的理论部分,本文将讨论有关HealthCheck的应用内容。

  • 可以监视内存、磁盘和其他物理服务器资源的使用情况来了解是否处于正常状态。

  • 运行状况检查可以测试应用的依赖项(如数据库和外部服务终结点)以确认是否可用和正常工作。

  • 运行状况探测可以由容器业务流程协调程序和负载均衡器用于检查应用的状态。

源码研究

在应用中引入HealthCheck,一般需要配置Startup文件,如下所示:

public void ConfigureServices(IServiceCollection services)
{services.AddHealthChecks();
}public void Configure(IApplicationBuilder app)
{app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapHealthChecks("/health");});
}

其中services.AddHealthChecks();会把我们引入到HealthCheckService的扩展方法中,代码如下:

public static class HealthCheckServiceCollectionExtensions
{public static IHealthChecksBuilder AddHealthChecks(this IServiceCollection services){services.TryAddSingleton<HealthCheckService, DefaultHealthCheckService>();services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, HealthCheckPublisherHostedService>());return new HealthChecksBuilder(services);}
}

该扩展方法会尝试注册一个HealthCheckService的单例对象。HealthCheckService本身是一个抽象类,它内部含有一个抽象方法,主要用于执行健康检查并返回健康状态的聚合信息。抽象方法如下所示:

public abstract Task<HealthReport> CheckHealthAsync(Func<HealthCheckRegistration, bool> predicate,CancellationToken cancellationToken = default);

HealthCheckService有一个默认派生类,就是DefaultHealthCheckService,在其构造方法中,会去验证是否有重复的健康检查名称存在,如果有,就会抛出异常。另外名称的检查是不区分大小写的。该类所实现的抽象方法作为健康检查的核心功能,内部实现还是比较复杂的。

首先我们看一下该方法的实现源码:

public override async Task<HealthReport> CheckHealthAsync(Func<HealthCheckRegistration, bool> predicate,CancellationToken cancellationToken = default)
{var registrations = _options.Value.Registrations;if (predicate != null){registrations = registrations.Where(predicate).ToArray();}var totalTime = ValueStopwatch.StartNew();Log.HealthCheckProcessingBegin(_logger);var tasks = new Task<HealthReportEntry>[registrations.Count];var index = 0;using (var scope = _scopeFactory.CreateScope()){foreach (var registration in registrations){tasks[index++] = Task.Run(() => RunCheckAsync(scope, registration, cancellationToken), cancellationToken);}await Task.WhenAll(tasks).ConfigureAwait(false);}index = 0;var entries = new Dictionary<string, HealthReportEntry>(StringComparer.OrdinalIgnoreCase);foreach (var registration in registrations){entries[registration.Name] = tasks[index++].Result;}var totalElapsedTime = totalTime.GetElapsedTime();var report = new HealthReport(entries, totalElapsedTime);Log.HealthCheckProcessingEnd(_logger, report.Status, totalElapsedTime);return report;
}

1、其内部有比较完善的监控机制,会在内部维护了一个Log功能,全程监控健康检查的耗时,该日志所记录的健康检查不仅仅是一个健康检查集合的耗时,而且也记录了每个Name的耗时。

2、该方法会通过await Task.WhenAll(tasks).ConfigureAwait(false);并发执行健康检查。当然,我需要注意的是,过多的健康检查任务将会导致系统性能的下降,这主要看如何取舍了

CheckHealthAsync内部还会调用一个私有方法RunCheckAsync,这是真正执行健康检查的方法。RunCheckAsync方法执行完成后,会创建HealthReportEntry对象返回到CheckHealthAsync中,并组装到HealthReport对象中,到此该抽象方法执行完毕。

以下是RunCheckAsync方法的源码:

private async Task<HealthReportEntry> RunCheckAsync(IServiceScope scope, HealthCheckRegistration registration, CancellationToken cancellationToken)
{cancellationToken.ThrowIfCancellationRequested();var healthCheck = registration.Factory(scope.ServiceProvider);using (_logger.BeginScope(new HealthCheckLogScope(registration.Name))){var stopwatch = ValueStopwatch.StartNew();var context = new HealthCheckContext { Registration = registration };Log.HealthCheckBegin(_logger, registration);HealthReportEntry entry;CancellationTokenSource timeoutCancellationTokenSource = null;try{HealthCheckResult result;var checkCancellationToken = cancellationToken;if (registration.Timeout > TimeSpan.Zero){timeoutCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);timeoutCancellationTokenSource.CancelAfter(registration.Timeout);checkCancellationToken = timeoutCancellationTokenSource.Token;}result = await healthCheck.CheckHealthAsync(context, checkCancellationToken).ConfigureAwait(false);var duration = stopwatch.GetElapsedTime();entry = new HealthReportEntry(status: result.Status,description: result.Description,duration: duration,exception: result.Exception,data: result.Data,tags: registration.Tags);Log.HealthCheckEnd(_logger, registration, entry, duration);Log.HealthCheckData(_logger, registration, entry);}catch (OperationCanceledException ex) when (!cancellationToken.IsCancellationRequested){var duration = stopwatch.GetElapsedTime();entry = new HealthReportEntry(status: HealthStatus.Unhealthy,description: "A timeout occured while running check.",duration: duration,exception: ex,data: null);Log.HealthCheckError(_logger, registration, ex, duration);}// Allow cancellation to propagate if it's not a timeout.catch (Exception ex) when (ex as OperationCanceledException == null){var duration = stopwatch.GetElapsedTime();entry = new HealthReportEntry(status: HealthStatus.Unhealthy,description: ex.Message,duration: duration,exception: ex,data: null);Log.HealthCheckError(_logger, registration, ex, duration);}finally{timeoutCancellationTokenSource?.Dispose();}return entry;}
}

来自官方的应用

  • 数据库探测,例子可以是执行select 1 from tableName根据数据库响应来判断是否健康

  • Entity Framework Core DbContext 探测,DbContext 检查确认应用可以与为 EF Core DbContext 配置的数据库通信。

  • 单独的就绪情况和运行情况探测,在某些托管方案中,可能初始化是一个比较耗时的操作,应用正常运行,但是可能还不能正常处理请求并响应

  • 具有自定义响应编写器的基于指标的探测,比如检查内存占用是否超标,cpu 是否占用过高,连接数是否达到上限

  • 按端口筛选,指定端口,一般用于容器环境,根据容器启动时配置的端口号进行响应

  • 分发运行状况检查库,将检查接口实现独立一个类,并通过依赖注入获取参数,检查时根据参数编写逻辑

  • 运行状况检查发布服务器,如果向 DI 添加 IHealthCheckPublisher,则运行状态检查系统将定期执行状态检查,并使用结果调用 PublishAsync。适用于需要推送的健康系统,而不是健康系统

  • 使用 MapWhen 限制运行状况检查,使用 MapWhen 对运行状况检查终结点的请求管道进行条件分支

其他更多内容请参考:https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-3.1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多重背包问题以及二进制优化

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 多重背包问题&#xff08;N< 100): //Wecccccccc //2020.12.31 #include <iostream> using namespace std; int n,m,dp[110]; int main() {cin>>n>>m;for(int i0;i&…

UnitTest in .NET(Part 2)

Photo &#xff1a;Unit Test in Visual Studio文 | Edison Zhou上一篇我们学习基本的单元测试基础知识和入门实例。但是&#xff0c;如果我们要测试的方法依赖于一个外部资源&#xff0c;如文件系统、数据库、Web服务或者其他难以控制的东西&#xff0c;那又该如何编写测试呢&…

二维费用的背包问题

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2020.12.31 #include <iostream> using namespace std; int n, v, m, dp[120][120];int main() {cin >> n >> v >> m;for (int i 0; i < n; i) …

UnitTest in .NET(Part 1)

Photo &#xff1a;Unit Test in Visual Studio文 | Edison Zhou2015年看了Roy Osherove的《单元测试的艺术》一书&#xff0c;颇有收获。因此&#xff0c;我在当时就将我的学习笔记过程记录了下来&#xff0c;并分为四个部分分享成文&#xff0c;与各位Share。本篇作为入门&am…

找出一个字符串中出现次数最多的字_Day34:第一个只出现一次的字符

剑指Offer_编程题——第一个只出现一次的字符题目描述&#xff1a;在一个字符串(0<字符串长度<10000&#xff0c;全部由字母组成)中找到第一个只出现一次的字符&#xff0c;并返回它的位置&#xff0c;如果没有则返回-1&#xff0c;需要区分大小写。(从0开始计数)。具体要…

2020 WTM 继续向前

WTM3.1 正式发布在过去的2019年&#xff0c;承蒙各位的厚爱&#xff0c;WTM从零开始一年的时间在GitHub上收获了将近1600星&#xff0c;nuget上的下载量累计超过10万。WTM所坚持的低码开发&#xff0c;快速实现的理念受到了越来越多.netcore使用者的喜爱。在2020年&#xff0c;…

使用ASP.NET Core 3.x 构建 RESTful API - 4.3 HTTP 方法的安全性和幂等性

什么样的HTTP方法是安全的&#xff1f; 如果一个方法不会改变资源的表述&#xff0c;那么这个方法就被认为是安全的。 例如 HTTP GET 和 HTTP HEAD 就被认为是安全的&#xff0c;但需要注意的是&#xff0c;这并不意味着执行GET请求就不会引起其它的资源操作&#xff0c;在表面…

混合背包问题

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2020.12.31 #include <iostream> using namespace std; #include <vector>struct note {int kind;int v, w; };vector <note> kinds; int n, v, v1, w, dp…

.NET Core 3.1通用主机原理及使用

一、前言只是讲asp.net core 3.x通用主机的大致原理&#xff0c;这些东西是通过查看源码以及自己根据经验总结得来的&#xff0c;在文章中不会深入源码&#xff0c;因为个人觉得懂原理就晓得扩展点&#xff0c;后期碰到有需求的时候再仔细去研究源码也不迟。阅读前你应该先去了…

火焰效果材质实现_「游戏开发」使用Unity实现魔法火焰效果

*本文转载自公众号“Unity官方平台”。本文由视觉效果艺术家Evgeny Starostin分享如何使用Unity制作魔法火焰效果的过程&#xff0c;让我们一起学习和制作魔法火焰吧。下面是魔法火焰效果图。项目下载本文提供项目工程及着色器下载。本文为转载文章&#xff0c;请关注公众号“U…

激光炸弹(二维前缀和问题)

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2021.1.2 #include <iostream> using namespace std; const int N 5010; int mp[N][N]; int main() {int n,m,k,r,x,y,w;cin>>k>>r;r min(r,5001);n m …

错误使用.Net Redis客户端CSRedisCore,自己挖坑自己填

本文2019年中原创首发于博客园&#xff0c;当时使用CSRedisCore的排障思路引起很大反响&#xff0c;当时被张队公众号翻牌&#xff0c;本次转回公号。背景上次Redis MQ分布式改造之后&#xff0c;编排的容器稳定运行一个多月&#xff0c;昨天突然收到ETL端同事通知&#xff0c;…

最佳牛围栏(二分)

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 #include <iostream> using namespace std; #include <algorithm> const int N 100001; int n, m; int cow[N]; double sum[N];bool check (double ave) {for (int i 1; i <…

IHostingEnvironment VS IHostEnvironment - .NET Core 3.0中的废弃类型

原文&#xff1a;https://andrewlock.net/ihostingenvironment-vs-ihost-environment-obsolete-types-in-net-core-3/作者&#xff1a;Andrew Lock译者&#xff1a;Lamond Lu本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇。Part 1 - 将.NET Standard 2.0 类库转换为.NET C…

【敏捷案例】老板太外行,朝令夕改!要不要拿了年终奖就撤?

快到春节了&#xff0c;不知道有多少人在等着春节后跳槽&#xff0c;想跳槽的原因也很多&#xff0c;其中一个比较普遍的原因是和老板聊不到一块儿去。前两天&#xff0c;有个学员咨询了我们一个问题&#xff0c;因为这个问题比较普遍&#xff0c;拿出来和大家一起讨论一下~提出…

【2019总结篇】谈谈数字化时代,ERP如何坐稳数字化底座

源宝导读&#xff1a;面向未来&#xff0c;信息化、在线化、智能化&#xff0c;开放应该是数字化转型的核心要素&#xff01;本文将重点介绍2019年明源云ERP开放平台在推进数字化转型中的核心技术层面的实践成果。一、前言面向未来&#xff0c;信息化、在线化、智能化&#xff…

dotNetCore操作Redis(含CentOS7哨兵模式部署)

现在说到使用缓存中间件基本就是 Redis 了&#xff0c;通常开发环境或测试环境部署一个单机版就可以运行了&#xff0c;但要上生产环境还需要进行高可用的方式来部署&#xff0c;本文说说在 CentOS7 中 Redis 高可用的部署以及在 dotNetCore 中怎样调用。环境CentOS&#xff1a…

php和mysql一键安装包_iis+php+mysql一键安装教程和安装包

导读&#xff1a;iis上mysqlphp一键安装 很多用vps的朋友&#xff0c;在windons系统iis上配置mysqlphp环境的时候都非常的头痛&#xff0c;过程非常复杂和麻烦&#xff0c;所以我们推荐大家用mysqlphp一键安装包&#xff1a; 1、下载mysqlphp一键安装包&#xff0c;安装包下载地…

程序员过关斩将--自定义线程池来实现文档转码

背景我司在很久之前&#xff0c;一位很久之前的同事写过一个文档转图片的服务&#xff0c;具体业务如下&#xff1a;1. 用户在客户端上传文档&#xff0c;可以是ppt&#xff0c;word&#xff0c;pdf 等格式&#xff0c;用户上传完成可以在客户端预览上传的文档&#xff0c;预览…

UnitTest in .NET(Part 4)

Photo &#xff1a;Unit Test in Visual Studio文 | Edison Zhou上一篇我们学习了如何使用模拟对象进行交互测试。这一篇我们则会进一步使用隔离框架支持适应未来和可用性的功能。为何使用模拟框架&#xff1f; 对于复杂的交互场景&#xff0c;可能手工编写模拟对象和存根就会变…