背景:

业务的容器化刚刚搞完,线上开始告警,容器重启,容器重启。describe pod 查看原因是OOMKilled

分析:

OOMKilled 是pod 中的进程使用的内存超过了.spec.containers[*].resources.limits.memory中定义的内存限制,在超出限制后, kubernetes 会向容器中的进程(pid=1)发送kill -9 信号。kill -9 信号对于进程来说是不可捕捉的,进程无法在收到-9 信号后优雅的退出。 这对于业务来说是有损的。那么为啥进程会超过容器的limit 限制呢?

查看容器中进程的启动参数:

java -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -XX:MetaspaceSize=128m -jar bxr-web-1.0.jar

查看容器的limit限制

k8s-master-01#kubectl get pods -n calculation bxr-web-dd656458b-8m4fb -o=custom-columns=name:.metadata.name,namespace:.metadata.namespace,memory-limit:.spec.containers[0].resources.limits.memory

name namespace memory-limit

bxr-web-dd656458b-8m4fb calculation 2000Mi

进程没有设置内存限制,但是这个业务之前在虚拟机上运行时,配置相同,启动参数也是如此,为什么上线到容器中会经常出现OOMKilled 的情况呢。这里就需要说到docker对进程资源的限制。

docker 通过 cgroup 来控制容器使用的资源配额,包括 CPU、内存、磁盘三大方面,基本覆盖了常见的资源配额和使用量控制。但是在java 的早期版本中(小于1.8.131),不支持读取cgroup的限制。 默认是从/proc/目录读取可用内存。但是容器中的/proc目录默认是挂载的宿主机的内存目录。即java 读取的到可用的内存是宿主机的内存。那么自然会导致进程超出容器limit 限制的问题。

验证:

起初, 我们采用为进程设置-Xmx参数来限制进程的最大heap(堆)内存。例如。 容器的limit限制为3G。 那么设置java进程的最大堆内存为2.8G,采用这种方式后,容器重启的情况少了很多,但还是偶尔会出现OOMKilled 的情况。因为-xms 只能设置java进程的堆内存。 但是其他非堆内存的占用一旦超过预留的内存。还是会被kubernetes kil掉。附java 内存结构:

JVM内存结构主要有三大块:堆内存、方法区和栈

堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden空间、From Survivor空间、To Survivor空间,默认情况下年轻代按照8:1:1的比例来分配;

方法区存储类信息、常量、静态变量等数据,是线程共享的区域,为与Java堆区分,方法区还有一个别名Non-Heap(非堆);

栈又分为java虚拟机栈和本地方法栈主要用于方法的执行。

那么有没有办法能让java 正确识别容器的内存限制呢?这里有三种方法:

升级java版本。Java 10支持开箱即用的容器,它将查找linux cgroup信息。这允许JVM基于容器限制进行垃圾收集。默认情况下使用标志打开它。

-XX:+UseContainerSupport

值得庆幸的是,其中一些功能已被移植到8u131和9以后。可以使用以下标志打开它们。

-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

LXCFS,FUSE filesystem for LXC是一个常驻服务,它启动以后会在指定目录中自行维护与上面列出的/proc目录中的文件同名的文件,容器从lxcfs维护的/proc文件中读取数据时,得到的是容器的状态数据,而不是整个宿主机的状态。 这样。java进程读取到的就是容器的limit 限制。而不是宿主机内存

-XX:MaxRAM=`cat /sys/fs/cgroup/memory/memory.limit_in_bytes` 通过MaxRAM 参数读取默认的limit限制作为java 内存的最大可用内存。同时结合-Xmx 设置堆内存大小

