Kubernetes 活性 - 为具有 Spring 引导的特定端点保留 threads/memory
Kubernetes liveness - Reserve threads/memory for a specific endpoint with Spring Boot
您知道(如果可能的话)如何在 spring 启动微服务中为特定端点保留 threads/memory 吗?
我有一个 微服务 通过 Spring MVC 接受 HTTP 请求,这些请求会触发对 3rd system,有时会部分降级,响应很慢。我无法减少超时时间,因为有些调用天生就很慢。
我启用了 spring-boot-actuator /health
端点,我像使用容器一样使用它 livenessProbe
在 kubernetes 集群中。有时,当第三个系统降级时,微服务不响应 /health
端点并且 kubernetes 重新启动我的服务。
这是因为我正在使用 RestTemplate 进行 HTTP 调用,所以我不断地创建新线程,并且 JVM 开始出现内存问题。
我想过一些解决办法:
实施高可用性“/health”端点、保留线程或类似的东西。
使用异步 http 客户端。
实施断路器。
为我使用的每个第三端点配置自定义超时。
创建其他小服务(golang)并将其部署在同一个 pod 中。此服务将处理 liveness 探测。
Migrate/Refactor 服务到小型服务,也许还有其他 framework/languages,如 Vert.x、go 等
你怎么看?
听起来您的微服务仍应响应运行状况检查 /health
whilist 从其调用的第三个服务返回结果。
我会用 Vert.x-Web 构建一个异步 http 服务器,并在修改您的好代码之前尝试测试。创建两个端点。 /health
检查和一个 /slow
调用,它只是 sleeps() 大约 5 分钟,然后用 "hello" 回复。将其部署在 minikube 或您的集群中,看看它是否能够在休眠其他 http 请求时响应健康检查。
我有一个原型刚刚解决了同样的问题:SpringBoot 允许 100% 的可用线程被 public 网络请求填满,导致 AWS 负载均衡器无法访问 /health 端点,这会敲击离线服务认为它不健康。不健康和忙碌之间是有区别的……健康不仅仅是一个进程运行、端口监听、表面检查等——它需要是一个"deep ping"来检查它和它的所有依赖项是可操作的,以便返回自信的健康检查响应。
我解决这个问题的方法是生成两个新的自动装配组件,第一个为 Jetty 配置固定的、可配置的最大线程数(确保你的 JVM 分配了足够的内存来匹配),以及第二个是在每个请求开始和完成时保留一个计数器,如果计数接近上限即 maxThreads - reserveThreads,则抛出一个映射到 HTTP 429 TOO MANY REQUESTS 响应的异常。然后我可以将 reserveThreads 设置为我想要的任何值,并且 /health 端点不受请求计数器的约束,确保它始终能够进入。
我只是四处寻找其他人是如何解决这个问题的,发现你的问题有同样的问题,到目前为止还没有看到任何其他可靠的东西。
通过应用程序属性文件配置 Jetty 线程设置:
http://jdpgrailsdev.github.io/blog/2014/10/07/spring_boot_jetty_thread_pool.html
执行器运行状况端点在 Spring 引导时非常方便 - 在这种情况下几乎太方便了,因为它进行的运行状况检查比您在活动探测中所需要的要深入。为了准备就绪,你想做更深入的检查而不是活跃度。这个想法是,如果 Pod 有点不堪重负并且无法就绪,那么它将从负载平衡中退出并获得喘息机会。但是,如果它的活性失败,它将重新启动。因此,您只需要最少的活动检查 ()。通过为两者使用执行器健康状况,您忙碌的 Pods 无法在他们先被杀死时喘口气。并且 kubernetes 在执行这两个探测时会定期调用 http 端点,这会进一步导致您的线程使用问题(请考虑探测器上的 periodSeconds)。
对于您的情况,您可以定义活动命令而不是 http 探测 - https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-a-liveness-command。该命令可以只检查 Java 进程是否为 运行(有点类似于您基于 go 的探测建议)。
在许多情况下,使用执行器来实现活跃性会很好(想想在线程之前遇到不同约束的应用程序,如果您使用反应式堆栈 async/non-blocking 就会遇到这种情况)。你的是一个可能导致问题的地方 - 执行器对依赖项(如消息代理)的可用性的探测可能是另一个你过度重启的地方(在这种情况下是第一次部署)。
您知道(如果可能的话)如何在 spring 启动微服务中为特定端点保留 threads/memory 吗?
我有一个 微服务 通过 Spring MVC 接受 HTTP 请求,这些请求会触发对 3rd system,有时会部分降级,响应很慢。我无法减少超时时间,因为有些调用天生就很慢。
我启用了 spring-boot-actuator /health
端点,我像使用容器一样使用它 livenessProbe
在 kubernetes 集群中。有时,当第三个系统降级时,微服务不响应 /health
端点并且 kubernetes 重新启动我的服务。
这是因为我正在使用 RestTemplate 进行 HTTP 调用,所以我不断地创建新线程,并且 JVM 开始出现内存问题。
我想过一些解决办法:
实施高可用性“/health”端点、保留线程或类似的东西。
使用异步 http 客户端。
实施断路器。
为我使用的每个第三端点配置自定义超时。
创建其他小服务(golang)并将其部署在同一个 pod 中。此服务将处理 liveness 探测。
Migrate/Refactor 服务到小型服务,也许还有其他 framework/languages,如 Vert.x、go 等
你怎么看?
听起来您的微服务仍应响应运行状况检查 /health
whilist 从其调用的第三个服务返回结果。
我会用 Vert.x-Web 构建一个异步 http 服务器,并在修改您的好代码之前尝试测试。创建两个端点。 /health
检查和一个 /slow
调用,它只是 sleeps() 大约 5 分钟,然后用 "hello" 回复。将其部署在 minikube 或您的集群中,看看它是否能够在休眠其他 http 请求时响应健康检查。
我有一个原型刚刚解决了同样的问题:SpringBoot 允许 100% 的可用线程被 public 网络请求填满,导致 AWS 负载均衡器无法访问 /health 端点,这会敲击离线服务认为它不健康。不健康和忙碌之间是有区别的……健康不仅仅是一个进程运行、端口监听、表面检查等——它需要是一个"deep ping"来检查它和它的所有依赖项是可操作的,以便返回自信的健康检查响应。
我解决这个问题的方法是生成两个新的自动装配组件,第一个为 Jetty 配置固定的、可配置的最大线程数(确保你的 JVM 分配了足够的内存来匹配),以及第二个是在每个请求开始和完成时保留一个计数器,如果计数接近上限即 maxThreads - reserveThreads,则抛出一个映射到 HTTP 429 TOO MANY REQUESTS 响应的异常。然后我可以将 reserveThreads 设置为我想要的任何值,并且 /health 端点不受请求计数器的约束,确保它始终能够进入。
我只是四处寻找其他人是如何解决这个问题的,发现你的问题有同样的问题,到目前为止还没有看到任何其他可靠的东西。
通过应用程序属性文件配置 Jetty 线程设置: http://jdpgrailsdev.github.io/blog/2014/10/07/spring_boot_jetty_thread_pool.html
执行器运行状况端点在 Spring 引导时非常方便 - 在这种情况下几乎太方便了,因为它进行的运行状况检查比您在活动探测中所需要的要深入。为了准备就绪,你想做更深入的检查而不是活跃度。这个想法是,如果 Pod 有点不堪重负并且无法就绪,那么它将从负载平衡中退出并获得喘息机会。但是,如果它的活性失败,它将重新启动。因此,您只需要最少的活动检查 (
对于您的情况,您可以定义活动命令而不是 http 探测 - https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-a-liveness-command。该命令可以只检查 Java 进程是否为 运行(有点类似于您基于 go 的探测建议)。
在许多情况下,使用执行器来实现活跃性会很好(想想在线程之前遇到不同约束的应用程序,如果您使用反应式堆栈 async/non-blocking 就会遇到这种情况)。你的是一个可能导致问题的地方 - 执行器对依赖项(如消息代理)的可用性的探测可能是另一个你过度重启的地方(在这种情况下是第一次部署)。