linux java应用间歇性不可用问题排查:
结论
Java引用,触发了linux内核的oom killer机制,以至于java进程被kill掉。
-
现象:
6月4号,应用现故障时,使用
ps -ef|grep java
命令查看进程时发现java进程不见了;6月5号 在另外一套应用环境进行压测时,也出现了这个现象;
-
排查:
查看日系统日志:
/var/log/messages
6月4号系统日志截图
6月5号系统日志截图
内核日志显示 oom killer 将java进程杀掉。
虚拟机内存现状:
虚拟的内存的总大小是8G,jvm启动参数设置的初始堆内存是4G,最大直接内存15G。
虚拟机中部署的其他应用有:
nginx服务、360entclient、/opt/datadog-agent/embedded/bin/python
在刚启动网关服务后,系统内存已经只剩下几十兆左右的可用内存。此时如果有比较消耗内存的操作,就会触发系统的oom killer。
点此了解oom killer
占用内存的操作,初步怀疑是批量缓存同步操作,
-
解决方案:
以下几种解决方案供参考
- 增加系统内存
- 是优化进程,使其占用内存降低。
- 是可以使用oom_score_adj参数,这个参数会被计算影响到oom_score,改了之后就可以避免进程被杀死(不推荐)。
-
具体调整:
修改网关服务主体jvm启动参数,降低使用内存,降低触发oom killer的可能性。
## 修改jvm内存从4g调整到2g JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g" ## 调整直接直接内存 JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=1g"
以上是本次问题的排查结论,下面是排查过程的记录。
具体排查过程做了简单的记录
下面是具体的问题定位过程,由于对系统的不熟悉和对问题现象行的不明确,导致一致定位不到根本问题。走了些弯路。
问题现象
本次问题排查经过了一些摸索,记录一下:
服务器:20.26.85.230
问题描述:
6月3号:
同事描述:重启nginx或者重启应用后,服务恢复正常。
临时考虑是系统配置问题:
-
top(top -Hp 进程id)查看cpu和内存使用情况:cpu利用率不高,内存使用率偏高。
-
ulimit -a 查看句柄数设置,发现普通用户最大句柄数为16384。明显少于规范使用的65535
试探性的将句柄数设置到65535观察。后来再次出现故障,句柄数调大并未解决问题。
6月4号:
1、jstack 将线程堆栈信息dump下来(jstack pid >> file)。11点后的一个小时,进行了4次的线程信息取样:
总线数量分别是:696、644、650、650
- RUNNABLE,线程处于执行中
- BLOCKED,线程被阻塞
- WAITING,线程正在等待
- TIMED_WAITING,这个一般是指这个线程是Timer定期执行任务,但是当前处于waiting状态
线程数量不多,未发现阻塞线程,无线程积压的情况
内存dump:
jmap -dump:format=b,file=jmap. pid
11:42
发现应用会”自动重启“。问了别人后发现,可能是其他项目组的人员进行了重启
1、RUNNABLE,线程处于执行中
2、BLOCKED,线程被阻塞
3、WAITING,线程正在等待
4、TIMED_WAITING,这个一般是指这个线程是Timer定期执行任务,但是当前处于waiting状态
一个同事 的意见是:增加ng日志打印请求、返回信息,怀疑ng和网关服务之间有问题
ng默认不支持打印请求内容:
需要增加lua模块,然后用lua脚本来获取请求和返回的内容并且打印到日志中。
/home/aifgw/nginx/sbin/nginx -s reload
监控ng日志、监控jvm gc (jstat -gcutil 进程id)
发现java进程不见了;
linux的OOM killer
Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉。
因此,发现java进程突然没了,首先要怀疑是不是被linux的OOM killer给干掉了!
查看系统报错日志: /var/log/messages
网关服务原始启动脚本(启动参数设置):
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"
JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy"
JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"
JAVA_OPT="${JAVA_OPT} -Dcsf.client.name=xxx -Dxxx.server.name=xxx"
JAVA_OPT="${JAVA_OPT} -Dfile.encoding=UTF8 -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib"
JAVA_OPT="${JAVA_OPT} -Dprint.logback.status.enable=false"
JAVA_OPT="${JAVA_OPT} -Dlogback.configurationFile=${BASE_DIR}/conf/logback.xml -javaagent:/home/user/agentlib/log4x-agent.jar"
JAVA_OPT="${JAVA_OPT} -Darea.code="
启动参数中 最小堆、最大堆内存:4G; 直接内存:15G
而系统内存只有8G
应用启动成功后,系统可用内存只有100M的空闲内存。很有可能触发系统的OOM killer。
解决方案:
-
增加系统内存
-
是优化进程,使其占用内存降低。
-
是可以使用oom_score_adj参数,这个参数会被计算影响到oom_score,改了之后就可以避免进程被杀死(不推荐)。
http://www.wowotech.net/memory_management/oom.html
尝试解决方案:
修改配置:
JAVA_OPT="${JAVA_OPT} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dev/shm/oom_%p.log"
## 修改jvm内存从4g调整到2g
JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g"
6月5号:
进程被linux oom killer kill掉了
性能压测服务器:20.26.85.228
启动参数:
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"
JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy"
JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"
JAVA_OPT="${JAVA_OPT} -Dcsf.client.name=xxx -Dxxx.server.name=xxx"
JAVA_OPT="${JAVA_OPT} -Dfile.encoding=UTF8 -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib"
JAVA_OPT="${JAVA_OPT} -Dprint.logback.status.enable=false"
JAVA_OPT="${JAVA_OPT} -Dlogback.configurationFile=${BASE_DIR}/conf/logback.xml -javaagent:/home/user/agentlib/log4x-agent.jar"
JAVA_OPT="${JAVA_OPT} -Darea.code="