0


TPS死活上不去,为啥?

项目背景

这个接口大概每天早上7点到8点有100万人使用,你安排个压测吧!

接到了这个任务,发现这个接口在容量测试过程中,发现无论并发用户数有多大,TPS无增长,响应时间随着用户数的增加而增加,服务器资源消耗较小,并在逐渐增加并发用户数的过程中,出现大量超时报错。

疑问一:为何增加并发用户数时,响应时间随之递增,TPS无增长趋势?

疑问二:为何有大量超时报错产生?

疑问三:为何并发用户数增加,服务器资源损耗不增加?

地址:http://IP:8080/syncMethod

请求:GET

参数:type:0

4.2分析思路

一般遇到此类问题先看线程或者线程池,最好是可以通过链路追踪工具宏观的看下整个链路的走势。

4.3排查手段

4.3.1方法一:Jstack线程dump方式

  1. 查看目标进程的pid(下面任意命令都可以)
ps -ef | grep <应用信息包含的关键字符> jps # 可查看所有的java进程的pid
  1. 执行线程dump命令
jstack <pid> > xxx.log
  1. 快照的内容分析

"http-nio-18080-exec-30" #155 daemon prio=5 os_prio=0 tid=0x00007fb4356cf000 nid=0x7814 waiting for monitor entry [0x00007fb38c98e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
at com.perf.demo.cases.Perf_Synchronized_Method.run_static(Perf_Synchronized_Method.java:34)
- waiting to lock <0x00000000ec2a9498> (a java.lang.Class for com.perf.demo.cases.Perf_Synchronized_Method)
at com.perf.demo.cases.Perf_Synchronized_Method.run(Perf_Synchronized_Method.java:26)
at com.perf.demo.controller.PerfCaseController.Synchronized_Method(PerfCaseController.java:264)
at sun.reflect.GeneratedMethodAccessor378.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
······
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
- locked <0x00000000ec9731d8> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper)
at com.perfma.agent.ttl.TtlRunnable.run(TtlRunnable.java:65)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
  1. 如何判断线程阻塞

我们所说的线程阻塞,也即java.lang.Thread.State这个字段的值为BLOCKED。所以Dump文件中存在状态BLOCKED的线程就表示当前应用中存在线程阻塞的情况。

  1. 如何调优

丢给开发?

NO!NO!NO!

直接丢给开发,算什么性能测试,我们需要进一步进行分析!

4.3.2方法二:Arthas反编译的方式

  1. 打开arthas
java -jar arthas-boot.jar

  1. 监控被测应用

启动的过程中,会把当前机器上的java进程打印出来,我们只需要输入[id]中的数字并按回车键,就能快速监控目标进程。

  1. 查看是否存在线程阻塞
dashboard -i 5000 -n 10

参数名称

参数说明

[i:]

刷新实时数据的时间间隔 (ms),默认 5000ms

[n:]

刷新实时数据的次数

  1. 使用thread命令查看
thread -b

  1. 分析阻塞原因
jad com.perf.demo.cases.Perf_Synchronized_Method

对类进行反编译,查看源码

  1. 调优手段

降低锁的粒度

临界区代码块或者方法长度(或复杂度)

4.4线程那点事

4.4.1线程的6种状态

  1. NEW

至今尚未启动的线程的状态。线程刚被创建,但尚未启动。

  1. RUNNABLE

可运行线程的线程状态。线程正在JVM中执行,有可能在等待操作系统中的其他资源,比如处理器。

  1. BLOCKED

受阻塞并且正在等待监视器的某一线程的线程状态。处于受阻塞状态的某一线程正在等待监视器锁,以便进入一个同步的块/方法,或者在调用 Object.wait 之后再次进入同步的块/方法。

在Thread Dump日志中通常显示为 java.lang.Thread.State: BLOCKED (on object monitor) 。

  1. WAITING

某一等待线程的线程状态。线程正在无期限地等待另一个线程来执行某一个特定的操作,线程因为调用下面的方法之一而处于等待状态:

  • 不带超时的 Object.wait 方法,日志中显示为 java.lang.Thread.State: WAITING (on object monitor)
  • 不带超时的 Thread.join 方法
  • LockSupport.park 方法,日志中显示为 java.lang.Thread.State: WAITING (parking)
  1. TIMED_WAITING

指定了等待时间的某一等待线程的线程状态。线程正在等待另一个线程来执行某一个特定的操作,并设定了指定等待的时间,线程因为调用下面的方法之一而处于定时等待状态:

  • Thread.sleep 方法
  • 指定超时值的 Object.wait 方法
  • 指定超时值的 Thread.join 方法
  • LockSupport.parkNanos
  • LockSupport.parkUntil
  1. TERMINATED

线程处于终止状态

4.4.2各状态转换概念图

4.4.3线程阻塞的含义

当前线程 没有条件(锁) 执行 某个方法,而被挂起(让出CPU执行权),等待获取执行条件(锁)。

从整个应用来看,原本线程应该执行业务代码并快速返回结果的,但是现在线程被挂起等待了,因此相应的我们的RT也就增加了。


本文转载自: https://blog.csdn.net/qq_28569939/article/details/130097116
版权归原作者 无可无奈 所有, 如有侵权,请联系我们删除。

“TPS死活上不去,为啥?”的评论:

还没有评论