故障描述:线上项目,每隔一段时间就会假死一次,现象是网站无法打开,重启后解决,但是不定时会出现,没有固定的规律
原因分析:1第一时间查了cpu和内存情况,并没有发现特殊情况,只是cpu比往常稍高了一些,也不会导致服务不可用
因为要急于给用户使用,前面两次便直接重启了。
2、分析日志,发现日志是到了某个点突然就截止不动了,没有报内存溢出,线程异常,也没有jvm crash的日志,证明服务确实在启用,只是无法对外提供服务,并且无法自动恢复(排除内存或线程会释放的问题),因为是用的k8s部署的,本身k8s环境对开发不太透明,所以一直怀疑有可能是环境问题,让运维加了探针,检测到服务接口不可用便自动重启,后面发现确实会有检测到接口不可用情况,逐渐排除了运维环境问题
3、后面尝试增加pod(增加应用数),有1个服务提到2个,再到4个,还是会出现这种情况,某个pod有问题,但其他pod没问题,初步排除了mysql等中间件负载问题(不排除连接池不释放等)
4、不定时假死,前面没拿到jvm日志,怀疑tomcat线程数或者连接池或者内存已满,就增加了线程数和重新配置了jvm参数(-Xms,-Xmx),前面好了点,后面还是会出现
5、后面再次遇到,用ps -T -p <PID>|wc -l 查看了tomcat线程数,发现有两百多,tomcat的线程配置的200个被占满了,其他的是守护等进程,用jstack命令查看,发现很多都是BLOCK状态
然后发现Category里面有同步代码,这里是日志打印的
public void callAppenders(LoggingEvent event) {
int writes = 0;
for(Category c = this; c != null; c=c.parent) {
// Protected against simultaneous call to addAppender, removeAppender,...
synchronized(c) {
if(c.aai != null) {
writes += c.aai.appendLoopOnAppenders(event);
}
if(!c.additive) {
break;
}
}
}
if(writes == 0) {
repository.emitNoAppenderWarning(this);
}
}
然后搜了网上的log4j问题,果然1.x版本是有这种问题的,后升级为log4j2
6、升级为log4j2之后仍然有问题,很多线程都在等待这个线程持有的锁,但这个就是不释放
后面看了程序有很多System.out.println方法,可能跟log等有冲突,把所有System.out.println去掉,后面没在出现