【Azure 应用服务】App Service 运行状况健康检查功能简介 (Health check)

通过Azure App Service门户,启用Health Check来监视应用服务的实例,当发现其中一个实例处于不健康(unhealthy)状态时,通过重新路由(即把有问题的实例从负载均衡器中移除, Load Balancer)的方式把请求发送到健康的实例上。并且如果不健康的实例一直存在问题,系统则会启动一个新实例来替换不健康的这个实例。

应用服务计划应该扩展到两个或者更多的实例,以充分利用Health Check功能。并且应该是对应用的关键组件进行监控检查。

例如:如果应用依赖于数据库和一个Message系统,那么Health Check应该设置在需要与数据库连接,Message系统连接的功能点。当应用关键组件出现异常时,通过返回500的状态码告诉Health Check表示当前实例的运行状态为不健康(unhealthy)。


No alt text provided for this image

Health Check 会做些什么呢?

1)通过启用Health Check功能时配置的请求URL,应用服务的所有实例将会每间隔1分钟对该URL请求一次。

2)如果某一个实例在连续两次或多次无法处理URL请求(响应状态不在200 ~ 299 间),或者根本就无法响应URL的请求,则系统将判定这一个实例为不健康状态并将其从请求路由表中删除以便于不处理真正的业务请求。

3)当从路由表中移除后,Health check将继续对这一个不健康的实例发送请求,如果这个实例一直没有成功响应,App Service将会重启底层的VM,努力尝试修复它并让它正常工作。

4)如果这一个实例在一个小时内,一直都是unhealthy状态,它将会被新的实例所取代。

5)此外,在向外扩展实例(添加新实例),App Service也会使用Health check中所配置的请求URL,确保当前实例已做好充分准备,正式接受真正业务请求。

注意:Health check不支持 302 重定向。 每小时最多更换一个实例,每个应用服务计划每天最多更换三个实例。

启用 Health Check

No alt text provided for this image
  • 为了启用Health Check,进入App Service的Azure 门户页面,然后选择Health Check目录
  • 选择” **启用 **“按钮,并输入一个有效的URL,可以对应用的健康状态起健康检测的相对路径,例如:/health or /api/health
  • 点击” **保存 **“按钮

注意:Health Check启用或更改会重启当前应用程序。为了尽量减少对生产应用程序的影响,建议配置在Staging slots后,通过交换部署槽的方式发布到生产。

Health Check的配置选项

为了修改默认的Health Check配置选项,可以在应用程序的设置(Application Setting)修改参数:*** WEBSITE_HEALTHCHECK_MAXPINGFAILURES*** 和 WEBSITE_HEALTHCHECK_MAXUNHEALTHYWORKERPERCENT

  • WEBSITE_HEALTHCHECK_MAXPINGFAILURES : 允许值为 2 ~10 。将实例视为unhealthy并将从负载均衡器中移除所需要满足的失败请求次数。例如,当设置为2时,实例将在2次ping失败后被删除(默认值为10)
  • WEBSITE_HEALTHCHECK_MAXUNHEALTHYWORKERPERCENT : 允许值为 0 ~ 100。默认情况下,一次将不超过一般的实例数从负载均衡器中移除,以避免压倒剩余的健康实例。例如,如果应用服务计划扩展到四个实例并且三个不正常,则两个将被排除。 另外两个实例(一个健康和一个不健康)将继续接收请求。 在所有实例都不健康的最坏情况下,不会排除任何实例。 将值修改为 0 到 100 之间,更高的值意味着将删除更多不健康的实例(默认值为 50)。

Health Check的身份认证和安全

Health Check与应用服务的身份验证和授权功能集成。 如果启用了这些安全功能,则不需要其他设置。

如果使用的是自定义的身份验证系统,则健康检查路径(Health Check Path)必须允许匿名访问。

要保护 Health Check Endpoint,应该首先使用 IP 限制、客户端证书或虚拟网络等功能来限制应用程序访问。 可以通过要求传入请求的 User-Agent 匹配 HealthCheck/1.0 来保护Health Check Endpoint。 User-Agent 不能被欺骗,因为请求已经被先前的安全功能保护了。

Health Check Metrics指标

启用 App Service 的Health Check后,可以使用 Azure Monitor 监视站点的运行状况。操作步骤如下:


No alt text provided for this image

常见问题

1: 如果应用程序在单个实例上运行会发生什么?

如果应用程序仅扩展到一个实例并且变得不健康,它不会从负载均衡器中删除,因为这会导致您的应用程序完全停机。 将两个或更多实例扩展到两个或更多实例,以获得Health Check的重新路由优势。 如果应用程序在单个实例上运行,仍然可以使用 Health check 的监控功能来跟踪应用程序的健康状况。

2: 为什么健康检查请求没有显示在前端日志中?

