性能瓶颈分析与调优
对于性能测试,很多时候压力并不能完全到达服务端,在客户端、网络连接端都有可能被阻塞,或者压测的某些特征符合CC和DDoS的行为,触发了防护策略导致压测结果达不到预期。
以下是各节点可能发生性能瓶颈的地方:
- 客户端阻塞:线程设置不合理,压测机配置跟不上;
- 网络连接端:宽带、最大连接数、新建连接数的限制;
- 服务器端:CPU、内存、磁盘IO、Network I/O;
- 中间件相关指标:线程池、连接池、GC等;
- 数据库相关指标:慢查SQL、命中率、锁、参数设置;
- 应用程序:算法、缓冲、缓存、同步或异步。
瓶颈排查处理方案:
瓶颈应对手段
CPU:
如果CPU User非常高,需要查看消耗在哪个进程,可以用top(linux)命令看出,接着用top –H –p 看哪个线程消耗资源高,如果是java应用,就可以用jstack看出此线程正在执行的堆栈,看资源消耗在哪个方法上,查看源代码就知道问题所在;
如果CPU Sys非常高,可以用strace(linux)看系统调用的资源消耗及时间;
如果CPU Wait非常高,考虑磁盘读写,可以通过减少日志输出、异步或换速度快的硬盘。
内存:
内存的问题主要看某个进程占用的内存是否非常大以及是否有大量的swap(虚拟内存交换)。
磁盘IO:
磁盘I/O一个最显著的指标是繁忙率,可以通过减少日志输出、异步或换速度快的硬盘。
网络IO:
网络I/O主要考虑传输内容大小,不能超过硬件网络传输的最大值70%,可以通过压缩、减少内容大小、在本地设置缓存以及分多次传输等。
内核参数:
注意运行参数不要超过内核参数而导致系统出现问题
JVM:
jvm主要分析GC/FULL GC是否频繁,以及垃圾回收的时间,可以用jstat命令来查看,对于每个代大小以及GC频繁,通过jmap将内存dump,再借助工具HeapAnalyzer来分析哪地方占用的内存较高以及是否有内存泄漏可能。
线程池:
如果线程不够用,可以通过参数调整,增加线程;对于线程池中的线程设置比较大的情况,还是不够用可能的原因是:某个线程被阻塞来不及释放,可能在等锁、方法耗时较长、数据库等待时间很长等原因导致,需要进一步分析才能定位。
JDBC连接池:
连接池不够用的情况下,可以通过参数进行调整增加;但是对于数据库本身处理很慢的情况下,调整没有多大的效果,需要查看数据库方面以及因代码导致连接未释放的原因。
SQL:
慢SQL,可以通过查看执行计划看SQL慢在哪里来进一步优化。