tomcat假死排查学习笔记

415 阅读7分钟

最近遇到了这种情况了,客户反映登录不上,但是登录页面能打开,看了日志没发现有特别大的异常(有报错但是不会导致系统死掉的那种。还有是接口有个接口优化了但是日志上显示有个数据推送中间停了20s,客户9s就按照过期处理了。

这里先在网上收集点资料,后续按照这个例子排查

1.首先找到PID

win:
    netstat -ano|findstr 8080
    
linux:
    ps -ef | grep tomcat

2.查看tomcat 内存使用情况

打印堆信息的
jmap -heap pid >> jvm_memory.log

打印进程内存的
jmap -dump:format=b,file=dump 6228

内存分析工具
jvisualvm.exe
using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 536870912 (512.0MB)
   NewSize          = 1048576 (1.0MB)
   MaxNewSize       = 536870912 (512.0MB)
   OldSize          = 4194304 (4.0MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 12582912 (12.0MB)
   MaxPermSize      = 536870912 (512.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):      #新生代区内存分布,包含伊甸园区+1个Survivor区
   capacity = 483131392 (460.75MB)
   used     = 450787280 (429.9042510986328MB)
   free     = 32344112 (30.845748901367188MB)
   93.30531765569893% used
Eden Space:                                    #Eden区内存分布
   capacity = 429457408 (409.5625MB)
   used     = 429457408 (409.5625MB)
   free     = 0 (0.0MB)
   100.0% used
From Space:                                   #其中一个Survivor区的内存分布
   capacity = 53673984 (51.1875MB)
   used     = 21329872 (20.341751098632812MB)
   free     = 32344112 (30.845748901367188MB)
   39.73968468597375% used
To Space:                                     #另一个Survivor区的内存分布
   capacity = 53673984 (51.1875MB)
   used     = 0 (0.0MB)
   free     = 53673984 (51.1875MB)
   0.0% used
tenured generation:                           #当前的Old区内存分布  
   capacity = 65536 (0.0625MB)
   used     = 65536 (0.0625MB)
   free     = 0 (0.0MB)
   100.0% used
Perm Generation:                              #当前的 “永久代” 内存分布
   capacity = 182452224 (174.0MB)
   used     = 182295864 (173.85088348388672MB)
   free     = 156360 (0.14911651611328125MB)
   99.91430085280845% used

145631 interned Strings occupying 16887536 bytes.

image.png

JVM年轻代,老年代,永久代详解

eden和survivor默认比例是8:1:1,进行垃圾回收采用的是分代复制算法。 每次新生代的使用,会是eden区和一块survivor区。当我们进行垃圾回收的时候,清除正在使用的区域,将其中的存活对象,放入到另一个survivor区域,并进行整理,保证空间的连续。如果对象长时间存活,则将对象移动到老年区。存活下来的对象,他的年龄会增长1。当对象的年龄一次次存活,一次次增长,到达15的时候,这些对象就会移步到老年代。在年轻代执行gc的时候,如果老年代的连续空间小于新生代对象的总大小,就会触发一次full gc。是为了给新生代做担保,保证新生代的老年对象可以顺利的进入到老年代的内存区。

image.png

我们知道垃圾回收机制有三种,minor gc,major gc 和full gc。针对于堆的就是前两种。年轻代的叫 minor gc,老年代的叫major gc。

老年代和永久代区别

永久代是hotspot虚拟机,也就是我们使用的java虚拟机的特有的概念,他不属于堆内存,是方法区的一种实现,各大厂商对方法区有各自的实现。永久代存放jvm运行时,需要的类,包含java库的类和方法,在触发full gc的情况下,永久代也会被进行垃圾回收。永久代的内存溢出也就是 pergen space

元空间

元数据区替代方法区 元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。但由于元空间主要用于存储文件,因此静态成员的存储位置从方法区更改到了堆内存中

元空间是metaspace,在jdk1.8的时候,jvm移除了永久代的概念,元空间也是对java虚拟机的方法区的一种实现。元空间与永久代最大的区别在于,元空间不在虚拟机中,使用本地内存。通过配置如下参数可以更改元空间的大小。
-XX:MetaspaceSize:初始空间的大小。达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。
永久代的回收会随着full gc进行移动,消耗性能。每种类型的垃圾回收都需要特殊处理元数据。将元数据剥离出来,简化了垃圾收集,提高了效率。

image.png

8张图 让你明白 Java内存区域

3.Java的jstat命令使用详解

jstat -gc 6228 250 5

间隔250毫秒 输出5次

### **-gc选项**
1.  S0C:年轻代中第一个Survivor区的容量,单位为KB。
1.  S1C:年轻代中第二个Survivor区的容量,单位为KB。
1.  S0U:年轻代中第一个Survivor区已使用大小,单位为KB。
1.  S1U:年轻代中第二个Survivor区已使用大小,单位为KB。
1.  EC:年轻代中Eden区的容量,单位为KB。
1.  EU:年轻代中Eden区已使用大小,单位为KB。
1.  OC:老年代的容量,单位为KB。
1.  OU:老年代已使用大小,单位为KB。
1.  MC:元空间的容量,单位为KB。
1.  MU:元空间已使用大小,单位为KB。
1.  CCSC:压缩类的容量,单位为KB。
1.  CCSU:压缩类已使用大小,单位为KB。
1.  YGC:Young GC的次数。
1.  YGCT:Young GC所用的时间。
1.  FGC:Full GC的次数。
1.  FGCT:Full GC的所用的时间。
1.  GCT:GC的所用的总时间。

image.png

4.查看数据库连接状况ORCLE

select count(*) from v$process --当前的连接数
select value from v$parameter where name = 'processes' --数据库允许的最大连接数

SELECT SESS.SID,  SESS.SERIAL#,  LO.ORACLE_USERNAME,  LO.OS_USER_NAME,  AO.OBJECT_NAME 被锁对象名, LO.LOCKED_MODE 锁模式, sess.LOGON_TIME 登录数据库时间,
'ALTER SYSTEM KILL SESSION ''' || SESS.SID || ','||SESS.SERIAL#||'''' FREESQL
FROM V$LOCKED_OBJECT LO,  DBA_OBJECTS AO,  V$SESSION SESS 
WHERE AO.OBJECT_ID = LO.OBJECT_ID AND LO.SESSION_ID = SESS.SID ORDER BY sid, sess.serial#;

ALTER SYSTEM KILL SESSION '1851,33226';

5.CLOSE_WAIT过多

查询网络情况

netstat -aonp

pid查看 ps -ef |grep mysqld

linux连接 netstat -anp |grep 3306

linux连接数 netstat -pnt |grep :3306 |wc

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

windows netstat -ano |findstr 8443

windows下实现统计某个端口的连接数命令为:

netstat -an|find "ESTABLISHED" /c

netstat -ano|findstr "PID"|find "ESTABLISHED" /c

解决办法

vim /etc/sysctl.conf在文件末端加上以下内容:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30

然后执行 /sbin/sysctl -p 让参数生效。

net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间
<Connector port="33011" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="20000" maxThreads="1000" URIEncoding="UTF-8" 
           keepAliveTimeout="0" />
           
          keepAliveTimeout 禁用 wait ,让连接在返回后立马关闭,成为一个可用连接

6.tomcat连接数调整

<Connector acceptCount="100"
           connectionTimeout="20000" 
           disableUploadTimeout="true"     
           enableLookups="false" m
           axHttpHeaderSize="8192" 
           maxSpareThreads="75" 
           maxThreads="150" 
           minSpareThreads="25" 
           port="9999" redirectPort="8442"/>
           

maxThreads="150" 表示最多同时处理150个连接

minSpareThreads="25" 表示即使没有人使用也开这么多空线程等待

maxSpareThreads="75" 表示如果最多可以空75个线程,例如某时刻有80人访问,之后没有人访问了,则tomcat不会保留80个空线程,而是关闭5个空的。

acceptCount="100" 当同时连接的人数达到maxThreads时,还可以接收排队的连接,超过这个连接的则直接返回拒绝连接。

connectionTimeout:网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000

enableLookups:是否反查域名,取值为:true或false。为了提高处理能力,应设置为false

disableUploadTimeout:允许Servlet容器,正在执行使用一个较长的连接超时值,以使Servlet有较长的时间来完成它的执行,默认值为false。 这个参数一般和 connectionUploadTimeout两个参数一起配合才能设置文件上传的超时时间为60秒,毕竟文件上传可能需要消耗更多的时间。

欢迎关注公众号:冒泡的肥皂

image.png