使用ASP.NET Core实现Docker的HealthCheck指令
写在前面
HealthCheck 不仅是对应用程序内运行情况、数据流通情况进行检查, 还包括应用程序对外部服务或依赖资源的健康检查。
健康检查通常是以暴露应用程序的HTTP端点的形式 实施,可用于配置健康探测的的场景有 :
① 容器或负载均衡器 探测应用状态,执行既定策略,例如:容器探测到应用unhealthy可终止后续的滚动部署或者重启容器;负载均衡器探测到实例unhealthy能将请求路由到健康的运行实例。
② 对应用程序种依赖的第三方服务进行健康探测,比如redis、database、外部服务接口
③ 内存、硬盘、网络等物理依赖资源的探测
HealthCheck提供对外暴露程序运行状态的机制。
容器HEALTHCHECK指令
一般情况下我们很容易知道容器正在运行[running], 但容器作为相对独立的应用执行环境,有时候并不知道容器是否以预期的方式正确运作[working]
Dockerfile HEALTHCHECK指令提供了探测容器以预期工作的轮询机制,轮询内容可由应用自身决定。
通过在容器内运行shell命令来探测容器健康状态,Dockerfile以command的退出码表示容器健康状态:
0 指示容器健康
1 指示容器不健康
2 指示不使用这个退出码
(docker-compose.yml 也有相应的配置节完成HealthCheck)
// 可定义轮询interval、探测超时timeout、 重试retries参数轮训探测
HEALTHCHECK [OPTIONS] CMD command
Every Linux or Unix command executed by the shell script or user has an exit status. Exit status is an integer number. 0 exit status means the command was successful without any errors. A non-zero (1-255 values) exit status means command was a failure. 传送门
故为方便对接Docker- HealcthCheck,以上CMD之后我们一般都接 || exit 1
对于容器内Web应用,自然而然会联想到 使用端点访问的形式去探测容器应用: 应用端点返回成功对应返回0 ;返回失败对应返回1
// shell将成功的退出状态(0)映射为真,任何失败退出/非0都映射为假, 这样做可以有条件的执行链接shell命令 http://www.dovov.com/0shelltruefalse1.html
HEALTHCHECK --interval=5m --timeout=3s --retries= CMD (curl -f http://localhost:5000/healthz) || exit 1
探测命令在stdout或stderr 输出的任何内容 会在 容器Health Status中存储,可通过docker inspect [ContainerId] 查看HealthCheck状态节点。
下面我们会将渐进式演示使用Docker平台的HEALTHCHECK指令对接 ASP.NET Core程序的健康检查能力。

实现AspNetCore HealthCheck端点
ASPNET Core在2.2版本内置了健康检查的能力: 终端中间件(满足该路径的url请求,将会被该中间件处理)。
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHealthChecks("/healthcheck");
}
请求/healthcheck端点, 程序会进行健康检查逻辑并响应输出, 默认的行为:
① 对healthy、degraded状态返回200 OK 响应码; 对于unhealthy返回503 Service Unavailable 响应码
② 响应体只会包含简单的HealthStatus枚举字符串
③ 将每次健康检查的结果写入HealthReport对象。
作为企业级项目,存在对Web项目物理资源和服务依赖的健康检查需求, 这里我们为避免重复造轮子,引入了开源的力量。
开源社区对HealthCheck的支持
开源的企业级AspNetCore.Diagnostics.HealthChecks系列组件,该系列组件支持多种物理资源和服务依赖的健康检查,支持报告推送,支持友好的检查报告UI(支持后台轮训检查)、支持webhook通知。
下面的步骤演示了对web程序HTTP请求、Redis、Sqlite等服务进行健康检查的端点配置
① 引入AspNetCore.HealthChecks.Redis 、 AspNetCore.HealthChecks.Sqlite nuget库
② Startup.cs配置并启用健康检查
// 以下代码截取自 Startup.ConfigureServices方法,对swagger服务地址、redis、sqlte进行健康检查
services.AddHealthChecks().AddAsyncCheck("Http", async () =>
{
using (HttpClient client = new HttpClient())
{
try
{
var response = await client.GetAsync("http://localhost:5000/swagger");
if (!response.IsSuccessStatusCode)
{
throw new Exception("Url not responding with 200 OK");
}
}
catch (Exception)
{
return await Task.FromResult(HealthCheckResult.Unhealthy());
}
}
return await Task.FromResult(HealthCheckResult.Healthy());
})
.AddSqlite(
sqliteConnectionString: Configuration.GetConnectionString("sqlite"),
healthQuery: "select count(*) as count from ProfileUsageCounters;",
name: "sqlite",
failureStatus: HealthStatus.Degraded,
tags: new string[] { "db", "sqlite", "sqlite" }
)
.AddRedis(Configuration.GetConnectionString("redis"), "redis", HealthStatus.Unhealthy, new string[] { "redis", "redis" })
.Services
.AddMvc(); // 以下代码截取自Startup.Configure方法: 启用/healthz作为检查端点
app.UseHealthChecks("/healthz").UseMvcWithDefaultRoute(); // 这里仍然只会响应 200/503状态码+简单的HealthStatus枚举值
小技巧:你也可以使用UseHealthChecks()扩展方法修改默认的响应输出, 这里我们可引入HealthChecks.UI.Client nuget package输出更加详细的的HealthReport
app.UseHealthChecks("/healthz", new HealthCheckOptions()
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse // 该响应输出是一个json,包含所有检查项的详细检查结果
});
注意,容器HealthCheck指令不关注响应体, 只关注CMD命令的执行结果: 0 表示容器健康, 1 表示容器不健康, 所以不管以何种CMD ,我们都需要将CMD的结果转换为 0,1
ps: docker-compose.yml 文件中可参考如下配置:
healthcheck:
test: curl -u huangjun:Iampossword -f http://localhost/healthcheck || exit 1 # -u 指定了用于基本身份验证的用户名和密码
interval: 1m30s
timeout: 10s
retries:
容器HEALTHCHECK指令输出
使用docker ps命令可查看容器的状态, 通过docker inspect [container_id] 查看容器HealthCheck的输出,容器启动输出:starting,一旦监测到成功的响应状态码,将会转换为healthy 并将会持续轮询检查。
//---------截取自 docker inspect 【containerid】 输出--------------------------------
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 2645,
"ExitCode": 0,
"Error": "",
"StartedAt": "2019-09-29T04:04:42.395037744Z",
"FinishedAt": "0001-01-01T00:00:00Z",
"Health": {
"Status": "healthy",
"FailingStreak": 0,
"Log": [
{
"Start": "2019-09-29T12:06:12.400153719+08:00",
"End": "2019-09-29T12:06:12.478927574+08:00",
"ExitCode": 0,
"Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r100 206 0 206 0 0 12030 0 --:--:-- --:--:-- --:--:-- 12875\n{\"status\":\"Healthy\",\"totalDuration\":\"00:00:00.0080008\",\"entries\":{\"sqlite\":{\"data\":{},\"duration\":\"00:00:00.0075454\",\"status\":\"Healthy\"},\"redis\":{\"data\":{},\"duration\":\"00:00:00.0003594\",\"status\":\"Healthy\"}}}"
},
{
"Start": "2019-09-29T12:07:42.479160725+08:00",
"End": "2019-09-29T12:07:42.538163351+08:00",
"ExitCode": 0,
"Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r100 206 0 206 0 0 14312 0 --:--:-- --:--:-- --:--:-- 14714\n{\"status\":\"Healthy\",\"totalDuration\":\"00:00:00.0081428\",\"entries\":{\"sqlite\":{\"data\":{},\"duration\":\"00:00:00.0077286\",\"status\":\"Healthy\"},\"redis\":{\"data\":{},\"duration\":\"00:00:00.0003531\",\"status\":\"Healthy\"}}}"
},
{
"Start": "2019-09-29T12:09:12.53837533+08:00",
"End": "2019-09-29T12:09:12.596907251+08:00",
"ExitCode": 0,
"Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r100 206 0 206 0 0 14001 0 --:--:-- --:--:-- --:--:-- 14714\n{\"status\":\"Healthy\",\"totalDuration\":\"00:00:00.0085169\",\"entries\":{\"sqlite\":{\"data\":{},\"duration\":\"00:00:00.0080190\",\"status\":\"Healthy\"},\"redis\":{\"data\":{},\"duration\":\"00:00:00.0004430\",\"status\":\"Healthy\"}}}"
}
]
}
},
......
HealthChecks-UI 了解一下
抛开Docker的HEALTHCHECK指令、负载均衡器的轮询机制不谈,我们的Web自身也可以进行 轮询健康检查并给出告警。
就我们上面的Web 实例来说,我们只对外提供的是一个 /healthcheck 检查端点,引入HealthChecks.UI.dll 将会在前端生成友好的HealthReport 界面, 该库支持后台轮询检查、支持webhook 通知。
这里就不展开说明,自行前往AspNetCore.Diagnostics.HealthChecks查看相应文档,效果如下:
至此,本文内容完毕:
- 使用ASP.NETCore 框架实现一个稍复杂的HealthCheck端点 /healthz
- 使用docker的HEALTHCHECK 指令对接Web程序健康检查端点
(完成以上步骤,为实现容器自愈打下基础, 请关注后续博文)
+ linux shell 指令: http://www.dovov.com/0shelltruefalse1.html
码甲拙见,如有问题请下方留言大胆斧正;码字+Visio制图,均为原创,看官请不吝好评+关注, ~。。~
本文欢迎转载,请转载页面明显位置注明原作者及原文链接。
使用ASP.NET Core实现Docker的HealthCheck指令的更多相关文章
- ASP.NET Core开发-Docker部署运行
ASP.NET Core开发Docker部署,.NET Core支持Docker 部署运行.我们将ASP.NET Core 部署在Docker 上运行. 大家可能都见识过Docker ,今天我们就详细 ...
- 基于Microsoft Azure、ASP.NET Core和Docker的博客系统
欢迎阅读daxnet的新博客:一个基于Microsoft Azure.ASP.NET Core和Docker的博客系统 2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客 ...
- .NET Core微服务之ASP.NET Core on Docker
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.Docker极简介绍 1.1 总体介绍 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源.D ...
- [翻译] ASP.NET Core 利用 Docker、ElasticSearch、Kibana 来记录日志
原文: Logging with ElasticSearch, Kibana, ASP.NET Core and Docker 一步一步指导您使用 ElasticSearch, Kibana, ASP ...
- asp.net core的docker实践
如果centos中没有安装和docker和.net core镜像,先安装docker和asp.net core 镜像 安装dockeryum -y install docker-io 启动 Docke ...
- ASP.NET Core开发Docker部署
ASP.NET Core开发Docker部署,.NET Core支持Docker 部署运行.我们将ASP.NET Core 部署在Docker 上运行. 大家可能都见识过Docker ,今天我们就详细 ...
- ASP.NET Core使用Docker进行容器化托管和部署
一.课程介绍 人生苦短,我用.NET Core!今天给大家分享一下Asp.Net Core以Docker进行容器化部署托管,本课程并不是完完全全的零基础Docker入门教学,课程知识点难免有没覆盖全面 ...
- 自动部署Asp.Net Core到Docker
原文链接:个人博客:自动部署Asp.Net Core至Docker 本文简介 最近在开发一个管理系统,代码框架是用的前后台分离的方式 后台使用的是Asp.Net Core平台,开发所有业务,向前台提供 ...
- 欢迎阅读daxnet的新博客:一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为"希赛网" ...
随机推荐
- Qt中的通用模板算法QtAlgorithms(qDeleteAll,qBinaryFind,qCountLeadingZeroBits,qPopulationCount,qFill,qSwap,qSort)
Qt在<QtAlgorithms>头文件中为我们提供了一系列的全局模板方法,这些模板方法主要用于容器操作,比如qDeleteAll().其在Qt中的声明如下: void qDeleteAl ...
- 韩国版微信Kakao推出公链,能否用区块链实现全球扩张?
2018年是属于区块链的一年,国内外巨头们纷纷布局区块链产业,前不久韩国最大的移动社交平台Kakao集团正式启动了旗下的第一个公链Klaytn的测试网. 此次宣布只是一次试探性举措,旨在对外公布Kla ...
- svn 出现冲突时可以使用 meld . 命令合并。 而git的冲突合并详见内容
1.可以在任意目录使用 git mergetool --tool-help 查看 git 所支持的merge tools. 2.可以使用如下配置去设置merge tool 和 diff tool ...
- 支付宝异步通知notify_url接收不了问题解决(转)
此处return_url可以成功跳转回网站页面但notify_url却接收不到支付宝的异步通知.已保证notify_url是一个外网可以访问的网址 1.网站用的是ssh框架,当支付宝发通知到我这个ac ...
- PYTHON加密解密字符串
依赖包安装部分 安装依赖包: pip install pycryptodome 在你的python环境中的下图红框路径中找到 crypto 将其改成 Crypto 代码部分 #!/usr/bin/en ...
- map select reduce
map: 针对每个element进行变换并返回整个修改后的map a.map do |item| a.upcase end a.map(&:upcase) 一样的效果, &:代表了it ...
- 《程序员代码面试指南》第八章 数组和矩阵问题 打印N 个数组整体最大的Top K
题目 打印N 个数组整体最大的Top K java代码 package com.lizhouwei.chapter8; /** * @Description: 打印N 个数组整体最大的Top K * ...
- 校园网络 usaco
这道题和上一道[最受欢迎的牛]差不多,都是强连通分量的练习题: 第一问实际上就是问缩点后入度为0的点有多少,第二问就是问添加几条边能使缩点后的图变成强连通图: 第一问好做,第二问需要动下脑子,也不难: ...
- HTML布局之左右结构,左边固定右边跟据父元素自适应
HTML布局之左右结构,左边固定右边跟据父元素自适应,兼容IE6+.Firefox.Chrome.Opera.Safari,这里是用表单写的一个demo,其实就在主体布局中也是可以的,比如像后台一些管 ...
- 【Lintcode】137.Clone Graph
题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...