java jar killed_容器中Java 程序OOMKilled原因浅析相关推荐

  1. java jar killed_我的Java应用程序被OOMKilled了,原因竟是这样?

    在AWS云上,我们运行并部署容器化应用程序到我们的PaaS管道.像我们这样在Docker中运行Java应用程序的人,可能已经遇到过 **JVM在容器中运行时无法准确检测可用内存的问题 **.jvm没有 ...

  2. 【docker ros】docker 开启自启运行容器中的程序

    前言: 使用docker大规模部署应用,而又需要开机自启,自动启动容器中的程序,这里以docker ros为例子,使用systemctl服务,结合shell脚本,也可以结合Python脚本,进而实现了 ...

  3. java jar 打包命令行_Java程序命令行打包Jar

    最近要跑爬虫程序,需要打包成jar发在linux服务器中运行.主要是第三方的lib包与配置文件,不进行打包,方便修改. 1.eclipse中src中源码编译后生成的源码在bin文件中,把里面源码单独拿 ...

  4. 容器中Java RAM的使用:不会丢失内存的5大技巧

    在本文中,我们希望分享Java内存管理的细节和容器内部的弹性,这些细节乍一看并不明显. 在下面,您将找到要注意的问题列表以及即将发布的JDK版本中的重要更新,以及针对核心痛点的现有解决方法. 我们收集 ...

  5. linux java jar打包_【Java】Java程序打包成jar包在Linux上运行

    当需要把在Windows上开发的Java程序用在Linux上运行时,就需要吧该Java程序打包成jar包上传到Linux上去运行. 1.Java程序用MyEclipse打包成可运行的jar包 (1)在 ...

  6. java jar 目录_将Java类路径中的所有jar包括在一个目录中

    有没有一种方法可以将所有的jar文件包含在类路径的目录中? 我正在尝试java -classpath lib / *.jar :. my.package.Program,它无法找到当然在这些罐子里的类 ...

  7. linux java jar war_简单介绍Java 的JAR包、EAR包、WAR包区别

    WAR包 WAR(Web Archive file)网络应用程序文件,是与平台无关的文件格式,它允许将许多文件组合成一个压缩文件.War专用于Web方面.大部分的JAVA WEB工程,都是打成WAR包 ...

  8. android java 调用js,Android中Java和JavaScript交互实例

    Android提供了一个很强大的WebView控件用来处理Web网页,而在网页中,JavaScript又是一个很举足轻重的脚本.本文将介绍如何实现Java代码和Javascript代码的相互调用. 如 ...

  9. jmeter里看java的log,jmeter中java协议请求

    5.Export为Runnable Jar File:hello.jar 注意:不需要将整个工程导出,只需要选中包名(test)在file菜单中点击export->选java项的jar file ...

最新文章

  1. ubuntu14.04如何在线安装eclipse以及C/C++开发组件,搭建软件开发平台
  2. mysql dba系统学习(1)mysql各版本编译安装
  3. SAP收购Sybase意欲何为
  4. 2021.11.18
  5. 1880: wjw的火车站(栈)
  6. 引领三消新模式 《梦幻花园》商业化分析
  7. redis维护问题总结
  8. java推送数据给安卓,java – 如何从Firebase推送通知中获取数据并将其显示在Android Activity中?...
  9. 关于客户端无法获得服务器端GP服务(Geoprocessing Service)结果的解决办法
  10. 计算机项目教学法探讨,项目教学法在计算机教学中应用计算机教学论文计算机论文...
  11. 北师大计算机学院调剂,北师大数学科学学院2020年硕士研究生调剂方案
  12. C#调用第三方ocx控件 (winform /aspx)
  13. android获取当前activity view,Android中如何通过View获取Activity
  14. [2018.09.08 T2] 最大土地面积
  15. 怎么取消wps云服务器_关闭手机版wps云服务器
  16. IE8_XP安装包.zip
  17. 机器人学导论学习笔记No.1-第一章 :概述
  18. OSChina 周二乱弹 —— 仙女抚我顶,脱发不长生
  19. 记录一次面试经历(深刻)
  20. Python:下载数据——CSV文件格式练习题

热门文章

  1. 线程方法destroy()和stop(Throwable)在JDK 11中删除
  2. 新闻发布系统java ee_Java EE 7发布–反馈和新闻报道
  3. drools 决策表_骆驼和春天的Drools决策表
  4. mongodb适用于_适用于MongoDB和Mongometer的SpiderMonkey至V8
  5. Apache Storm的实时情绪分析示例
  6. MySQL JDBC驱动程序如何处理准备好的语句
  7. 使用Java 8 CompletableFuture和Rx-Java Observable
  8. 让我们回顾一下如何通过JDBC插入Clob或Blob
  9. 在Java中对Singleton类进行双重检查锁定
  10. Java安全教程–创建SSL连接和证书的分步指南