Health Endpoint Monitoring Pattern

Health Endpoint Monitoring模式是一种用来监控服务健康状态的模式。

Health Endpoint Monitoring模式通过在应用内额外暴露一个可以进行功能检查的接口来实现,可以由外部工具定期访问暴露在外部的端点来检查服务的状态。该模式可以有效验证服务是否可用。

问题

监控应用的状态通常是一种很好的应用实践。通常来说,也是业务的一个需求。针对一些中间层和共享的服务也同样如此。因为这样可以有效确认服务在正确工作。然而,监控运行在云上面的服务要比监控一般的服务更复杂。举例来说,开发者是没有服务器环境的全部权限的,并且服务通常还会依赖于一些其他平台的服务,监控起来更难。

在基于云环境的应用会受到很多不同因素的影响,比如网络延迟,存储系统的系能和可用性,以及不同云之间的网络带宽等等。服务可能会因为各种各样的原因全部失败,或者某个环节失败掉。因此,开发者必须每隔一段时间就验证一下服务是否正确,以确保应用能够提供保证服务等级协议。

解决方案

一般通过将请求发送到应用端暴露的接口来实现应用Health的监控。应用应该执行一些基本的检查,并且返回应用当前状态的一些信息。

健康检查通常会包含两个基本点:由应用执行的针对服务的状态的检查,以及针对健康检查请求所产生应答的分析。应答的返回code表示了应用的状态,并且,可以额外提供一些他使用的组件或者服务的信息。监控工具或者框架来完成一些服务响应时间的检查。 下图显示了该模式的实现的大概结构:

应用中用来监控服务健康状态的检查可能还会包括以下内容:

很多服务或者工具都是通过提交请求到指定的端点来获取对应的响应,并且通过分析响应结果来监控web应用的配置以及健康状态的。通常来说,创建一个职能仅仅检查系统的服务端点是相对简单的事情。

监控工具所执行的常规检查可以包括如下一些:

当然,从不同的地方来发送请求来执行健康检查,并且对比不同地点的响应时间也是十分有效的。理论上,开发者应该监控距离客户很近的地方的健康检查结果,这样可以获取不同地点更为精确的响应性能的检查结果。除了可以提供一个更强大的检查机制,检查结果可能会影响应用程序的部署位置的选择和是否将其部署在多个数据中心。

测试应该也检查所有的应用实例,这样可以确保无论用户路由到哪一台服务器,应用都是可用的。比如说,如果用户的存储是跨越多个数据仓库的话,监控的程序必须检查所有数据仓库可用性。

实现Health-Endpoint Monitoring的问题和考虑

当实现Health-Endpoint监控模式的时候,需要考虑如下一些点:

同时确保系统本身也对自己进行检查,比如一些自带的测试和内置测试,避免工具对正确的结果做出错误的分析。

何时使用该模式

Health-Endpoint Monitoring模式最适用于以下的一些场景。

使用举例

下面代码的例子中,是从HealthEndpointMonitoring中的HealthCheckController类中截取的。其中包含了一系列的健康检查。

如下代码中的CoreServices方法中,执行了一些列的针对应用中服务的检查。如果所有测试的执行都没有任何错误,方法会返回200(OK)的状态码。如果任何一个测试的方法抛出了异常,放回就会返回500(Internal Error)状态码。方法可以选择性的附带一些额外的错误信息。这些信息可以让监控工具或者框架来使用,分析错误产生的原因。

public ActionResult CoreServices()
{
    try
    {
        // Run a simple check to ensure the database is available.
        DataStore.Instance.CoreHealthCheck();
        // Run a simple check on our external service.
        MyExternalService.Instance.CoreHealthCheck();
    }
    catch (Exception ex)
    {
        Trace.TraceError("Exception in basic health check: {0}", ex.Message);
        // This can optionally return different status codes based on the exception.
        // Optionally it could return more details about the exception.
        // The additional information could be used by administrators who access the
        // endpoint with a browser, or using a ping utility that can display the
        // additional information.
        return new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError);
    }
    return new HttpStatusCodeResult((int)HttpStatusCode.OK);
}

下面的ObscurePath方法展示了你可以从应用配置中读取应用的配置信息,并且以之作为端点来执行测试。下面的代码展示了如何接收一个ID作为参数,并且用之来验证请求。

public ActionResult ObscurePath(string id)
{
    // The id could be used as a simple way to obscure or hide the endpoint.
    // The id to match could be retrieved from configuration and, if matched,
    // perform a specific set of tests and return the result. It not matched it
    // could return a 404 Not Found status.
    // The obscure path can be set through configuration in order to hide the endpoint.
    var hiddenPathKey =
        CloudConfigurationManager.GetSetting("Test.ObscurePath");

    // If the value passed does not match that in configuration, return 403 “Not Found”.
    if (!string.Equals(id, hiddenPathKey))
    {
        return new HttpStatusCodeResult((int)HttpStatusCode.NotFound);
    }

    // Else continue and run the tests...
    // Return results from the core services test.
    return this.CoreServices();
}

下面的TestResponseFromConfig方法展示了如何暴露一个端点,并且基于指定的配置来执行检查。

public ActionResult TestResponseFromConfig()
{
    // Health check that returns a response code set in configuration for testing.
    var returnStatusCodeSetting = CloudConfigurationManager.GetSetting(
        "Test.ReturnStatusCode");
    int returnStatusCode;
    if (!int.TryParse(returnStatusCodeSetting, out returnStatusCode))
    {
        returnStatusCode = (int)HttpStatusCode.OK;
    }
    return new HttpStatusCodeResult(returnStatusCode);
}

相关模式

在考虑实现该模式的时候,可以参考以下的相关信息: