服务器问题排查

deadloop排查(jstack查看java进程堆栈)

一个cpu核心可以处理多个线程,但一个线程只能交给一个cpu处理,不能跨cpu。

一个请求由同一个线程处理,不能跨线程(异步新开线程的除外)。一个请求需要处理完,该线程才会释放,否则会一直阻塞。因此服务器线程池通常可以配置上千个线程,因为一个cpu同时处理多个线程比单独处理一个线程效率高(考虑线程阻塞的情况)。

 

因此如果有deadloop,该线程会一直占用同一个cpu核心的资源,而其他cpu核心不受影响(因为线程不能跨cpu,请求不能跨线程)。

 

top查看占用cpu占用高的进程(进去后按1可查看每个cpu核情况)

 

如这里是4核的,占用cpu最高进程号是2729

用jstack 2729即可查看,如:

 

但jstack打印了所有线程的日志,有时候不方便查看,可以grep出线程号,首先查询线程号,top中,按shift h可以切换为线程显示,如:

 

此时占用cpu最高的线程号是2749,需要转换成16进制abd

printf %x 2749

 

再用命令grep即可,如:

jstack 2729|grep -A 10 abd

第1个2729是进程号,第2个abd是线程号2749的16进制。

 

内存文件分析

1、登录到服务器dump文件

jmap -dump:format=b,file=test.dump 3431

其中3431是java的进程号

2、下载到本地电脑后,用HeapAnalyzer(ha456.jar)即可打开分析,选Analysis,右边可以看到值

java -jar ha456.jar

 

线程数排查

1、tomcat支持的最大线程数在server.xml配置

<Connector port="9101" acceptCount="1000" minSpareTHreads="10" maxThreads="2500" maxSpareThreads="30" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>

 

maxThreads表示最大线程数,处理中的线程超过这个数,新的请求会排队,并且后台会提示

acceptCount表示排队数,超过排队数,新的请求会被拒绝,返回connection refused

minSpareTHreads:最小空闲线程,初始化最小创建的线程。

maxSpareThreads:最大空闲线程,如果空闲线程超过它,会自动销毁多余线程。

 

 

2、linux用户所能创建的最大线程数在

cat /etc/security/limits.d/90-nproc.conf

中限定,如:

如果满了会提示java.lang.OutOfMemoryError: unable to create new native thread异常。

 

 

其中*表示非root的其他用户。

配置后需reboot重启生效。

因此:1、不要用root来部署,因为线程数没有限制,资源耗光会导致终端都无法连接,只能硬重启。

2、linux可创建的最大线程数计算:用物理内存/128K,大约等于最大线程数。

如:

 

 

所以tomcat服务器所能创建的最大线程数受上面2个条件限制。tomcat的maxSpareThreads配置要比90-nproc.conf中配置的用户线程数小一些才行,否则linux系统的线程被tomcat用光, 会导致终端无法连接,只能用root登录上去处理了。

 

 

用root登录上去,top查看,然后按shift+h切换到线程显示,会看到很多sleeping(挂起的)线程.

top -H -p 进程号,可以查看单个进程下的线程情况,如:

top -H -p 12440

 

 

java如有多个线程sleep或者等待锁释放的情况,会造成服务器线程数耗光。

首先排查服务器java进程的线程数:

cat /proc/进程号/status

如:

cat /proc/3899/status

 

然后通过jstack 进程号查看线程状态,如:

jstack 3899 > ~/dump3899.txt

 

如:

sleep阻塞状态:

 

同步锁阻塞状态

 

 

cat /proc/*/status | egrep 'Threads:|Name:|Pid:''

可以查看每个进程的线程数量

posted @ 2021-01-27 19:20  吴克兢  阅读(214)  评论(0)    收藏  举报