现在可以发现,执行时间戳是因为本地的test调用远端的delay方法导致的,可以查看远程的delay代码优化了。
| 通过线程堆栈分析
生产环境中,大多数情况下没有条件通过jvisualvm的方式分析,因此只能通过执行堆栈来分析。
通过堆栈分析的话,最好是在应用出问题提交明显的情况下分析。
线程分析的根本为同一时间点同时执行某项任务的几率比较低,每次都被抓到的概率更低,如果每次都有相同的执行堆栈被抓取到,那肯定是有原因的,要么是长态任务,要么是有问题。
抓取线程堆栈
jstack 进程ID > /tmp/文件名.jstack
分析
- 3-
造成高延迟案例
| 示例 - 锁等待导致的响应时间长
在遇到堆栈中有大量的BLOCKED线程的情况下,如要确定是不是用了某些不合适的同步锁。
以下是一个锁等待导致的响应时间长的堆栈信息的摘取,可以看到大量的堆栈都在waiting一个lock。
另外,线程池中没有任务,或者大量的Queue的等待的话,线程池中的线程也会是blocked或者wait的状态,但是这个是正常的,因为他就是没事可做,在等待任务。
"Thread-96" #116 prio=5 os_prio=0 tid=0x00007f4efc677800 nid=0x2ba9 waiting for monitor entry [0x00007f4e69ddc000]
java.lang.Thread.State: BLOCKED (on object monitor)
at main.java.demo.delay.Client.testDelay(Client.java:47)
- waiting to lock <0x0000000785cd4748> (a java.lang.Class for main.java.demo.delay.Client)
at main.java.demo.delay.Client$1.run(Client.java:31)
at java.lang.Thread.run(Thread.java:745)
"Thread-95" #115 prio=5 os_prio=0 tid=0x00007f4efc675800 nid=0x2ba8 waiting for monitor entry [0x00007f4e69edd000]
java.lang.Thread.State: BLOCKED (on object monitor)
at main.java.demo.delay.Client.testDelay(Client.java:47)
- waiting to lock <0x0000000785cd4748> (a java.lang.Class for main.java.demo.delay.Client)
at main.java.demo.delay.Client$1.run(Client.java:31)
at java.lang.Thread.run(Thread.java:745)
"Thread-94" #114 prio=5 os_prio=0 tid=0x00007f4efc673800 nid=0x2ba7 waiting for monitor entry [0x00007f4e69fde000]
java.lang.Thread.State: BLOCKED (on object monitor)
at main.java.demo.delay.Client.testDelay(Client.java:47)
- waiting to lock <0x0000000785cd4748> (a java.lang.Class for main.java.demo.delay.Client)
at main.java.demo.delay.Client$1.run(Client.java:31)
at java.lang.Thread.run(Thread.java:745)
"Thread-93" #113 prio=5 os_prio=0 tid=0x00007f4efc671800 nid=0x2ba6 waiting for monitor entry [0x00007f4e6a0df000]
java.lang.Thread.State: BLOCKED (on object monitor)
at main.java.demo.delay.Client.testDelay(Client.java:47)
- waiting to lock <0x0000000785cd4748> (a java.lang.Class for main.java.demo.delay.Client)
at main.java.demo.delay.Client$1.run(Client.java:31)
at java.lang.Thread.run(Thread.java:745)
"Thread-92" #112 prio=5 os_prio=0 tid=0x00007f4efc66f800 nid=0x2ba5 waiting for monitor entry [0x00007f4e6a1e0000]
java.lang.Thread.State: BLOCKED (on object monitor)
at main.java.demo.delay.Client.testDelay(Client.java:47)
- waiting to lock <0x0000000785cd4748> (a java.lang.Class for main.java.demo.delay.Client)
at main.java.demo.delay.Client$1.run(Client.java:31)
at java.lang.Thread.run(Thread.java:745)
| 示例 - 第三方资源响应时间长
第三方的资源有问题导致调用方响应时间长的话,和锁等待的堆栈有点类似。
如果请求第三方为单线程则比较简单,直接查看该线程的堆栈,如果每次抓堆栈信息都能看到在请求第三方资源的话,那说明就是有问题了,因为在响应时间很短的情况下,你不大可能每次都能抓到请求中的堆栈。
如果是多线程访问的话,查看线程堆栈中是不是同时有很多线程同时在执行这些操作,如果有,则需要考虑是不是第三方资源有问题了,同第一次条原因,在响应时间很短的情况下,能抓到很多线程都在执行某一个操作,不太容易。