现象

压测过程中,发现应用服务器CPU使用率比较高(80%)

这种现象产生的原因,一可能是接口性能非常好,比如响应时间10ms,TPS很高,此时CPU使用率很高是正常的,不需要做代码层面的优化;还有一种情况就是接口性能不好,可能响应时间>200ms,TPS很低,这种情况下就需要定位问题并做优化了。

CPU消耗高的可能原因:

  1、使用了复杂的算法,比如加密解密;

  2、压缩、解压缩、序列化等操作;

  3、代码bug,比如死循环

 

案例

某接口测试结果如下:

Android 并发调用接口 接口并发调用cpu过高_性能测试

Android 并发调用接口 接口并发调用cpu过高_Android 并发调用接口_02

从上面的结果来看,平均时间响应时间较长,TPS也不高,这种情况下很可能是存在问题的。

 

问题分析方法一  用top和jstack

1、通过top命令查看占用CPU高的进程pid,然后执行top -p pid,手动输入H,可以查看应用程序内部的线程占用资源情况:

Android 并发调用接口 接口并发调用cpu过高_堆栈_03

注:上图中的pid对应的应该是堆栈日志中的nid,对应的是系统线程

2、将第1中占用CPU高的线程pid转成16进制

(1)可以通过linux命令将十进制转成16进制: printf "%x" 2662

(2)进制在线转换:https://tool.lu/hexconvert/

3、用jstack获取堆栈日志

4、用第2步中获取的16进制去堆栈日志中查找,链路比较长且状态是runnable的进程,并查看日志中是否有业务代码,这样应该可以找到CPU占用高的地方

Android 并发调用接口 接口并发调用cpu过高_性能测试_04

 

问题分析方法二   Jprofiler

  • jprofiler安装

使用jprofiler之前需要分别在对应的windows机器和服务器安装相同版本的jprofiler

windos安装:安装比较简单,直接下一步即可

linux安装:

  (1)上传安装包,执行命令rpm -ivh jprofiler_linux_9_1_1.rpm

  (2)tomcat/bin/catalina.sh文件配置JVM参数的地方添加:-agentpath:/opt/jprofiler11/bin/linux-x64/libjprofilerti.so=port=8849,nowait

  默认安装到/opt/jprofiler11目录下

 

  • jprofiler配置

1、打开jprofiler,点击Start Center

Android 并发调用接口 接口并发调用cpu过高_Android 并发调用接口_05

2、在弹出的窗口上选择New Session --> Mew Remote Integration

Android 并发调用接口 接口并发调用cpu过高_响应时间_06

3、选择 应用是在本机还是远程机器上。如下图:

Android 并发调用接口 接口并发调用cpu过高_Android 并发调用接口_07

4、选择JVM Vendor、版本选1.8,如下图:

Android 并发调用接口 接口并发调用cpu过高_16进制_08

5、开始模式选择下图中的第一个

Android 并发调用接口 接口并发调用cpu过高_堆栈_09

6、上图中点击下一步,填写远程tomcat安装地址:

Android 并发调用接口 接口并发调用cpu过高_响应时间_10

7、下一步后,下图中填写服务器中jprofiler安装目录

Android 并发调用接口 接口并发调用cpu过高_堆栈_11

8、下一步配置远程jprofile端口

Android 并发调用接口 接口并发调用cpu过高_响应时间_12

9、上述信息都填写完毕后,弹出窗口核对信息(注意:Please insert内容与我们之前写到tomcat配置文件里面的内容完全一致

Android 并发调用接口 接口并发调用cpu过高_响应时间_13

10、核对完成后点击下一步如下图,选择立即启动

Android 并发调用接口 接口并发调用cpu过高_16进制_14

11、默认选中第二种启动方式,我们也点击这个选项

Android 并发调用接口 接口并发调用cpu过高_Android 并发调用接口_15

12、下图中的Performance体现了当前占用的资源情况:

Android 并发调用接口 接口并发调用cpu过高_16进制_16

13、点击ok开始连接,下图中自动开始绘制图表,说明已经连上远程了。

Android 并发调用接口 接口并发调用cpu过高_Android 并发调用接口_17

 

  • Jprofile分析使用

1、查看线程监控,可以看到线程有很多阻塞的。

Android 并发调用接口 接口并发调用cpu过高_响应时间_18

2、查看CPU,使用率为100%。(说明当前阻塞不是主要问题,如果阻塞的话CPU不能100%打满)

Android 并发调用接口 接口并发调用cpu过高_响应时间_19

3、接着查看CPU views--Hot Spots (或者用Call Tree来看)

Android 并发调用接口 接口并发调用cpu过高_16进制_20

 从上图中我们能找到是某个接口的Gson.toJson序列化操作导致了cpu使用率高。