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<Object> 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<Object> 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了,只会打印异常堆栈

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值