当前位置: 首页 > 后端技术 > Node.js

java容器为什么推荐使用ExitOnOutOfMemoryError

时间:2023-04-03 19:58:15 Node.js

前言好久没写文章了。之所以今天突发奇想,是因为昨天有一个情况:我们公司某手机APP后端的用户(客户)微服务发生内存泄漏。导致OutOfMemoryError,但是由于我们精心优化的openjdk容器参数,这种故障是用户完全察觉不到的。那么我们该怎么做呢?我们都知道HeapDumpOnOutOfMemoryErrorVSExitOnOutOfMemoryError,部署在传统虚拟机上的Java实例。为了更好的分析问题,一般需要加上参数:-XX:+HeapDumpOnOutOfMemoryError。加上这个参数后,如果发生内存溢出,会自动生成一个HeapDump,后面我们可以得到这个HeapDump,更准确不过,“大人,时代变了!”容器技术的发展给传统的运维模式带来了巨大的挑战。这个挑战是革命性的:传统应用程序是“永久性的”,而容器Pod是“短暂而暂时的存在”。传统的应用程序扩展相对困难,而容器扩展则如丝般顺滑。传统应用运维模型的重点是:“定位问题”vs容器运维模型是:传统应用的“快速恢复”一个instance报HeapDumpError,少一个vsHeapDumpshutdown后容器可以自动启动,以及已达到指定副本数……简单总结一下,使用容器平台后,我们的工作趋向于:遇到故障就迅速失效,遇到故障就迅速失效恢复要尽量让用户“意识不到”故障。因此,对于Java应用容器,我们也必须进行优化来满足这种需求。以OutOfMemoryError故障为例:遇到故障时快速失败,即尽可能“快速退出,快速终止”,在有问题的java应用容器实例退出后,新实例快速开始填充;“快退出,快终止”,配合LB,退出和冷启动过程中不会分发用户请求。-XX:+ExitOnOutOfMemoryError恰到好处这个要求:传递这个参数时,JVM会在抛出OutOfMemoryError时立即退出。如果你想终止应用程序,你可以传递这个参数。细节让我们重温故障:“我司某手机APP后端用户(客户)微服务内存泄漏,导致OutOfMemoryError。”客户应用总结如下:stateless通过Deployment部署,6个副本通过SVC提供服务完整流程如下:6个副本,其中1个出现OutOfMomoryError,因为副本的jvm参数配置为:-XX:+ExitOnOutOfMemoryError,本实例(PID为1)的JVM立即退出。因为pid1进程退出,pod立即处于Terminating状态,变为:Terminated。同时,客户的SVC负载均衡会从SVC负载均衡中移除副本,用户请求不会分发到该节点。K8S检测到副本数与Deploymentreplicas不一致,重新启动1个副本。ReadinessProbe的新部分通过检测后,客户的SVC负载均衡器会将这个新副本添加到负载均衡器中以接收用户请求。在这个过程中,用户基本上是“意识不到后台故障”的。当然,要做到这一点,其实JVM参数和启动脚本中有很多细节和门槛。例如:启动脚本应该是:execjava....$*有机会再写一篇分享新问题上一章我们解释了“为什么Java容器推荐使用ExitOnOutOfMemoryError而不是HeapDumpOnOutOfMemoryError”,但是细心的朋友也会发现,新的配置会也会带来新的问题,比如:JVM在fullgc->OutOfMemoryError期间,但是用户体验还是会下降,怎么会“不知故障”呢?用ExitOnOutOfMemoryError代替HeapDumpOnOutOfMemoryError,那怎么能我定位到问题的根源并解决了?这两个参数一起使用不是更好吗??这些其实可以通过其他方式解决:在JVM的fullgc->OutOfMemoryError期间,用户体验还是会下降。它怎么能“对错误不敏感”呢?答:配置合理的ReadinessProbe,只要ReadinessProbe检测失败,K8S会自动将该节点从SVC中移除。那么就合理了这里的ReadinessProbe是指当应用程序不可用时,ReadinessProbe检测一定会失败。所以一般不能检测某个端口是否在监听,而应该检测对应的API是否正常。如下。答:通过PrometheusJVMExporter+Prometheus+AlertManger,配置合理的AlertRule。例如:“过去X时间,GC总时间>5s”报警,报警后提前人工干预。将“HeapDumpOnOutOfMemoryError”替换为“ExitOnOutOfMemoryError”,那么如何定位问题根源及解决方法呢?这两个参数一起使用不是更好吗?答:目的是“快速退出,快速终止”。毕竟做HeapDump是需要时间的,这期间可能会造成体验下降。所以只有“ExitOnOutOfMemoryError”,退出越快越好。答:对于分析问题,可以通过其他方式进行分析,比如嵌入“Tracingagent”进行Tracing监控,在故障发生时通过痕迹分析定位根因。PrometheusAlertrulegctime告警后,Manuallydoheapdump.readinessProbe:httpGet:path:/actuator/infoport:8088scheme:HTTPinitialDelaySeconds:60timeoutSeconds:3periodSeconds:10successThreshold:1failureThreshold:3复制代码总结新技术带来新变化,我们需要站在开发的角度看“最佳实践,最佳配置”。