对于运行状况检查失败,我应该使用哪个 HTTP 状态代码?

Posted

技术标签:

【中文标题】对于运行状况检查失败,我应该使用哪个 HTTP 状态代码?【英文标题】:Which HTTP status code should I use for a health-check failure? 【发布时间】:2014-10-12 21:33:59 【问题描述】:

我正在实现一个/_status/ 端点,它会对我们数据库中的数据进行一些完整性检查。

例如,我们正在收集测量值,如果最新测量值超过一个小时,状态应该会变为“不良”。

我想将 Pingdom 指向此 URL,以利用他们的警报基础设施并在出现问题时告诉我们。

在“良好”状态下,我将提供具有 HTTP 200 OK 状态的 html 页面。但是“坏”的适当 HTTP 状态代码是什么?还是不通过状态码而是通过 HTML 内容来传达此信息更正确?

谢谢!

【问题讨论】:

你的“坏”状态是服务器故障的结果吗?如果是这样,500 可能是合适的 并非如此,这通常是后端处理作业失败的结果。服务器、数据库和一切都运行良好但其中的数据“坏”是很合理的。 抱歉 Paul,我应该说“服务故障”而不是“服务器故障” tools.ietf.org/html/draft-inadarei-api-health-check-00 已起草 RFC 以标准化这些类型的响应。然后感兴趣的是 /health 端点和 Content-Type: application/vnd.health+json 【参考方案1】:

如果您的数据“坏”是因为服务失败(即使这是后端作业失败),那么 HTTP 500 似乎是一个有效的响应。它表明某物,某处坏了。

不是很具体,你只是耸了耸肩说:

500(内部服务器错误)状态码表示服务器 遇到了阻止它实现的意外情况 请求。

ietf rfc7231

【讨论】:

但是,在另一端,您成功地给出了服务的状态。所以请求本身是成功的。 500 表示响应请求的问题,而不是整个服务的问题。如果您可以成功提供状态,则情况并非如此。 我不认为 500 是这里最合适的代码。 500 用于未处理的服务器异常或不可完成的请求。但是在这种情况下,服务器能够成功完成健康检查并且没有发生未知错误,所以我认为应该使用比 500 更细粒度的代码。 @Tommy,您对 503 响应感觉如何? @ShaunP 如果 OP 的运行状况检查脚本依赖于某些外部事物,例如数据库,并且无法访问该数据库,我将使用 503。 (503 下游不可到达)。请注意,503 表示“稍后在相同情况下再试一次,我可能会正常工作”。这不是“永久性错误”,它是指可能是暂时性的错误。【参考方案2】:

我们刚刚在小组中进行了类似的讨论。出于我们的目的,我们决定 HTTP 响应代码应该报告您的服务器成功或失败响应请求。对于 GET,这意味着您是否可以响应请求的资源。在这种情况下,请求的资源是健康报告,因此只要您成功返回该资源,它就应该是 200 响应。

我们将返回 JSON 以进行健康检查,并将***“isHealthy”字段设置为 true 或 false。我们的负载均衡器和其他监视器将解析 JSON 并使用此字段来确定系统是否健康。

如果您不想在监视器中解析 JSON,您可以尝试放置一个自定义响应标头来指示系统的二进制运行状况,例如 System-Health: trueSystem-Health: false。获得可以检查这一点的监视器可能会更好。

如果您真的想使用响应代码,我会推荐一个名为“health”之类的附加端点,它在健康时返回“204 No Content”,并返回“404 Not Found”不健康的时候。在这种情况下,由 URL 定义的资源象征性地代表系统的健康状况,因此如果它健康,您就可以返回成功的响应。如果它不健康,那么就找不到它的健康状况,因此会出现 404。

【讨论】:

对此进行了一些后续讨论,我们认为 4xx 错误实际上并不合适,因为它们旨在指示客户端错误,而这里不是这种情况。 5xx 错误更适合表示不健康。这仍然可能与尝试提供健康检查的错误混为一谈,但这可能没问题,因为它仍然表明服务器上存在问题。我认为理想的情况是 JSON(或其他结构化数据)的健康报告,无论健康与否都是 200 响应,并依靠健康报告的内容来指示系统的健康状况。 这个推理是不正确的。 HTTP 状态码与服务器是否能够处理请求无关。响应被发回这一事实表明服务器能够处理请求。 HTTP 状态代码用于指示处理的结果。处理健康检查的结果是健康的或不健康的。可以使用 2xx 状态代码指示健康的结果。不健康的结果可以用 5xx 表示。不健康的服务器无法处理未来的请求以提供正确的结果。因此,5xx。 服务器定义了资源的含义。当服务器不健康时,服务器可以将其定义为客户端错误以询问健康信息。 409 冲突特别合适。【参考方案3】:

嗯...这是一个老问题,但我最终到了这里,所以我想我会在这里给我两分钱: 如果一切正常,应该返回 2xx 似乎很清楚

如果健康不OK,我认为应该返回一个5xx的结果(4xx表示客户端在请求中有问题;2xx和3xx在某种程度上都是成功的)。

我认为 5xx 是正确的,因为这是一个回答整个服务状态的特殊请求。此外,因为大多数负载均衡器都提供基于响应代码的活跃度检查,但并非所有负载均衡器都提供解析更复杂负载的方法(除了可能会使检查变得脆弱的 RegExp 匹配)。

我同意 @Julien 的观点,即 500(特别是)似乎不合适,我们已决定 503 Service Unavailable

503 似乎适合以下几个原因:

这是一个 5xx 系列结果代码,表示服务器端正在发生某些事情。 它具有暂时性,表明它可能会恢复。

【讨论】:

阅读tools.ietf.org/html/rfc7231#section-6.6.1 我感觉503 是指过载问题。因此我更喜欢 500【参考方案4】:

如果您要求健康并且服务器状态不健康,我偏爱 409 Conflict ,“表明由于资源当前状态存在冲突,无法处理请求”。

有些人可能会反对,如果您可以响应,则可以处理请求,但我不同意。每个错误消息都是一个响应。服务器定义资源语义。如果您请求好消息资源并且服务器响应“这里是坏消息”,它没有给您它定义在该资源上提供的内容。

在实践中,说 2**="up" 4**="down" 和管道请求计数到可用性指标中并让负载平衡器根据响应代码从其池中删除服务器要容易得多。想出一些方法来争辩说“嘿,我们告诉过你一些事情,所以 200 OK”对我来说就像错过了树木的福雷斯特。

【讨论】:

以上是关于对于运行状况检查失败,我应该使用哪个 HTTP 状态代码?的主要内容,如果未能解决你的问题,请参考以下文章

AWS Elastic Beanstalk 运行状况检查偶尔失败

ECS 服务的 AWS 网络负载均衡器运行状况检查失败

Terraform 创建了 AWS ECS 基础设施:运行状况检查一直失败

如何在Elastic Load Balancer运行状况检查中获取302重定向的URL?

Terraform AWS LB 运行状况检查失败

如何找出 ECS 运行状况检查失败的原因?