系统压测时CPU达到100%但是QPS却很低
发布网友
发布时间:2022-12-24 09:36
我来回答
共1个回答
热心网友
时间:2023-10-08 23:46
线上系统,正在做压力测试,刚开始10并发进行压测,cpu压到了100%但是系统最大qps才200多。通过JVM监控查看JVM younggc很频繁,fullGC数量为零。
cpu 达到100% 则先看cpu使用率最高是哪个进程,可以直接通过linux命令 top查看,找到对应的进程ID,发现正是压测的java系统进程ID,找到进程ID后,然后在查找该进程下CPU使用率最高是哪个线程,可以通过top -p 进程ID -H 命令显示线程使用cpu信息,效果如下:
图片中PID列则为十进制显示的线程ID,然后转换为16进制通过jstack 系统进程ID | grep 16进制线程ID 可以找到对应的线程信息如下,也就是该线程占用了一半左右的cpu
Finalizer线程是个单一职责的线程。这个线程会不停的循环等待java.lang.ref.Finalizer.ReferenceQueue中的新增对象。一旦Finalizer线程发现队列中出现了新的对象,它会弹出该对象,调用它的finalize()方法,将该引用从Finalizer类中移除,因此下次GC再执行的时候,这个Finalizer实例以及它引用的那个对象就可以回垃圾回收掉了。
说明Finalizer的队列中有许多的等待回收的垃圾对象,可以通过命令查看等待回收的对象都有哪些;
jmap -finalizerinfo 进程ID
执行命令后显示结果如下
发现有好多的自定义对象,通过类名可以看到这些对象都是通过CGLIB动态代理创建的,而这些动态代理类都默认实现了finalize方法,导致这些对象在进行垃圾回收时必须先要执行finalize方法,所以都积压到了finalizer的队列中。
1.不要使用cglib来给那些需要频繁进行垃圾回收的对象创建动态代理,这些对象大量创建的同时,也会创建相等数量的动态代理对象,使得内存占用迅速增长,并且不断进行垃圾回收,由于代理类重写了finalize方法,给垃圾回收带来了额外的压力。
2.尽量能够复用对象,不要每次都new一个对象