宕机判断与预处理
OOM Killer原理
- 当物理内存和交换空间爆满时,OOM Killer会计算每个进程的oom_score并选择杀死进程。oom_score的值越大就越有可能被 OOM Killer 选中。这里列举两个主要因素:
进程消耗的内存越大,oom_score越大
进程运行消耗的CPU时间越小,oom_score越大
- Windows下没有OOM Killer机制,用户只能强制杀死进程或者重启机器。
内存溢出OOM判断和dump获取
内存溢出的导致无响应的主要原因,是由于JVM的内存全部耗光,但是依然需要进一步分配内存。此时JVM就会进行很多次的的Full GC,希望回收不使用的内存。但是由于数据都在使用,因此一直释放不掉内存,于是就一遍遍的进行Full GC。
按照以下办法判断是因为内存溢出导致的宕机
- 利用top命令发现进程的CPU使用率非常高。
- CPU高并不一定是在做Full GC,需要进一步确认。利用jstat -gc pid 2000 2000 这一命令。如下代码块所示,关注FGC一栏,如果数值增加很快,而且FGCT(Full GC 的总时间)数值很大,例如FGC 为20 FGCT已经2000以上,平均一次FGC耗时100s。这里就可以确定是内存溢出了导致的宕机,需要获取dump
- 满足上面条件才认为是内存溢出,否则不在这个内存溢出处理范畴内。
- 优先通过配置来让JVM自己生产dump,但是如果没有配置的话那就是手动获取。执行“ jmap -dump:format=b,live,file=路径 进程pid”,例如 代码块中获取22374进程的dump。
- 如果客户环境没有配置JVM进行dump的参数,需要加上以防万一。配置宕机文件自动生成
系统的OOM Killer
1 | 执行下面三个命令 |
测试方法
1 | // oom_adj=15时,必然会被OOM Killer选中 |
监测宕机 (信号量 + JVM Shutdown Hook)
信号量
利用sun.misc.SignalHandler类,可以监听除了kill -9之外的其他关闭信号。Java对每个信号量都启动一个线程进行处理,注册信号量后会启动”SIGTERM handler” 线程。即便主线程被阻塞,信号依然可以得到处理。JVM Shutdown Hook
当程序执行System.exit(0)退出时,信号量方法是无法知道的,这时候需要使用JVM Shutdown Hook。