我们在 Amazon EC2 上的 k8s 上运行 spring-boot 微服务,使用 undertow 作为我们的嵌入式 Web 服务器。
每当 - 无论出于何种原因 - 我们的下游服务被传入的请求淹没,并且下游 pod 的工作线程队列变得太大(我已经看到这个问题发生在 400 左右(,然后 spring-boot 完全停止处理排队的请求,应用程序进入沉默。
通过 JMX 监控队列大小,我们可以看到,随着 IO 工作线程排队的请求越来越多,队列大小会继续增长 - 但此时,任何工作线程都不会处理排队的请求。
我们看不到任何日志输出或任何指示为什么会发生这种情况的内容。
此问题会向上游级联,瘫痪的下游 Pod 会导致上游 Pod 中的流量遇到相同的问题,并且它们也会变得无响应 - 即使我们关闭了通过 API 网关的所有传入流量也是如此。
为了解决这个问题,我们必须停止上游的传入流量,然后杀死所有受影响的 Pod,然后再将它们大量恢复并重新打开流量。
有人对此有任何想法吗? 这是预期行为吗? 如果是这样,我们如何在队列大小变得太大并终止服务之前建立暗流拒绝连接? 如果不是,是什么导致了这种行为?
非常感谢。 亚伦。
我不完全确定调整 Spring 引导版本/嵌入式 Web 服务器是否可以解决此问题,但以下是如何使用 Kubernetes/Istio 扩展它。
- 活体探针
如果 livenessProbe 配置正确,那么 Kubernetes 会在 Pod 不处于活动状态时重新启动它们。 https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-a-liveness-http-request
- 水平吊舱自动缩放器
根据CPU 利用率或自定义指标增加/减少 Pod 的副本数。 https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
- 垂直吊舱自动缩放器
根据负载增加/减少 POD 的 CPU/RAM。 https://cloud.google.com/kubernetes-engine/docs/concepts/verticalpodautoscaler
- 集群自动缩放器
根据负载增加/减少集群中的节点数。 https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
- Istio 限速和重试机制
限制服务将接收的请求数量,并对无法执行的请求具有重试机制 https://istio.io/docs/tasks/traffic-management/request-timeouts/https://istio.io/docs/concepts/traffic-management/#network-resilience-and-testing