服务器问题排查
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:''
可以查看每个进程的线程数量
浙公网安备 33010602011771号