Health Check请求在内部发送到站点,因此该请求不会显示在前端日志中。这也意味着请求的来源为 127.0.0.1,因为它是在内部发送的请求。可以在Health Check Path页面的代码中添加日志语句,以保留Health Check URL何时被 ping 的日志。

3: Health Check请求是通过 HTTP 还是 HTTPS 发送的?

当站点上启用 HTTPS Only 时,Health Check请求将通过 HTTPS 发送。否则,它们将通过 HTTP 发送。

4: 如果在同一个应用服务计划中有多个应用怎么办?

无论应用服务计划中的其他应用如何(最多达到 WEBSITE_HEALTHCHECK_MAXUNHEALTHYWORKERPERCENT 中指定的百分比),运行状况不佳的实例将始终从负载均衡器轮换中删除。

当实例上的应用程序保持不健康状态超过一小时时,仅当所有其他启用Health Check的应用程序也处于不健康状态时,才会更换该实例。未启用Health Check的应用程序将不会被考虑在内。

例如:假设您有两个应用程序启用了Health Check,称为App A 和App B。它们在同一个应用服务计划中,并且该计划扩展到 4 个实例。

  • 如果 App A 在两个实例上变得不健康,负载均衡器将停止向这两个实例上的 App A 发送请求。 假设 App B 是正常的(Healthy),请求仍会在这些实例上路由到 App B。
  • 如果 App A 在这两个实例上保持不健康状态超过一个小时,则只有当 App B 在这些实例上也不健康时,才会替换这些实例。 如果 App B 健康,则不会替换实例。


    No alt text provided for this image

注意:如果在同一个应用服务计划下还有另外一个App Serice,它没有启用Health Check,则该实例将永远不会因为Health Check功能而被替换。所以建议对重要的应用程序单独部署在一个应用服务计划中,并开启Health Check。

5: 如果所有实例都不健康怎么办?

在应用程序的实例不正常的情况下,应用服务将从负载均衡器中删除实例,最多可达 WEBSITE_HEALTHCHECK_MAXUNHEALTHYWORKERPERCENT 中指定的百分比。

在所有实例都不健康的最坏情况下,不会排除任何实例。

6: 测试Health Check的.Net代码 (设置Health Check Path为 /fail

创建一个默认的.NET Core API项目,在 Program.cs 文件中替换默认的Host Builder方法。

  • 通过发送一个/fail的请求,人为的设置请求返回为500。使得Health Check功能认为当前实例为不健康(unhealthy)
  • 在Host启动的时候会自动生产一个GUID,用于标记当前实例。以便于在后续的验证中跟踪实例处理请求的行为或重启动作
  • 启用Health Check功能后,所以实例都会收到并处理 /fail 请求,返回500.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace hellodotnetcore
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            //初始化当前Host实例时候随机生成一个GUID,用于在此后的请求中判断当前时候是否被标记为健康,非健康,回收。
            var instance = Guid.NewGuid();
            //firstFailure来记录第一个失败请求所进入当前实例的时间,firstFailure保存在内存中
            DateTime? firstFailure = null;

            return Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                webBuilder.Configure(configureApp =>
                configureApp.Run(async context =>
                {
                    //当请求URL为fail时候,认为设置返回状态为500,告诉App Service的Health Check功能,当前实例出现故障。
                    if (firstFailure == null && context.Request.Path.Value.ToLower().Contains("fail"))
                    {
                        firstFailure = DateTime.UtcNow;
                    }

                    if (firstFailure != null)
                    {
                        context.Response.StatusCode = 500;
                        context.Response.ContentType = "text/html; charset=utf-8";
                        await context.Response.WriteAsync(
                           $"当前实例的GUID为 {instance}.\n" +
                            $"这个实例最早出现错误的时间是 {firstFailure.Value}.\n\n" +
                            $"根据文档的描述 https://docs.microsoft.com/en-us/azure/app-service/monitor-instances-health-check, 如果一个实例在一直保持unhealthy状态一小时,它将会被一个新实例所取代\n\n" +
                            $"According to https://docs.microsoft.com/en-us/azure/app-service/monitor-instances-health-check, \"If an instance remains unhealthy for one hour, it will be replaced with new instance.\".");
                    }
                    else
                    {
                        context.Response.StatusCode = 200;
                        context.Response.ContentType = "text/html; charset=utf-8";
                        await context.Response.WriteAsync($"当前实例的GUID为 {instance}.\n" +
                            $"此实例报告显示一切工作正常.");
                    }
                })));

            //public static IHostBuilder CreateHostBuilder(string[] args) =>
            //    Host.CreateDefaultBuilder(args)
            //        .ConfigureWebHostDefaults(webBuilder =>
            //        {
            //            webBuilder.UseStartup<Startup>();
            //        });
        }
    }
}

在本地测试以上代码效果如下:

No alt text provided for this image

参考资料

Monitor App Service instances using Health check:https://docs.azure.cn/zh-cn/app-service/monitor-instances-health-check

当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!

分类: 【Azure 应用服务】

标签: App Service, Health Check

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容