tomcat线上服务器负载过高的问题 - 高飞网
371 人阅读

tomcat线上服务器负载过高的问题

2017-07-28 02:09:46

    今天运维反馈,我们线上一个web项目,CPU负载非常高,导致其他项目都快不正常了,查看线上的cpu负载,看到cpu竟然被这个进程占用了800%以上,着实惊人。

当时的CPU负载图:

而正常状态下应该是:


运维在服务器top查询的结果如下图所示:

    怎么回事呢?内存占用并不高,所以排除是内存漏洞或gc等问题,最有可能的原因,就是代码上有死循环。于是试着看代码。

    看了半天后,并没有发现有死循环的情况。竟然CPU看到该进程占用如此多的资源,那能否看到某个线程的使用情况呢?运维把内存dump下来以后,的确看到一些运行的线程,但看不出什么名目来。网上发现一篇好文章,《tomcat7高CPU问题》

  •     原文就不赘述了,这里只引用其关键部分:
  •     第一步,使用top命令,发现占用较高的进程及ID。(上面的截图即是)   
top
  •    
  •     第二步,找到进程以后,查看进程中占用时间较长的线程信息
ps -mp PID -o THREAD,tid,time | sort -rn
  •     下面是运行出来的截图:
  •    
  •     第三步,根据线程信息TID,打印出线程堆栈信息,需要先得出TID的16进制表示
printf "%x\n" TID
jstack PID |grep XXX -A 30
  •     下面是运行出来的截图:
  •    
  •     这样就发现问题出现的具体代码了。我们的Filter中,有一个成员变量Map,这个Map会在初始化的时候,往里面put一些数据,而在put的时候,没有线程控制,那put会出现死循环吗?开始不敢相信,查看下面这些文章
  • http://coolshell.cn/articles/9606.html
  • http://xm-king.iteye.com/blog/962172
  • http://my.oschina.net/xianggao/blog/393990
  • http://coolshell.cn/articles/9606.html


    总之是因为HashMap的多线程环境下,键的链表会形成环,导致后续的操作陷入死循环。解决的办法是:

1. Collections. synchronizedMap(new HashMap())
2. concurrent包下的 ConcurrentMap 系列 ConcurrentHashMap, ConcurrentSkipListMap
3. 同步锁 synchronized  方法级 、块级
4. concurrent.locks 包下的 Lock 接口
推荐大家使用在并发的情况下使用 ConcurrentHashMap 代替HashMap
  •                                 
还没有评论!
23.20.166.68