问题排查步骤
检查是否服务异常(OOM)或GC异常
-
查看线程是否存活。
ps -aux|grep xxx.jar
-
查看日志,并没有抛出异常,是否发生OOM。
tail -1000f log.log
JVM添加OOM时导出dump文件参数,可以采用jvisualvm等工具进行分析。
-XX:+HeapDumpOnOutOfMemoryError//开启导出 -XX:HeapDumpPath=./ //导出路径
导出dump文件参数(直接复制版)
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
-
使用arthas查看是否死锁
thread -b
-
使用arthas查看是否重复GC
dashboard
在JVM启动项中添加GC日志参数
‐Xloggc:./gc‐%t.log //GC文件命名 ‐XX:+PrintGCDetails //展示GC细节 ‐XX:+PrintGCDateStamps //展示日期时间 ‐XX:+PrintGCTimeStamps //展示小时时间 ‐XX:+PrintGCCause //展示GC原因 ‐XX:+UseGCLogFileRotation //开启GC文件输出 ‐XX:NumberOfGCLogFiles=10 //GC文件最大总数量 ‐XX:GCLogFileSize=100M //GC最大大小
添加GC日志参数(直接复制版)
‐Xloggc:./gc‐%t.log ‐XX:+PrintGCDetails ‐XX:+PrintGCDateStamps ‐XX:+PrintGCTimeStamps ‐XX:+PrintGCCause ‐XX:+UseGCLogFileRotation ‐XX:NumberOfGCLogFiles=10 ‐XX:GCLogFileSize=100M
GC日志可以用GC分析工具进行分析,如GCViewer【提取码:qqwb】,也可以使用GCEasy进行分析。
个人调整链接
检查是否是JVM线程阻塞
-
查看与之关联的网络请求状态
netstat -nat|grep 端口
-
查看是否为微服务内部阻塞,使用Jstack进行导出微服务线程执行以及状态
jstack [PID] > jstack.log
分析jstack.log,查询线程名称包含
http
的线程(包含http
的线程名为外部访问的HTTP请求的线程,当然也可以自定义线程名字)"http-nio-9084-exec-1059" #18281 daemon prio=5 os_prio=0 tid=0x00007f951cc17000 nid=0x75de waiting on condition [0x00007f947d1cf000] java.lang.Thread.State: WAITING (parking) //线程状态 at sun.misc.Unsafe.park(Native Method) //阻塞方法,后面都为调用了链路 - parking to wait for <0x00000000802d02f7> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:590) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:425) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:346) at redis.clients.util.Pool.getResource(Pool.java:49) at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226) at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:70) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:113) at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:58) at redis.clients.jedis.BinaryJedisCluster.hget(BinaryJedisCluster.java:373) at org.springframework.data.redis.connection.jedis.JedisClusterHashCommands.hGet(JedisClusterHashCommands.java:95)
解决阻塞问题即可。
网络上存在的其他情况或临时解决方法。
- httpClientUtils工具类中未调用close方法,未指定超时等问题。
- 针对暂未排除查出问题的,设置ipv4的超时,如果多个应用部署在同一个服务器,可能存在使用ipv6协议。
修改/etc/sysctl.conf
文件# 禁用整个系统所有接口的IPv6 net.ipv6.conf.all.disable_ipv6 = 1 # 禁用某一个指定接口的IPv6(例如:eth0, lo) net.ipv6.conf.lo.disable_ipv6 = 1 net.ipv6.conf.eth0.disable_ipv6 = 1 # 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间 net.ipv4.tcp_fin_timeout = 3 # 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟 net.ipv4.tcp_keepalive_time = 1200 # 表示开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭 net.ipv4.tcp_syncookies = 1 # 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭 net.ipv4.tcp_tw_reuse = 1 # 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 net.ipv4.tcp_tw_recycle = 1 # 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。 net.ipv4.ip_local_port_range = 1024 65000 # 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。 net.ipv4.tcp_max_syn_backlog = 8192 # 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改为5000。 net.ipv4.tcp_max_tw_buckets = 5000
可以临时使用,不建议长时间使用,只是降低了发生概率而已,并没有彻底解决问题。
网络阻塞异常
-
直接测试网络ip
ping [ip]
-
测试网络端口
telnet ip port
-
使用postman直接测试端口