栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

docker配置OOM打dump追加时间戳

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

docker配置OOM打dump追加时间戳

今天公司项目收到线上告警,某个集群监控到OOM了,于是立马去服务器上查看相关日志:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to /applog/java_pid69.hprof ...
Unable to create /applog/java_pid69.hprof: File exists



> 看到这边顿时心里凉了半截, 该打的dump文件没生成, 到 /applog目录下看对应的 dump生成时间, 果然是几天之前的



查看  JVM 启动参数:

~~~properties
-XX:+HeapDumponOutOfMemoryError -XX:HeapDumpPath=/applog

是因为这个配置,只会在OOM时候生成 java_pid.hprof的文件么, 没有自动添加时间戳?

于是, 我自己本地搭建了一个项目,验证这个问题:

package com.itboat008.springboot;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest
class SpringBootDemoApplicationTests {

	@Test
	void contextLoads() {
		List list = new ArrayList<>();
		while(true){
			list.add(new byte[1024 * 1024]);
		}
	}

}

 

VM options:

-Xms2048M -Xmx2048M  -XX:+HeapDumponOutOfMemoryError -XX:HeapDumpPath=/applog

运行,果然只有pid, 没有自动追加时间戳

于是想到将自己的spring-boot项目部署到阿里云上, 在docker里面配置验证OOM打dump追加时间戳。

其他的源码可参考 之前的文章:
spring-boot整合thymeleaf和MyBatis

在此基础之上, 添加 一个get请求, 可访问这个请求,触发OOM打dump

UserController 添加 如下代码:

@GetMapping("/testOOM")
@ResponseBody
public ResultVO testOOM(){
    ResultVO resultVO = new ResultVO();
    List list = new ArrayList<>();
    for(int i = 0 ; i < 10000; i++){
        list.add(new byte[1024 * 1024]);
    }
    resultVO.setResFlag("1");
    resultVO.setResInfo("asd");
    return resultVO ;
}
 

打包, 生成 jar包,上传至阿里云服务器 /home/docker/oom-test目录, 并修改 该jar包的执行权限

重命名jar名称为 app.jar

写Dockerfile
  1. 进入主机的 /home/docker/oom-test目录, vim Dockerfile

Dockerfile:

FROM java:8
MAINTAINER itboat008
#添加主机路径下的 app.jar到 镜像的 /home/docker/oom-test/路径
ADD ./app.jar /home/docker/oom-test/app.jar
ADD ./heapDump.sh /home/docker/oom-test/heapDump.sh
#设置 onOutOfMemoryError 时候需要执行的脚本
ENV JAVA_OPTS="-Xms256M -Xmx256M -XX:+HeapDumponOutOfMemoryError -XX:HeapDumpPath=/applog -XX:onOutOfMemoryError='/home/docker/oom-test/heapDump.sh'"
VOLUME ["/applog"]
ENTRYPOINT java ${JAVA_OPTS} -jar /home/docker/oom-test/app.jar

其中 heapDump.sh如下:

#在该脚本下修改hprof的文件名
datetime = $(date "%Y%m%d%H%M%S")
hprofs = `find /applog -name '*.hprof'`
for tmprof in $hprofs 
do
    mv $tmprof `echo "$tmprof.$datetime"`
done

主机上/home/docker/oom-test路径下的文件如下:

制作镜像
cd /home/docker/oom-test
docker build -t oom-test:foxer .
# 查看当前所欲镜像
docker images

#启动容器
docker run -d -p 8888:8080 --name oom-test2009 oom-test:foxer
#查看容器
docker ps

#跟踪容器日志
docker logs -f d63fbe05f043
触发OOM验证

打开浏览器 , 访问 对应的url, 可发现浏览器返回了500的错

跟踪容器日志:

进入容器 /applog路径下查看:

docker exec -it d63fbe05f043 bash

发现已经生成了, 再看下主机路径下对应文件

#查看当前容器信息
docker inspect d63fbe05f043

找到 Mounts这块的配置

#进入到宿主机对应路径 
cd /var/lib/docker/volumes/1b6f6094ee975ee3662316d8777aca5e5a8e07f26243699fd5fcaf70a3aaf7d3/_data

发现确实持久化到了主机的/var/lib/docker/volumes/1b6f6094ee975ee3662316d8777aca5e5a8e07f26243699fd5fcaf70a3aaf7d3/_data 路径上

指定主机生成路径
#如果需要指定生成的路径:
docker run -d -p 8888:8080 -v /applog:/applog --name oom-test2116 oom-test:foxer
#查看已启动的容器信息
docker inspect `docker ps | grep 'oom-test:foxer' |awk '{print $1}'`

发现确实挂载到主机的/applog路径下了

访问对应请求,发现生成到了/applog

经验证,如果当前应用已经打过dump了, 那么只要应用不重启, 后续OOM就不会再自动打dump了,只会打印异常堆栈

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号