2

我在天蓝色的云上托管我的服务,有时我会在没有任何明显原因的情况下得到“BackendConnectionFailure”,经过调查,在大多数情况下,我发现此异常与自动缩放(缩小)之间几乎同时存在相关性。

根据文档,终止宽限期默认为 30 秒,就是这种情况。pod 将被标记为终止,负载均衡器将不再考虑它,因此不再接收请求。据此,如果我的服务花费的时间远少于 30 秒,则我的应用程序中不需要 prestop 挂钩或任何特殊实现(如果我错了,请纠正我)。

如果上一段是正确的,为什么这个异常会比较频繁的发生呢?我的想法是当 pod 被标记为终止并且负载均衡器不再向 pod 转发请求时,它应该这样做。

编辑1:

架构就是这样

客户端 -> 防火墙(azure) -> API(azure APIM) -> 微服务(Spring boot) -> 后端(第三方) 或 Azure RDB,具体取决于服务

我认为异常来自 APIM,我发现此异常有两种模式:

  1. Message The underlying connection was closed: The connection was closed unexpectedly. Exception type BackendConnectionFailure Failed method forward-request

Response time 10.0 s

  1. Message The underlying connection was closed: A connection that was expected to be kept alive was closed by the server. Exception type BackendConnectionFailure Failed method forward-request

Response time 3.6 ms

4

3 回答 3

3

Spring Boot默认情况下不进行优雅终止

Spring Boot 应用程序及其应用程序容器(不是 linux 容器)可以控制终止宽限期内现有连接发生的情况。正在使用的协议以及客户端如何对“关闭”做出反应也可以发挥作用。

如果您到了宽限期结束,那么一切都会硬重置。

Kubernetes

当在 k8s 中删除 podSIGTERM时,会在向容器发出信号的同时触发从服务中删除 Pod Endpoint 。

此时,集群节点将被重新配置,以删除将流量引导至 Pod 的任何规则。任何与 Pod/容器的现有 TCP 连接都将保持连接跟踪,直到它们被关闭(由客户端、服务器或网络堆栈)。

对于 HTTP Keep Alive 或 HTTP/2 服务,客户端将继续访问同一个 Pod 端点,直到被告知关闭连接(或被强制重置)

应用程序

基本规则是,在 SIGTERM 上,应用程序应该:

  • 允许正在运行的事务完成
  • 是否需要进行任何应用程序清理
  • 停止接受新连接,以防万一
  • 关闭它可以关闭的任何非活动连接(保持活动请求,websockets)

您可能无法处理的某些情况(取决于客户)

  • 在宽限期内未完成请求的保持活动连接无法获取Connection: close标头。它将需要一个 TCP 级别的 FIN 关闭。
  • 一个长传输的慢客户端,以一种 HTTP 传输的方式,这些将不得不等待或强制关闭。

尽管 keepalive 客户端应该遵守 TCP FIN 关闭,但每个客户端的反应都不同。Microsoft APIM 可能很敏感并会产生错误,即使没有对现实世界产生影响。最好在扩展时对您的设置进行负载测试,以查看是否对现实世界产生影响。

有关更多弹簧靴信息,请参阅:

https://github.com/spring-projects/spring-boot/issues/4657 https://github.com/coretin59/spring-boot-graceful-shutdown https://github.com/SchweizerischeBundesbahnen/springboot-graceful-关闭

于 2020-02-19T00:21:38.993 回答
0

如果需要,您可以使用 preStop sleep。虽然 pod 会立即从服务端点中删除,但仍需要时间(10-100 毫秒)将端点更新发送到每个节点并让它们更新 iptables。

于 2020-02-18T10:11:41.380 回答
0

当您的应用程序接收到SIGTERM(来自 Pod 终止)时,它需要首先停止报告它已准备好(失败readinessProbe),但仍会在请求来自客户端时为它们提供服务。一段时间后(取决于您的readinessProbe设置),您可以关闭应用程序。

对于 Spring Boot,有一个小型库可以做到这一点:springboot-graceful-shutdown

于 2020-02-18T12:24:53.217 回答