Out of Memory?别怕!这个Java容器技巧让你的应用永不宕机!

通过dump文件,分析outOfMemoryError的排查过程和排查思路 前段时间发现有一个内存溢出导致java线上服务OOM的问题,通过jvm启动配置增加-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/app/oom的命令,在出现了第二次服务挂掉的时候,拿到了当时的dump文件,以下是我通过dump文件对异常进行梳理的过程。 首先,把服务器的dump文件拉到我本地后,使用jdk自带的jvisualvm装载dump文件 在载入后,我得到了各个类的内存占用情况分析图。如下: 在这个分析图表中,我发 阅读详情

来源:www.cnblogs.com/east4ming/p/17034195.html

为什么 java 容器推荐使用ExitOnOutOfMemoryError而非HeapDumpOnOutOfMemoryError? 今天我们一起来聊聊这个问题。

前言

最近,我们公司的某个应用后端的用户微服务频繁的出现内存泄露,导致OutOfMemoryError,导致经常会发生服务不可用。这对于 toC 场景来说,简直就是灾难性的。

于是,我们决定对 openjdk 的容器参数进行精心优化,通过一些优化,其后面再次发生故障时,对用户完全无感知💪💪💪

adfe577ba4e7eae264626e314d5acbe5.jpeg

那么我们是如何做到的呢?

内存溢出异常时Dump VS 内存溢出时退出

HeapDumpOnOutOfMemoryError VS ExitOnOutOfMemoryError。

在传统的虚拟机环境中部署Java应用时,为了便于问题诊断和分析,通常会在JVM启动参数中加入-XX:+HeapDumpOnOutOfMemoryError。这个参数的作用是在Java虚拟机发生内存溢出(OutOfMemoryError)时,自动触发堆转储(HeapDump)的生成。通过这种方式,开发者和运维人员可以在事后获取到一个详细的堆转储文件,其中包含了内存溢出时的内存使用情况和对象信息。

这个堆转储文件对于分析和定位内存泄漏、内存溢出等问题至关重要。通过分析HeapDump,可以查看到各个对象的内存占用情况,识别出内存使用异常的代码路径,以及追踪到具体的代码行。此外,还可以通过HeapDump来分析垃圾回收(GC)的行为,了解不同垃圾回收代的内存使用情况,以及识别出可能导致GC性能问题的潜在原因。

然而,需要注意的是,生成HeapDump是一个资源密集型的操作,可能会占用大量的磁盘空间,并且可能会延长应用的恢复时间。因此,在配置HeapDump时,还需要考虑磁盘空间的容量和性能影响。此外,为了保护敏感信息,还需要确保HeapDump文件中不包含敏感数据,或者在分析完成后及时删除这些文件。

也就是说,在传统的虚拟机环境中,通过配置-XX:+HeapDumpOnOutOfMemoryError参数,可以在Java应用发生内存溢出时自动生成HeapDump,为后续的问题诊断和分析提供重要的数据支持。但同时,也需要权衡HeapDump对资源的占用和性能影响,并采取相应的安全措施来保护敏感信息。通过综合考虑这些因素,可以更有效地利用HeapDump来提升Java应用的稳定性和性能。

但是,“大人,时代变了!”

容器技术的发展,给传统运维模式带来了巨大的挑战,这个挑战是革命性的:

  1. 传统的应用都是“永久存在的” vs 容器pod是“短暂临时的存在”

  2. 传统应用扩缩容相对困难 vs 容器扩缩容丝般顺滑

  3. 传统应用运维模式关注点是:“定位问题” vs 容器运维模式是:“快速恢复”

  4. 传统应用一个实例报HeapDumpError就会少一个 vs 容器HeapDump shutdown后可以自动启动,已达到指定副本数

  5. ...

简单总结一下,在使用容器平台后,我们的工作倾向于:

  1. 遇到故障快速失败

  2. 遇到故障快速恢复

  3. 尽量做到用户对故障“无感知”

所以,针对Java应用容器,我们也要优化以满足这种需求,以 OutOfMemoryError 故障为例:

  1. 遇到故障快速失败,即尽可能“快速退出,快速终结”

  2. 有问题java应用容器实例退出后,新的实例迅速启动填补;

  3. “快速退出,快速终结”,同时配合LB,退出和冷启动的过程中用户请求不会分发进来。

-XX:+ExitOnOutOfMemoryError 就正好满足这种需求:

传递此参数时,抛出OutOfMemoryError时JVM将立即退出。如果您想终止应用程序,则可以传递此参数。

细节

让我们重新回顾故障:“我们公司的某个手机APP后端的用户(customer)微服务出现内存泄露,导致OutOfMemoryError”

