您是否知道(如果可能)如何为spring boot微服务中的特定端点保留线程/内存?
我有一个微服务接受通过Spring MVC的 HTTP请求,这些请求会触发对第三个系统的http调用,有时会部分退化,而且响应速度很慢。我无法减少超时时间,因为有些调用本质上非常慢。
我启用了spring-boot-actuator /health
端点,我将其用作 livenessProbe
中的容器< strong> kubernetes集群。有时,当第三个系统降级时,微服务不响应/health
端点,kubernetes重新启动我的服务。
这是因为我使用 RestTemplate进行HTTP调用,因此我不断创建新线程,并且JVM开始出现内存问题。
我考虑过一些解决方案:
实现高可用性“/ health”端点,保留线程或类似内容。
使用异步http客户端。
实施断路器。
配置我使用的每个第3个端点的自定义超时。
创建其他小型服务(golang)并将其部署在同一个pod中。该服务将处理活体探测。
将服务迁移/重构为小型服务,也可能与Vert.x,go等其他框架/语言一起迁移/重构
您怎么看?
先谢谢。
答案 0 :(得分:1)
我有一个原型正好解决了这个问题:SpringBoot允许100%的可用线程填充公共网络请求,而/ health终端节点对于AWS负载均衡器来说是不可访问的,从而使服务脱机,以为它不健康。不健康和繁忙之间是有区别的……健康不仅是进程运行,端口监听,表面检查等,还需要“深度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
答案 1 :(得分:0)
听起来你的微服务应该仍然响应健康检查/health
whilist返回第三服务的结果。
我将使用Vert.x-Web构建一个异步http服务器,并在修改好代码之前尝试测试。创建两个端点。在回复“你好”之前,/health
检查和/slow
调用只是睡觉()5分钟。在minikube或您的群集中部署它,看看它是否能够在其他http请求上休眠时响应运行状况检查。
答案 2 :(得分:0)
执行器运行状况端点在使用Spring Boot时非常方便-在这种情况下,这实在太方便了,因为它执行了比活度探测器所必需的更深入的运行状况检查。为了准备就绪,您想做更深入的检查,而不是活泼性。这个想法是,如果Pod有点不堪重负并且无法就绪,那么它将从负载平衡中退出并喘口气。但是,如果失败,它将重新启动。因此,您只需要进行最少的活度检查(Should Health Checks call other App Health Checks)。通过同时使用执行器健康状况,繁忙的Pod可能无法呼吸,因为它们首先被杀死。 kubernetes在执行这两个探测时会定期调用http端点,这进一步加剧了您的线程使用问题(请考虑探测上的periodSeconds)。
根据您的情况,您可以定义活动命令而不是http探针-https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-a-liveness-command。该命令仅可以检查Java进程是否正在运行(有点类似于您的基于go的探测建议)。
在许多情况下,使用执行器来保持活动状态会很好(请考虑在线程之前遇到不同约束的应用程序,如果您使用反应堆进行异步/非阻塞操作,情况就是这样)。您所在的位置可能会引起问题-执行器对诸如消息代理之类的依赖项进行可用性的探查可能是另一个原因,您需要重新启动过多(在这种情况下是首次部署)。