在Linux操作系统中,通常采用8个不同的指标来研究Unix / Linux操作系统中的CPU消耗:用户CPU时间(us)、系统CPU时间(sy)、良好的CPU时间(ni)、空闲CPU时间(id)、等待CPU时间(wa)、硬件中断CPU时间(hi),软件中断CPU时间(si),被盗CPU时间(st)。在本文中,我们主要对“用户CPU时间”进行解析。
什么是“用户” CPU时间?
为了了解“用户CPU时间”,我们也应该同时了解“系统CPU时间”。用户CPU时间是处理器运行应用程序代码所花费的时间。系统CPU时间是处理器在运行连接到您的应用程序的操作系统(即内核)功能上花费的时间。假设我们的应用程序正在处理数组中的元素;然后,它将被计为“用户” CPU时间。假设我们的应用正在对外部应用组件进行网络调用。要进行网络调用,它必须将数据读/写到套接字缓冲区中,这是操作系统代码的一部分。这将被视为“系统CPU”时间。
如何找到“用户” CPU时间?
通常可以从以下来源找到用户CPU时间:
1、可以使用基于网络的分析工具来报告“用户” CPU时间。如果“用户” CPU时间超出阈值,该工具便能够生成警报。
2、Unix / Linux命令行工具“顶部”在“我们”字段中也报告了“用户” CPU时间,如下图命令行返回结果所示:
[administrator@JavaLangOutOfMemory nacos-docker ]%top top - 14:06:23 up 70 days, 16:44, 2 users, load average: 1.25, 1.32, 1.35 Tasks: 206 total, 1 running, 205 sleeping, 0 stopped, 0 zombie Cpu(s): 5.9%us, 3.4%sy, 0.0%ni, 90.4%id, 0.0%wa, 0.0%hi, 0.2%si, 0.0%st Mem: 32949016k total, 14411180k used, 18537836k free, 169884k buffers Swap: 32764556k total, 0k used, 32764556k free, 3612636k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 28894 root 22 0 1501m 405m 10m S 52.2 1.3 2534:16 java 18249 root 18 0 3201m 1.9g 11m S 35.9 6.0 569:39.41 java ... ...
如何模拟较高的“用户” CPU时间?
为了模拟高“用户” CPU报告,我们写个简单的Demon。将其打成jar包,使其运行以模拟各种性能问题。当我们启动此应用jar包时,它将导致主机上的“用户” CPU消耗激增。具体如下:
[administrator@JavaLangOutOfMemory cpu %]java -jar devopsDemo.jar PROBLEM_CPU
针对此应用jar包,我们看下其部分代码如下:
public class DevopsDemo { public static void start() { new DevopsrThread().start(); new DevopsrThread().start(); new DevopsrThread().start(); new DevopsrThread().start(); new DevopsrThread().start(); new DevopsrThread().start(); new DevopsrThread().start(); new DevopsrThread().start(); System.out.println("8 threads launched!"); } } public class DevopsrThread extends Thread { @Override public void run() { while (true) { doSomething(); } } public static void doSomething() { // Does nothing } }
可以看到devopsDemo应用在“ DevopsDemo”类中启动8个“ DevopsrThread”。同时,我们会注意到“ DevopsrThread”正在进行无限的while循环,并一次又一次地调用“ doSomething()”函数。这个doSomething()方法没有任何作用。
因此,如果线程在应用程序级代码上无限循环,那么“用户” CPU时间将开始增加。
如何解决“用户” CPU时间过长的问题?
通常主要有以下策略:
1、重新启动CPU消耗很大的过程。此策略为临时方案
2、借助相关工具,例如,jstatck之类的根本原因分析工具,识别导致CPU大量启动的应用程序中的代码行,并加以修复。
具体可参考文章:Java ThreadDump 生成解析
3、如果CPU消耗始终很高(即 7 x 24),则可能表明资源设备的计算能力不足。在这种情况下,我们可以尝试执行以下操作:升级设备的容量,可尝试将应用服务转移到更好的资源实例环境);减少该设备上运行的进程数;联机负载,即,借助横向扩容方式分担压力。