该 customer 应用概述如下:

  1. 无状态

  2. 通过 Deployment 部署,有 6 个副本

  3. 通过 SVC 提供服务

完整的过程如下:

  1. 6 个副本,其中 1 个出现 OutOfMomoryError

  2. 因为副本的 jvm 参数配置有:-XX:+ExitOnOutOfMemoryError,该实例的 JVM(PID 为 1)立即退出。

  3. 因为 pid 1 进程退出,此时 pod 立刻出于 Terminating 状态,并且变为:Terminated

  4. 同时,customer 的 SVC 负载均衡会将该副本从SVC 负载均衡中移除,用户请求不会被分发到该节点。

  5. K8S检测到副本数和 Deployment replicas 不一致,启动1个新的副本。

  6. 待新的部分 Readiness Probe 探测通过,customer 的 SVC 负载均衡将这个新的副本加入到负载均衡中,接收用户请求。

在此过程中,用户基本上是对后台故障“无感知”的。

当然,要做到这些,其实JVM参数以及启动脚本中,还有很多细节和门道。如:启动脚本应该是:exec java ....$*

新的疑问

上面,我们解释了《为什么 Java 容器推荐使用 ExitOnOutOfMemoryError 而非 HeapDumpOnOutOfMemoryError》,但是细心的小伙伴也会发现,新的配置也会带来新的问题,比如:

  1. JVM 从 fullgc -> OutOfMemoryError 这段时间内,用户的体验还是会下降的,怎么会是“故障无感知”呢?

  2. 用ExitOnOutOfMemoryError代替HeapDumpOnOutOfMemoryError,那我怎么定位该问题的根因并解决?2 个参数一起用不是更香么?

这些其实可以通过其他手段来解决:

  • JVM 从 fullgc -> OutOfMemoryError 这段时间内,用户的体验还是会下降的,怎么会是“故障无感知”呢?

答:

在容器化应用的运维实践中,合理配置Readiness Probe对于确保服务的高可用性至关重要。Readiness Probe的主要作用是检测应用是否已经准备好接收流量。当Readiness Probe探测失败时,Kubernetes会自动将该容器实例从服务的负载均衡池中移除,防止未准备好的实例影响整体服务的稳定性和响应时间。

为了实现这一目标,Readiness Probe的配置需要精心设计,以确保在应用不可用时,Probe能够准确反映应用状态。通常,仅仅检查端口是否开放是不够的,因为即使端口开放,应用也可能因为内部错误而无法正常处理请求。因此,更合理的方法是探测应用的特定API端点,这些端点能够更准确地反映应用的实际可用性。例如,可以配置Readiness Probe去调用一个特定的健康检查API,该API会检查应用的内部状态和依赖服务的连通性,从而提供更全面的可用性信息。

除了Readiness Probe,还可以利用Prometheus JVM Exporter、Prometheus监控系统和AlertManager的组合来进一步增强应用的监控和预警能力。通过配置合理的AlertRule,比如设置“在过去X分钟内,GC(垃圾回收)总时间超过5秒”的规则,可以在潜在的性能问题演变成严重故障之前发出告警。这样的告警机制可以帮助运维团队及时发现并介入处理问题,从而避免服务中断或性能下降。

总的来说,通过结合使用Readiness Probe和先进的监控工具,可以有效地提高容器化应用的稳定性和可靠性,确保在应用出现问题时能够快速响应和恢复。这种综合的监控和响应策略,是现代云原生应用运维的最佳实践之一。

  • 用ExitOnOutOfMemoryError代替HeapDumpOnOutOfMemoryError,那我怎么定位该问题的根因并解决?2 个参数一起用不是更香么?

答:

在容器化的应用环境中,我们通常追求的是快速失败和快速恢复,以此来确保服务的高可用性。在Java应用中,当遇到内存溢出(OutOfMemoryError)时,-XX:+ExitOnOutOfMemoryError 参数能够确保JVM立即退出,避免在生成堆转储(HeapDump)时消耗的额外时间,这段时间可能会导致服务体验进一步下降。因此,我们更倾向于使用 ExitOnOutOfMemoryError 来实现快速退出和终结,以最小化对用户体验的影响。

为了在应用出现内存溢出时快速恢复服务,我们可以依赖于Kubernetes的探针机制,特别是就绪探针(Readiness Probe)。通过配置合理的就绪探针,当应用不可用时,探针探测失败,Kubernetes会自动将该节点从服务负载均衡中摘除,确保用户请求不会被分发到不可用的实例。这样的探针配置应该能够准确反映应用的可用性,而不仅仅是检查端口是否在监听,而是应该探测应用的特定API端点是否正常响应。

