这个项目本身并不复杂springboot做的网关请求其他dubbo服务,本身没有逻辑的功能,主要是接收请求鉴权,请求dubbo服务。
运行一段时间cpu就升高到30%, 10%,40%,忽高忽低。原本认为是请求负载问题,增加服务器后仍然出现该问题,于是决定排查一下cpu
升高原因。
Jstack是Jdk自带的线程跟踪工具,几种线程状态
1.NEW
线程刚刚被创建,也就是已经new过了,但是还没有调用start()方法,jstack命令不会列出处于此状态的线程信息。
RUNNABLE
RUNNABLE这个名字很具有欺骗性,很容易让人误以为处于这个状态的线程正在运行;事实上,这个状态只是表示,线程是可运行的。一个单核CPU在同一时刻,只能运行一个线程。
BLOCKED
线程处于阻塞状态,正在等待一个监视器锁(monitor lock)。通常情况下,是因为本线程与其他线程公用了一个锁。其他在线程正在使用这个锁进入某个synchronized同步方法块或者方法,而本线程进入这个同步代码块也需要这个锁,最终导致本线程处于阻塞状态,
2.WAITING
等待状态,等待某个condition或monitor发生,调用以下方法可能会导致一个线程处于等待状态:
wait() 不指定超时时间;
join() 不指定超时时间;
park() ;
3.TIMED_WAITING
线程等待指定的时间,对于以下方法的调用,可能会导致线程处于这个状态:
wait(long timeout) 指定超时时间;
join(long millis) 指定超时时间;
sleep(long millis) 指定超时时间;
parkNanos(long nanos) ;
parkUntil(long deadline);
4.TERMINATED:线程终止。
具体使用:
1.top命令找出最高占用的进程 PID
2.查看高负载进程下的高负载线程:top -Hp 【PID】 (或 ps -mp PID -o THREAD,tid,time)
3.找出最高占用的线程并记录thread_id,把线程号 进行换算成16进制编号:printf "%X\n" thread_id,如结果4f50
4.查看高负载的线程找到具体执行方法:jstack 1555【进程】 | grep 4f50【线程】 -a 100 (-a 100 意思打印100行)
5.也可以导出进程的堆栈日志,找到4f50这个线程号:jstack 1555>/home/16143.log
我这里结果
"http-nio-60000-exec-17" #417 daemon prio=5 os_prio=0 tid=0x00007f23d000a000 nid=0x4f50 waiting on condition [0x00007f238601f000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006c9168218> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
at org.apache.tomcat.util.threads.TaskQueue.poll(TaskQueue.java:89)
at org.apache.tomcat.util.threads.TaskQueue.poll(TaskQueue.java:33)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
发现是大量的lock问题,我们程序本身没有用到lock,应该是springboot的问题。搜索之后发现该bug是springboot 2.2.*存在的问题。在github springboot issue下也找到了该问题,
降到2.1.13 正式环境运行,发现问题解决。
这里还有其他的分析工具,详见帖子 https://www.cnblogs.com/caicz/p/14283376.html