【问题标题】:Requests get dropped during springboot service pod rollout在 springboot 服务 pod 推出期间请求被丢弃
【发布时间】:2021-10-27 15:25:16
【问题描述】:

我正在使用 Kubernetes 集群和 docker。当我部署 java 服务 [springboot] 时,一些请求被丢弃(几秒钟)并出现以下错误。

exception=org.springframework.beans.factory.BeanCreationNotAllowedException:创建名为“控制器”的 bean 时出错:当此工厂的单例处于销毁状态时,不允许创建单例 bean(不要在销毁方法中从 BeanFactory 请求 bean实现!),stackTrace=[org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() at line: 208]

我已经在使用 livenessProbe 和 readinessProbe。 Java 版本:12 SpringBoot 版本:2.1.5.RELEASE Hibernate 版本:带有 Postgres DB 的 2.4.3

据我所知,这是由于在执行某些请求时关闭应用程序上下文而发生的。理想情况下,它不应该是。

有人可以帮忙吗?

【问题讨论】:

  • 您应该将您的 k8s 平台设置为仅将请求路由到有效的运行实例;听起来正在退役的实例并未从请求定位中删除。
  • 请提供足够的代码,以便其他人更好地理解或重现问题。

标签: java spring-boot docker kubernetes


【解决方案1】:

问题实际上不是 springboot,而是 Kubernetes 停止 Pod 的方式。 当您的旧部署/副本中的 pod 被终止(或者实际上设置为“终止”状态)时,会同时发生两件事:

A) pod 已从服务端点中移除,因此它不再接收新请求

B) pod 容器获得 SIGTERM,因此应用可以正常关闭

所以您在这里看到的基本上是在上下文关闭时正在处理的活动请求(正如您已经发现的那样)

有(至少)两种解决方案:

1 在 kubernetes pod 定义中:

Kubernetes pod 可以配置一个 pre-stop 钩子,在 A 和 B 之间执行命令。 根据您的应用程序,几(毫秒)秒的简单“睡眠”就足够了,让应用程序有足够的时间在关闭之前完成当前请求。 来自谷歌的不错的文档更详细: https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace

2 在 SpringBoot 中:

您可以让 Java 在收到关闭中断时等待完成正在运行的任务。 这是(恕我直言)在这里很好地解释: https://www.baeldung.com/spring-boot-graceful-shutdown

注意:kubernetes 默认的正常关闭超时是 30 秒,然后 Pod 被强制删除。但像往常一样,您可以在terminationGracePeriodSeconds 中配置此超时(也在 (1) 中的 google 博客中进行了描述

【讨论】:

    猜你喜欢
    • 2016-05-13
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多