在问题诊断方面,虽然HeapDumpOnOutOfMemoryError可以生成堆转储文件以供后续分析,但在容器环境中,我们更推荐使用其他监控手段。例如,通过嵌入分布式追踪代理(Tracing agent),我们可以收集和分析故障发生时的追踪信息,从而定位问题的根本原因。此外,结合Prometheus JVM Exporter、Prometheus监控系统和AlertManager,我们可以设置合理的告警规则,如GC总时间超过阈值时触发告警。在告警触发后,运维人员可以手动介入,使用jcmd等命令工具执行堆转储操作,以便进一步分析和解决问题。

各种平衡之后,再来看这个问题。就是在容器化的应用环境中,我们更倾向于使用ExitOnOutOfMemoryError来实现快速的失败和恢复,同时通过监控和探针机制来确保服务的高可用性,并通过其他手段进行问题诊断,而不是依赖于在OOM时生成堆转储。这种方法更符合容器化应用的运维模式,有助于实现快速响应和问题恢复。

readinessProbe:  
  httpGet:  
    path: /actuator/info  
    port: 8088  
    scheme: HTTP  
  initialDelaySeconds: 60  
  timeoutSeconds: 3  
  periodSeconds: 10  
  successThreshold: 1  
  failureThreshold: 3

在容器时代,推荐使用-XX:+ExitOnOutOfMemoryError而非-XX:+HeapDumpOnOutOfMemoryError的主要原因与容器技术的特点和运维模式的转变有关。以下是几个关键点:

  1. 快速失败与快速恢复:容器技术的一个核心优势是其快速的启动和停止能力。在容器环境中,当应用出现内存泄漏或溢出时,快速失败并迅速启动新实例可以更快地恢复服务,而不是花费时间生成堆转储文件进行问题分析。

  2. 容器的短暂性:与传统的虚拟机部署相比,容器被设计为短暂和临时的存在。它们通过快速的扩缩容来适应负载变化,而不是长期运行单个实例。

  3. 用户无感知:在容器环境中,通过配置如Kubernetes的Readiness Probe和Liveness Probe,可以确保在实例出现问题时,不会将用户请求分发到该实例,并且在实例恢复后迅速重新加入服务,实现用户对故障的无感知。

  4. 避免在OOM期间的资源消耗:生成堆转储(HeapDump)是一个资源密集型操作,可能会导致服务进一步恶化或延长故障恢复时间。使用ExitOnOutOfMemoryError可以立即终止进程,避免在OOM情况下继续消耗资源。

  5. 故障分析的其他手段:即使没有堆转储文件,也可以通过其他监控和日志分析工具来定位和分析问题。例如,使用Prometheus JVM Exporter、Prometheus和AlertManager进行监控,可以在GC时间超过阈值时发出告警,从而提前介入处理问题。

总结

新的技术带来新的变革,我们需要以发展的眼光看待“最佳实践,最佳配置”。

过去(2016 年以前),针对虚机部署的 Java 的最优参数,在今天来看,并不一定仍是最优解。

-XX:+ExitOnOutOfMemoryError在容器环境中更符合快速恢复和高可用性的需求,而-XX:+HeapDumpOnOutOfMemoryError虽然有助于问题分析,但在容器的快速运维模式下可能不是最佳选择。

推荐全新学习项目

全新基于springboot+vue+vant的前后端分离的微商城项目,包括手机端微商城项目和后台管理系统,整个电商购物流程已经能流畅支持,涵盖商品浏览、搜索、商品评论、商品规格选择、加入购物车、立即购买、下单、订单支付、后台发货、退货等。功能强大,主流技术栈,非常值得学习。

项目包含2个版本:

  • 基于springboot的单体版本

  • 基于spring cloud alibaba的微服务版本

线上演示:https://www.markerhub.com/vueshop

b032ec0e0dfc9cba8ae613472afc84b6.jpeg

从文档到视频、接口调试、学习看板等方面,让项目学习更加容易,内容更加沉淀。全套视频教程约44小时,共260期,讲解非常详细细腻。下面详细为大家介绍:

架构与业务

使用主流的技术架构,真正手把手教你从0到1如何搭建项目手脚架、项目架构分析、建表逻辑、业务分析、实现等。

单体版本:springboot 2.7、mybatis plus、rabbitmq、elasticsearch、redis

微服务版本:spring cloud alibaba 2021.0.5.0,nacos、seata、openFeign、sentinel

前端:vue 3.2、element plus、vant ui

ea9e91f9a2c198972bef6d712bdb7518.png

更多详情请查看:

手把手教学,从0开发前后端微商城项目,主流Java技术一网打尽!

