线上运行的项目突然变得很卡如何排查?
我们可能在项目部署后遇到一些问题,某一块模块功能或者全部的模块功能在某一时间段特别卡,我们应该如那些方面去排查呢?接下来我们一起去探究一下。
1、如果所有的模块都卡:
极有可能是网络出问题,cpu被拉满了。
2、如果是单一个模块的变得卡,其他模块都正常:
变卡的问题可能性点:文件句柄,IO流,SOCKET流,代码中sql不规范,数据库连接资源,数据库连接问题导致锁无法释放,代码中sleep过长,线程池使用不规范等等。
优先查看最近的代码提交是否符合规范。
如果上述无法确认,线上触发调用从接口调用出开始排查日志,查看每一次关键日志的时间信息,看能否确定哪一个调用链路时
间耗费过长,查看当前文件句柄,IO流,SOCKET流是否资源关闭正常,去数据库执行当前的sql语句看是否为慢sql,是否因为少参数问
题导致全表查询。
如果上述还无法确定,可以在触发线上调用之后看一下当前线程的dump信息
####使用top -H指令看每个线程的性能(如果有某个线程的cpu利用率一直是100,记录下pid) root@hadoop top -H ####将上步骤的pid转换成线程用的nid(16进制的) printf "%x\n" 上一步的pid ###获取当前项目的java的pid root@hadoop ps -aux | grep java tomcat 1538 17.1 39.4 11175396 6620524 ? Sl Jul09 3629:14 /opt/taobao/install/ajdk-8.1.1_fp1-b52/bin/java -server -Xms5334m -Xmx5334m -Xss1m -XX:PermSize=128m -XX:MaxPermSize=256m -Xmn2000m -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSMaxAbortablePrecleanTime=5000 -XX:+CMSParallelRemarkEnabled -XX:+CMSClassUnloadingEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -verbose:gc -Xloggc:/alidata/www/logs/tomcat7/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:-HeapDumpOnOutOfMemoryError -XX:ErrorFile=/usr/share/tomcat7/logs/hs_err_pid%p.log -XX:HeapDumpPath=/usr/share/tomcat7/logs/java_pid.hprof -verbose:gc -Xloggc:/alidata/www/logs/tomcat7/gc.log-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Djdk.tls.rejectClientInitiatedRenegotiation=true -Dsun.net.inetaddr.ttl=0 -Dcatalina.logs=/usr/share/tomcat7/logs -Dlog4j.defaultInitOverride=true -Dlog4j.dir=/alidata/www/logs/tomcat7 -Dlog4j.level=WARN -Dproject.name=ecm-server -javaagent:/alidata/tianjimon-apm/tianjimon-apm.jar -classpath :/usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar: -Dcatalina.base=/usr/share/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.endorsed.dirs= -Djava.io.tmpdir=/tmp -Djava.util.logging.config.file=/usr/share/tomcat7/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager org.apache.catalina.startup.Bootstrap start root 124342 0.0 0.0 61260 1864 pts/6 S+ 16:40 0:00 grep java ####使用pid dump当前运行的线程信息 root@hadoop jstack 1538 >> dump.log ####统计所有的线程状态 root@hadoop grep Thread.State dump.log| awk '{print $2 $3 $4 $5}' | sort | uniq -c 40 RUNNABLE 21 TIMED_WAITING(onobjectmonitor) 5 TIMED_WAITING(parking) 44 TIMED_WAITING(sleeping) 200 WAITING(onobjectmonitor) 3 WAITING(parking) ####如果有大量WAITING的线程,可以查看当前dump.log中WAITING的线程在干什么,如果WAITING的线程日志中有await,说明有大量线程空闲状态。如果有大量的WAITING,会造成过多的线程上下文切换次数【因为WAITING状态是等待状态,等待就绪,等待cpu调度,每一次WAITING到RUNNABLE都会进行一次上下文切换】 ###将第二步骤的线程nid拿过来去dump.log查询当前线程在干什么(示例) locked <0x00000007d0015508>,再waiting on <0x00000007d0015508> "Finalizer" #3 daemon prio=8 os_prio=31 cpu=0.43ms elapsed=283151.83s tid=0x00007fd4b301f800 nid=0x3803 in Object.wait() [0x0000700002aba000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(java.base@11.0.10/Native Method) - waiting on <0x00000007d0015508> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(java.base@11.0.10/ReferenceQueue.java:155) - locked <0x00000007d0015508> (a java.lang.Object) at java.lang.ref.ReferenceQueue.remove(java.base@11.0.10/ReferenceQueue.java:176) at java.lang.ref.Finalizer$FinalizerThread.run(java.base@11.0.10/Finalizer.java:170) ######日志中如果能体现线程使用不合理,需要去代码中去看下线程池的使用是否规范,是否有代码不合理的地方