最近遇到了这种情况了,客户反映登录不上,但是登录页面能打开,看了日志没发现有特别大的异常(有报错但是不会导致系统死掉的那种。还有是接口有个接口优化了但是日志上显示有个数据推送中间停了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.
JVM年轻代,老年代,永久代详解
eden和survivor默认比例是8:1:1,进行垃圾回收采用的是分代复制算法。 每次新生代的使用,会是eden区和一块survivor区。当我们进行垃圾回收的时候,清除正在使用的区域,将其中的存活对象,放入到另一个survivor区域,并进行整理,保证空间的连续。如果对象长时间存活,则将对象移动到老年区。存活下来的对象,他的年龄会增长1。当对象的年龄一次次存活,一次次增长,到达15的时候,这些对象就会移步到老年代。在年轻代执行gc的时候,如果老年代的连续空间小于新生代对象的总大小,就会触发一次full gc。是为了给新生代做担保,保证新生代的老年对象可以顺利的进入到老年代的内存区。
我们知道垃圾回收机制有三种,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进行移动,消耗性能。每种类型的垃圾回收都需要特殊处理元数据。将元数据剥离出来,简化了垃圾收集,提高了效率。
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的所用的总时间。
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秒,毕竟文件上传可能需要消耗更多的时间。
欢迎关注公众号:冒泡的肥皂