原创

Java后台程序因内存超额被系统Kill问题排查处理

今天打开博客网站,突然发现访问失败了,显示502 Bad Gatteway网关错误,于是赶紧登录服务器排查处理,记录一下处理过程。

一、排查nginx日志

后台程序是通过nginx代理暴露出来的,所以我们首先查看nginx日志是否有问题。

1.查看运行日志

查看access.log日志内容:

tail -f /var/log/nginx/access.log

看日志中所有blog.eyyyye.com的请求都报错了。

2.查看错误日志

接下来看一下error.log日志:

tail -f /var/log/nginx/error.log

可以看到所有请求都报错failed (111: Connection refused) while connecting to upstream,这就是连接上游服务失败了,对我们来说就是后台程序没响应了,接下来需要排查一下后台程序。

二、排查java程序问题

上一步排查nginx程序没有问题,下面就需要排查java程序是否有问题。

1.查看端口监听

上面看到Java后台端口是8443,我们首先需要看一下端口监听是否正常:

netstat -anptl|grep LISTEN|grep 8443

可以看到端口已经没有监听了。

2.查看后台进程

接下来查看一下后台java进程:

ps -ef|grep java

可以看到只有一个admin的进程还在,web的进程已经没有了。

3.启动后台进程

为了优先恢复访问,我们先将web服务启动起来再排查后续问题:

sh blog-web.sh start

模块启动起来之后博客页面就可以正常访问了:

查看端口和进程也已经正常:

三、系统问题排查

虽然后台进程已经启动,但是这个程序为什么会死掉,我们还是需要排查下原因的。

1.查看内核日志

首先通过下面命令查看Linux系统内核日志:

dmesg

找到java相关部分:

通过日志可以看到java程序是因为Out of memory内存不足的原因被杀掉的。

2.查看系统日志

接下来通过下面命令查看系统日志确定一下:

less /var/log/messages

进入后输入/java查看java相关日志:

通过日志分析发现java程序被kill是因为内存超额触发了系统的oom-killer机制,然后就被系统杀掉释放内存了。

3.查看systemd日志

输入下面命令查看systemd日志:

journalctl | grep -i "killed process"

4.查看java模块日志

接下来就需要分析一下,这个java后台程序占用的内存为什么会突然增加,所以我们看一下这个模块记录的日志看看当时发生了什么:

然后就看到了模块被杀之前的时间,几秒内有几百条访问请求记录,所以推测是这个原因导致内存超过正常范围了,接下来就需要研究一下处理方案。 

四、问题处理方案

1.调整Java应用JVM内存限制

在启动脚本中增加下面参数限制JVM内存大小:

java -Xms256m -Xmx512m -jar blog-web.jar

参数说明:

  • --Xms256m:初始内存256MB
  • -Xmx512m:最大内存512MB

修改完成后重新启动java模块。

2.配置Java应用自动重启

使用systemd管理java程序,让Java服务被杀掉后会自动重启。

首先在/usr/lib/systemd/system/下创建blog-web.service文件:

touch /usr/lib/systemd/system/blog-web.service

执行下面命令在文件中添加blog-web.service配置(具体参数根据实际情况修改):

cat << EOF >> /usr/lib/systemd/system/blog-web.service
[Unit]
Description=blog-web Java Application
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/data/web
ExecStart=/data/jdk1.8.0_211/bin/java -Xms256m -Xmx512m -jar /data/web/blog-web.jar
Restart=always
RestartSec=10
SuccessExitStatus=143
Environment="JAVA_HOME=/data/jdk1.8.0_211"
[Install]
WantedBy=multi-user.target
EOF

重新加载systemd配置:

systemctl daemon-reload

使用systemctl启动Java程序:

systemctl start blog-web

查看服务状态:

systemctl status blog-web

查看实时日志:

journalctl -u blog-web.service -f

杀掉进程看是不是能自动重启:

可以看到java应用已经自动重启了。

3.限制访问ip访问频率

内存超额原因是短时间内访问太频繁了,因为CDN使用的是阿里云的ESA,所以直接在ESA里限制请求频率。登录阿里云ESA工作台,在安全防护->WAF->频次控制规则中新增单ip访问控制规则:

规则内容:

这样就可以暂时先用着了,想彻底解决只能等其他服务器有空闲资源后升级内存了。


扩展说明:

1.可以使用JVM自带的工具jstat -gc 进程IDjmap -heap 进程ID查看java程序内存使用情况。

正文到此结束
本文目录