线上问题总结:运行在容器里的springboot应用,出现多次oom

2023-11-05

项目运行环境:

运行环境:k8s+docker+open-jdk11+springBoot
公司的项目都是使用kubernate+docker来管理、运行应用。


问题描述:

发现项目出现多次oom。排查到的原因有两个,1是分配的堆内存太小;2是代码设计原因(之后写出来总结)


原因分析:

进入容器,使用 jhsdb jmap --heap --pid [PID] 查看分配的堆大小
输出结果:

JVM version is 11.0.9.1+1

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 262144000 (250.0MB)
   NewSize                  = 5570560 (5.3125MB)
   MaxNewSize               = 87359488 (83.3125MB)
   OldSize                  = 11206656 (10.6875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 43319296 (41.3125MB)
   used     = 17549536 (16.736541748046875MB)
   free     = 25769760 (24.575958251953125MB)
   40.5120526427761% used
Eden Space:
   capacity = 38535168 (36.75MB)
   used     = 14510800 (13.838577270507812MB)
   free     = 24024368 (22.911422729492188MB)
   37.655992572810376% used
From Space:
   capacity = 4784128 (4.5625MB)
   used     = 3038736 (2.8979644775390625MB)
   free     = 1745392 (1.6645355224609375MB)
   63.51702964469178% used
To Space:
   capacity = 4784128 (4.5625MB)
   used     = 0 (0.0MB)
   free     = 4784128 (4.5625MB)
   0.0% used
tenured generation:
   capacity = 95477760 (91.0546875MB)
   used     = 69527288 (66.30638885498047MB)
   free     = 25950472 (24.74829864501953MB)
   72.82040131649507% used

可以看到最大堆内存只有250MB,也是很奇怪为什么会这么小,之前也没怎么关注这块。
查询发现,k8s会限制容器的运行内存,所以使用 kubectl describe [pod] 查看节点的详情,可以看到容器限制的内存大小:

Containers:
  your-appliction-name:
    Limits:
      cpu:     500m
      memory:  1000Mi
    Requests:
      cpu:      200m
      memory:   1000Mi

想不懂,限制的是1000mib,为什么实际分配的只有250mb。

查询发现:

-XX:+UseContainerSupport ,此参数用于使 JVM在分配堆大小时考虑容器内存限制,而不是主机配置。

在早期jdk版本里,应用运行在容器里,jvm无法感知到容器环境的存在,所以对容器资源的限制比如内存或者cpu等都无法生效,只能获取到服务器的配置。那么分配jvm内存超过容器限制,容器会被kill掉。
为了解决这个问题,从jdk10开始,加入了 +UseContainerSupport(默认情况下启用),通过这个特性,可以使得JVM在容器环境分配合理的堆内存。 并且,在JDK8U191版本之后,这个功能引入到了JDK 8,而JDK 8是广为使用的JDK版本。
注:这里具体jdk版本没经过验证。

-XX:MaxRAMPercentage=25(默认25),指定java堆最大大小占虚拟机可用总内存的百分比

也就是这个参数,造成 容器限制的最大内存为1000mib,java堆实际被分配到的最大为250mib。

-XX:InitialRAMPercentage =1.5(默认1.5),指定java堆初始大小占虚拟机可用总内存的百分比

所有堆内存只有250mb的原因找到了。


解决方案:

设置jvm参数:-XX:+UseContainerSupport -XX:MaxRAMPercentage=70 -XX:InitialRAMPercentage =70
把jvm堆内存占 容器限制的总内存70%。重启容器,使用jmap命令进行查询,确实发生改变。
注意:这个占比,需要根据自己的应用来进行设置,因为除堆内存外,jvm还会占用容器的部分内存,容器运行也需要一部分运行,当容器内存不足时,容器会产生OOMKill,将容器kill进行重启。


学习参考链接:

链接:
-XX:[+|-]UseContainerSupport.
容器环境的JVM内存设置最佳实践.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线上问题总结:运行在容器里的springboot应用,出现多次oom 的相关文章

随机推荐

  • 常见的List接口的实现类

    常见的List接口的实现类 ArrayList 数组实现 查询快 增删慢 轻量级 线程不安全 LinkedList 双向链表实现 增删快 查询慢 线程不安全 Vector 数组实现 重量级 线程安全 使用少 ArrayList实现类 pub
  • cesium-添加点线面可以动可编辑

    使用 const drawEntities new CesiumEntityDraw viewer drawEntities startDraw 需要绘制的类型 CesiumEntityDraw ts文件 import Cesium fro
  • RabbitMQ编程模型

    Hello World 在本教程的这一部分中 我们将用 Java 编写两个程序 发送单个消息的生产者和接收消息并将其打印出来的消费者 我们将忽略 Java API 中的一些细节 专注于这个非常简单的事情 以便开始 这是一个 Hello Wo
  • vue3的element-plus的el-dialog的样式加上scoped发现:deep()不再生效解决方案

    想要将 弹框 el dialog header el dialog body 的padding值设为0 但是 el dialog 用了 append to body 属性情况下 官网解释 Dialog 自身是否插入至 body 元素上 嵌套
  • C语言入门教程之三天入门C语言(第二天结构体与指针使用)

    三天学习C语言 第二步 一 C语言中的几种集合的表达形式 数组类型 数组扩展 结构体的表示 联合体的表示 二 sizeof 的使用 三 指针的使用 指针变量 未完待续 指针与数组 一 C语言中的几种集合的表达形式 在数学中一般一组数据的集合
  • 前端面试100道

    幕布链接 完整版 面试终极 幕布 目录 1 弹性布局的认识 2 Var和let有什么区别 3 和 的区别 4 Js事件 5 Vue计算属性 6 Vue采用指令 7 Html中的浮动怎么使用 8 箭头函数 9 Js的this指向 10 Cal
  • css兼容浏览器的各种背景渐变

    需要兼容各浏览要注意的是 必须加上浏览器的私有前缀 否则一般都是不生效的 浏览器的私有前缀主要是解决不同浏览器的兼容性问题 webkit 谷歌浏览器 安卓 moz 火狐浏览器 o opera浏览器 ms ie浏览器 首先来个简单的也最常见的
  • 父组件更新,子组件未更新

    囧 问题 项目中 渲染的数据为对象数组arr obj obj obj 业务需要要给某个对象obj增加一个属性key arr forEach obj gt obj key 囧 但是当在父组件中修改这个属性后 子组件并没有随着更新 原因 没有通
  • 软件测试笔试题含答案

    目录 一 填空 1 系统测试使用 C 技术 主要测试被测应用的高级互操作性需求 而无需考虑被测试应用的内部结构 2 单元测试主要的测试技术不包括 B 3 A 的目的是对最终软件系统进行全面的测试 确保最终软件系统满足产品需求并且遵循系统设计
  • ReactNative中使用WebSocket

    首先说说发布订阅这种设计模式 这种模式我给它起了个别名叫遥控炸弹 很多朋友理解不了这种模式 那 举个例子 张三是个法外狂徒 它要去复仇 他想去炸掉仇家的房子 他来到仇家所在的小区 拿出自己准备的炸弹 监听 丢进仇家的屋里 页面 等他走出小区
  • Hadoop3.x集成HBase

    HBase作为Hadoop家族中实现高并发的利器 我们来看看怎么进行集成 1 下载并上传到服务器 目前使用2 3 5版本 wget https mirrors bfsu edu cn apache hbase 2 3 5 hbase 2 3
  • 软件工程—软件测试

    前言 软件测试是为了发现错误而执行程序的过程 是对需求分析 设计和编码3个阶段进行的最终复审 下面介绍了软件测试的原则 方法过程等 测试用例的设计 测试的步骤还有软件的调试技术 一 软件测试 软件测试的目的 1 测试是程序的执行过程 目的在
  • QT Creator 自定义控件的方法和步骤

    QT版本 QT 6 2 3 QT Creator6 0 2 Community 是MSVC编写 要注意看哦 编写自定义控件的时候也要用 1 打开QT Creator 点击 文件 gt 新建文件或项目 gt 其他项目 gt QT4设计师自定义
  • 微信小程序在wxml中使用函数

    方法一 在wxml中直接添加模块 就可以在wxml中直接引用 举个例子
  • VS2022 安装 .NET Framework 4.0 和 .NET Framework 4.5 的方法

    前言 2022年5月27日 刚刚把VS2019升级到了VS2022 安装时已经不提供 NET Framework 4 0和 NET Framework 4 5的目标框架了 打开VS也提示不支持目标框架 解决方法 1 下载 NET Frame
  • tcp的半连接与完全连接队列

    队列及参数 server端的半连接队列 syn队列 在三次握手协议中 服务器维护一个半连接队列 该队列为每个客户端的SYN包开设一个条目 服务端在接收到SYN包的时候 就已经创建了request sock结构 存储在半连接队列中 该条目表明
  • 信号处理算法(4):全球最快的傅里叶变换算法(FFTW)

    本文大部分内容转载自博客 congwulong https blog csdn net congwulong article details 7576012 FFTW Fastest Fourier Transform in the Wes
  • C++Primer 第五版 ——《第十四章 》重载运算符 与 类型转换

    目录 基本概念 如何调用 非成员函数 和 成员函数的 重载运算符 491P 有哪些运算符就不应该被重载 491P 重载运算符的 返回类型 应该与 内置版本的返回类型兼容 492P 重载 赋值和 复合赋值运算符 应该返回左侧运算对象的一个引用
  • C语言 编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

    include
  • 线上问题总结:运行在容器里的springboot应用,出现多次oom

    项目运行环境 运行环境 k8s docker open jdk11 springBoot 公司的项目都是使用kubernate docker来管理 运行应用 问题描述 发现项目出现多次oom 排查到的原因有两个 1是分配的堆内存太小 2是代