性能优化 ---- 如何排查线上性能问题

零. 概述

又到了一年一度某电商帝国双十一大促备战阶段,今年我负责稳定性这块,系统压测找出性能瓶颈就是其中之一的工作。在压测某个系统 A,线上集群发现 CPU 使用率 50%,8C-16G-200G 的容器 load 达到 13 左右,吓得立刻下掉了压测流量。然后在预发环境单机压测寻找性能瓶颈,废话不多说,下面开始分析步骤。

一. 性能问题排查

压测预发环境 单机 8C-16G-200G ,压测目标 1800 QPS。

观察:GC 次数/时间可控,数据库RT维持在5ms以内,连接数使用正常2000+,只有 CPU 一项非常异常,使用率 90%,超过水位值 60%,load1 达到 45

压测中进行了一次 java dump,观察线程情况,发现了 TIMED_WAITING 占了 80%,那么说明这可能是他们都在等一个抢手的资源,也可能是正常的,他们是需要等待某个时机才能继续做。

"Keep-Alive-Timer" #1159 daemon prio=8 os_prio=0 tid=0x00007fd9dc014000 nid=0x7853 sleeping[0x00007fd99abfb000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep0(Native Method)
    at java.lang.Thread.sleep(Thread.java:398)
    at sun.net.www.http.KeepAliveCache.run(KeepAliveCache.java:172)
    at java.lang.Thread.run(Thread.java:882)

   Locked ownable synchronizers:
    - None

从堆栈没看出到底卡在哪个地方了?知道是线程卡住了,我们可以借助一下阿里巴巴开源的 Arthas 来协助排查,使用 Thread -b 可以打印出线程被卡在哪里

thread -b
"http-bio-8080-exec-4" Id=27 TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at org.apache.log4j...
    -  locked java.lang.Object@725be470 <---- but blocks 66 other threads!
    

可以看出来我们是被日志打印卡住了,我们知道 log4j、logback 默认的日志打印都是同步的,且要是打印的是 debug或者info 级别会打印非常多日志,非常消耗系统cpu及线程资源。知道问题原因,那么问题就好解决了,日志改成异步打印,线上系统只打印 ERROR 或者 WARN。改造之后压测 QPS 立刻就能压到目标值 1800,没改造前最多单机只能到 980。 

发布了159 篇原创文章 · 获赞 350 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/wenniuwuren/article/details/102525078