第一次问题:kubernetes pod频繁重启 容器内存占用不断升高 达到10g就自动重新构建
jvm参数设置:
-Xms4g -Xmx10g -XX:ParallelGCThreads=3 -XX:+UseParNewGC
开始就怀疑是OOM问题导致服务崩溃,想看日志有没有打印OOM异常信息,可是每次重启都把原来映射到持久卷的日志文件覆盖(在这里吐槽一下同事,为什么日志不分日期,为什么每次重启容器日志都会被覆盖)
所以加了两个参数:
OOM时输出dumap文件:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/dump
打印gc日志:-XX:+PrintGCDetails -Xloggc:/logs/gc.log
打算下次重启之后查看分析dumap文件和gc日志
…可结果令人大失所望,程序并没有发生OOM异常。问同事kubernetes并没有开启健康检查,然后检查容器配置配置参数,发现了问题:容器最大内存 10g,,java进程堆最大内存也是10g…(无力吐槽)
立马把容器内存加大之后重启服务打算着手优化 full gc 如此频繁的问题
OOM问题导致系统崩溃
那么真正的问题来了,上线一段时间后客户反映说接口没有响应了,看日志接口响应时间也非常慢,因为没有开启健康检查,服务并没有自动重启,java进程也没有被清理,查看日志确实发生了内存溢出,分析dumap文件发现大量的 org.apache.commons.net.ftp.FTPFile 对象和 java.util.GregorianCalendar占用了很大的内存 查看gcroots FTPFile 对象几乎都是在一个FTPFile数组中,,GregorianCalendar 对象都是在FTPfile中的一个成员变量引用
跟踪代码后发现了一段很可疑的代码:
ftpClient.changeWorkingDirectory(remotePath);//转移到FTP服务器目录
ftpClient.enterLocalPassiveMode();
FTPFile[] fs = ftpClient.listFiles();
for(FTPFile ff:fs){
if(ff.getName().equals(fileName)){
File localFile = new File(localPath+"/"+ff.getName());
OutputStream is = new FileOutputStream(localFile);
ftpClient.retrieveFile(ff.getName(), is);
is.close();
}
}
这是一段从ftp文件服务器上下载文件的代码
登录ftp文件服务器之后彻底懵逼:下载文件的那个文件夹中有多达60多w的图片 而且数量时刻在增加
也就是说每一个客户请求都在加载一个60多万长度FTPfile数组,然后去遍历,,,难怪响应会慢,难怪fullgc 会如此频繁,甚至发生OOM
然后剩下的就把代码贴给开发负责人修改了 =.= =.= =.=