JVM实战(一): dump文件的产生以及执行shell脚本 如何配置jvm参数,在OOM时生成dump文件并执行shell 脚本 阅读详情

相关推荐

向量服务优化:Embedding/Rerank模型共享与GPU资源高效利用

Embedding和Rerank本质上是面向向量检索的通用计算基础设施,其核心原理在于将文本语义映射为稠密向量并完成相关性重排序。技术价值体现在显著降低GPU显存占用、消除重复加载开销、统一预处理逻辑,并支撑高并发低延迟的AI应用底座。典型应用场景包括RAG问答系统、智能搜索、推荐排序及大模型上下文增强等。实践中需规避‘每个项目加载一次模型’的资源浪费陷阱,采用单进程多线程+模型管理器+OpenAI兼容接口的设计范式,结合Docker镜像分层优化与K8s弹性伸缩策略,实现bge-m3、bge-reranke

weixin_33859844的博客 429

HeapDumpOnOutOfMemoryError堆转储实践和一些分析

使用了标志-XX:+HeapDumpOnOutOfMemoryError,JVM会在遇到OutOfMemoryError时拍摄一个“堆转储快照”,并将其保存在一个文件中。 对如下一段代码,【代码1】 /** * @author zk * @Description: * @date 2019-08-01 14:17 */ public class Demo { public...

长河的博客 1万+

Java中的内存溢出异常(OutOfMemoryError)的出现场景及解决方法

除了上述场景外,还可能出现其他导致内存溢出的情况,例如大对象占用过多堆内存、过多的线程占用过多栈内存等。因此,在编写Java应用程序时,应当合理管理内存使用,及时释放不再使用的资源,避免内存溢出异常的发生。本文将介绍一些常见的导致内存溢出异常的场景,并提供相应的源代码示例,同时探讨一些解决方法。由于没有终止条件,递归调用会导致栈内存不断增长,最终抛出StackOverflowError异常(它是Error的子类,但也表示内存溢出)。在上面的示例中,我们动态生成了大量的类,并尝试加载它们。

CdiBug的博客 435

JVM|内存管理:OutOfMemoryError 异常

JVM 内存管理 - OutOfMemoryError 异常分类介绍与演示

三余知行 4819

U3d WebGL使用ToLua

首先我们在编辑器模式下加入Tolua插件,然后配置修改到在编辑器模式下能够正常的运行。 同个U3d 插件Build出WebGL的工程,运行的时候你会发现(有些需要把这个WebGL工程放在一个HttpServer下面,直接本地访问index.html会被拒绝,让你使用http的格式)。 当要加载完的时候会出现 To use dlopen, you need to use Emscripten'...

qq_35267906的博客 2949

投第一篇SCIE英文期刊(详细步骤)

一个投稿SCIE英文期刊的过程

weixin_48849679的博客 1万+

Out of Memory?别怕!这个Java容器技巧让你的应用永不宕机

最近,我们公司的某个应用后端的用户微服务频繁的出现内存泄露,导致,导致经常会发生服务不可用。这对于 toC 场景来说,简直就是灾难性的。于是,我们决定对 openjdk 的容器参数进行精心优化,通过一些优化,其后面再次发生故障时,对用户完全无感知💪💪💪那么我们是如何做到的呢?新的技术带来新的变革,我们需要以发展的眼光看待“最佳实践,最佳配置”。过去(2016 年以前),针对虚机部署的 Java 的最优参数,在今天来看,并不一定仍是最优解。在容器环境中更符合快速恢复和高可用性的需求,而。

tangjieqing的博客 881

BODAS说明书的中文版与相关资料总结

花了三天时间配了控制器的接线口,找了软件安装的一套东西。 又花了一周时间零零散散在网上只找到关于控制器少得可怜的资料: 1.力士乐控制器RC6系列介绍 2.力士乐控制器手册不完整版 3.RC6-9程序下载 力士乐配套的只有德语和英语两版,人工翻译专业文件的价格太惊人,决定自己写一版方便大家。有不正之处欢迎指出。 For these controllers, in the event of an...

我的技术日常 6497

【JVM】Out of Memory 内存溢出排查

记一次OOM排查过程!

Coinker的博客 5427

保姆级教程:在RK3576上配置USB网卡从零到外网访问(附udev规则详解)

本文提供了在RK3576开发板上配置USB网卡的完整教程,涵盖从内核驱动、udev规则到网络路由的全流程。重点讲解了如何利用USB Gadget功能实现高速网络连接,并构建稳定的算力集群,确保多设备间通信及外网访问。

grass的博客 461

深信服AC1000-B1200到手第一步:从开箱到激活上网的保姆级图文指南

本文提供深信服AC1000-B1200企业级行为管理设备的详细开局使用指南,涵盖从开箱验机、物理连接到网络配置、安全加固及设备激活的全流程。通过图文并茂的步骤解析,帮助用户快速完成设备初始化并实现安全上网,特别适合初次接触该设备的网络管理员参考。

weixin_42546392的博客 548

常见内存溢出异常

本文来说下常见内存溢出异常 文章目录概述 概述 在JVM内存区域中,除了程序计数器外,Java虚拟机的其他运行时区域都有可能发生OutOfMemoryError的异常,下面分别给出验证:

wh柒八九的博客 2447

Realtek RTD1319D芯片解析:H.266与AV1双解码的机顶盒SoC

视频编解码技术是数字媒体传输的核心,H.266/VVC作为新一代标准,相比H.265提升50%压缩效率,显著降低带宽需求。其实现原理依赖于专用硬件解码器和并行处理架构,在超高清视频传输领域具有重要价值。Realtek RTD1319D作为首款商用H.266处理器,采用异构计算设计,集成四核ARM CPU和独立视频处理单元,同时支持AV1解码,兼顾市场兼容性。该SoC特别适合4K机顶盒、数字标牌等应用场景,其HDMI 2.1a接口和DVB解调器为超高清内容传输提供完整解决方案。开发时需注意散热设计和内存配置优

weixin_42591413的博客 673

Java虚拟机——OutOfMemoryError异常

通过生成大量的动态类可以,当前的很多主流框架,如Spring、Hibernate对类进行增强的时候,都会使用到CGLib这类字节码技术。*明确允许Java虚拟机自行选择是否支持栈的动态拓展 HotSpot虚拟机是不支持拓展的。

肇秋贰拾捌的博客 1422

Python实战项目2:b站评论采集

本文不对数据采集的过程做探讨,直接上代码。

lyccomcn的博客 3200

10、贝叶斯曲线拟合与预测分布详解

本文详细介绍了贝叶斯曲线拟合与预测分布的核心概念与计算方法。从最大似然估计出发,引入参数的先验分布,推导出后验分布与最大后验估计,并进一步展示如何通过积分获得完整的预测分布。文章解析了预测分布中均值与方差的构成,强调贝叶斯方法在量化不确定性方面的优势,涵盖金融、医疗、气象等实际应用场景。最后总结了操作步骤与未来研究方向,帮助读者系统掌握贝叶斯方法在回归问题中的应用。

android的专栏 106

jvm一般相关配置OutOfMemoryError关参数配置解释

JVM提供了有用的参数来处理 OutOfMemoryError 。在本文中,我们将重点介绍这些JVM参数。在排除OutOfMemoryError故障时,它可能会很方便。这些JVM参数是:1. -XX:HeapDumpOnOutOfMemoryError-XX:HeapDumpPath2. -XX:onAutofmemoryError3. -XX:+ExitOnOutOfMemoryError4. -XX:+CrashOnOutOfMemoryError让我们在本文中详细讨论这些JVM参数。堆转储dump文件

奔跑的蜗牛的博客 4383

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

OutOfMemoryError内存溢出相关的JVM参数

原文在这里: OutOfMemoryError内存溢出相关的JVM参数 JVM提供了很多处理内存溢出的相关参数,本文主要来讲解下这些参数,当你遇到内存溢出的时候可能会对你非常有帮助,这些参数主要有: 1.-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath 2.-XX:OnOutOfMemoryError 3.-XX:+ExitOnOutOfMemor...

若鱼的专栏 7108

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

JVM参数-XX:+HeapDumpOnOutOfMemoryError使用方法

1、配置方法 在JAVA_OPTIONS变量中增加 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${目录}。 例如:export JAVA_OPTS="-Xms2048M -Xmx2048M -Xmn682M -XX:MaxPermSize=96M" 2、参数说明 (1)-XX:+HeapDumpOnOutOfMemoryError参数表示当J...

lusa1314的博客 9万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

-XX:HeapDumpOnOutOfMemoryError 内存溢出

说明: 通过jvm参数-XX:+HeapDumpOnOutOfMemoryError可以让JVM在出现内存溢出时候Dump出当前的内存转储快照。快照格式为java_pid2821.hprof(2821为Java进程号) 参数设置: -XX:+HeapDumpOnOutOfMemoryError :当内存溢出时触发java.lang.OutOfMemo: Java heap space -XX:He...

我是程序媛,我骄傲 1万+
上一篇: 11月后端彻底爆了???
下一篇: 2个GitHub上最近比较火的Java开源项目
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值