Kubernetes Pod通过TCP连接正常关闭(春季启动)

时间:2020-02-18 08:11:58

标签: spring-boot kubernetes azure-kubernetes horizontal-pod-autoscaling

我将服务托管在湛蓝的云上,有时我没有任何明显的原因收到“ BackendConnectionFailure”,经过调查后,在大多数情况下,我发现此异常与自动缩放(按比例缩小)之间存在关联。 / p>

根据文档的终止宽限期,默认情况下为30秒。吊舱将标记为已终止,并且负载平衡器将不再考虑该吊舱,因此不再收到任何请求。据此,如果我的服务花费的时间少于30秒,则我不需要在应用程序中使用prestop钩子或任何特殊的实现(如果我做错了,请纠正我)。

如果上一段是正确的,为什么这种例外发生相对频繁?我的想法是,当吊舱标记为已终止并且负载平衡器不再向吊舱发送请求时,它应该这样做。

编辑1:

架构就是这样

客户端->防火墙(天蓝色)-> API(天蓝色APIM)->微服务(春季启动)->后端(第三方)或天蓝色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

3 个答案:

答案 0 :(得分:1)

默认为Spring Boot doesn't do graceful termination

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

如果您到达宽限期的结尾,那么所有内容都会被硬重置。

Kubernetes

When a pod is deleted in k8s,从服务中删除Pod端点的操作是在向容器发送SIGTERM信号的同时触发的。

这时将重新配置群集节点,以删除将 new 流量引导到Pod的所有规则。到Pod /容器的任何现有TCP连接都将保持连接跟踪,直到被客户端,服务器或网络堆栈关闭为止。

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

应用

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

  • 允许运行中的交易完成
  • 需要进行任何应用程序清理
  • 为了以防万一,请停止接受新连接
  • 关闭所有可能的非活动连接(保留活动请求,websocket)

在某些情况下,您可能无法处理(取决于客户端)

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

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

有关更多春季引导信息,请参见:

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

答案 1 :(得分:0)

如果需要,您可以使用preStop睡眠。将Pod立即从服务端点中删除后,端点更新要发送到每个节点并更新iptables仍需要花费时间(10-100ms)。

答案 2 :(得分:0)

当您的应用程序从Pod终止接收到SIGTERM时,它需要首先停止报告它已准备就绪(readinessProbe失败),但是仍然可以处理来自客户端的请求。一段时间后(取决于您的readinessProbe设置),您可以关闭该应用程序。

对于Spring Boot,有一个小型库正是这样做的:springboot-graceful-shutdown