CPU飙升排查思路

叁歲伎倆 2022-10-19 05:31 301阅读 0赞

最近公司有个需求是对接E签宝的,也就是CA认证,大致的情况就是我们拿着文件去E签宝做CA认定,简单的理解就是拿着合同去E签宝盖章。
因为是对接三方的吗,所以在调E签宝服务的时候我就用log.info()把请求参数给打印了出来,方便看组装的参加,排查问题,参数中就包含我们的合同文件流,所以整个参数是一个大对象。在做压测的时候发现CPU很快就飙升到100%,并且耗时很久。但是我把打印日志的log.info()去掉之后,CPU和耗时马上就降下来了。下面开始排查这个问题:

首先使用top命令查看进程运行情况:

  1. # top
  2. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
  3. 7020 root 20 0 2538892 164144 11856 S 90.3 8.7 61:23.54 java
  4. 11022 root 20 0 2560528 241340 11920 S 0.3 12.8 311:23.23 java
  5. 26805 root 20 0 32612 4036 2472 S 0.3 0.2 24:50.95 AliYunDunUpdate
  6. 26838 root 10 -10 134120 14524 5924 S 0.3 0.8 343:05.22 AliYunDun
  7. 1 root 20 0 43280 3300 2108 S 0.0 0.2 2:16.82 systemd
  8. 2 root 20 0 0 0 0 S 0.0 0.0 0:01.78 kthreadd
  9. 3 root 20 0 0 0 0 S 0.0 0.0 1:30.68 ksoftirqd/0
  10. 5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
  11. 7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
  12. 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
  13. 9 root 20 0 0 0 0 S 0.0 0.0 65:15.85 rcu_sched
  14. 10 root rt 0 0 0 0 S 0.0 0.0 2:14.65 watchdog/0
  15. 12 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
  16. 13 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 netns
  17. 14 root 20 0 0 0 0 S 0.0 0.0 0:00.00 khungtaskd
  18. 15 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 writeback
  19. 16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kintegrityd

查询到7020这个进程有异常,在继续查看具体异常线程。

  1. # top -Hp 7020
  2. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
  3. 23328 root 20 0 2538892 164144 11856 S 90.0 8.7 0:00.00 java

找到了当前异常进程下的异常线程后使用jstack查看详细情况

  1. # jstack -l 6377 > error.log
  2. 将线程ID打印成16进制形式
  3. # printf "%x\n" 23328
  4. 5b20

然后从jstack里查询该线程信息

  1. # grep '18e9' error.log --color
  2. "http-bio-6379-exec-200" #8869954 daemon prio=5 os_prio=0 tid=0x00007f74a81f6800 nid=0x5b20 waiting for monitor entry [0x00007f742457f000]

最后从jstack文件定位到堆栈信息

  1. "http-bio-7020-exec-200" #8869954 daemon prio=5 os_prio=0 tid=0x00007f74a81f6800 nid=0x5b20 waiting for monitor entry [0x00007f742457f000]
  2. java.lang.Thread.State: BLOCKED (on object monitor)
  3. at org.apache.log4j.Category.callAppenders(Category.java:204)
  4. - waiting to lock <0x00000000800371d0> (a org.apache.log4j.spi.RootLogger)
  5. at org.apache.log4j.Category.forcedLog(Category.java:391)
  6. at org.apache.log4j.Category.log(Category.java:856)
  7. at org.slf4j.impl.Log4jLoggerAdapter.info(Log4jLoggerAdapter.java:368)

结论

在log4j 中,logger.info等日志记录方法是同步的(使用了synchronized),大量的日志导致线程阻塞在callAppenders()这个方法,也就是这个地方导致压测阻塞,响应耗时比较久的问题。

  1. public void callAppenders(LoggingEvent event) {
  2. int writes = 0;
  3. for(Category c = this; c != null; c = c.parent) {
  4. synchronized(c) {
  5. if (c.aai != null) {
  6. writes += c.aai.appendLoopOnAppenders(event);
  7. }
  8. if (!c.additive) {
  9. break;
  10. }
  11. }
  12. }
  13. if (writes == 0) {
  14. this.repository.emitNoAppenderWarning(this);
  15. }
  16. }

发表评论

表情:
评论列表 (有 0 条评论,301人围观)

还没有评论,来说两句吧...

相关阅读

    相关 记一次cpu飙升问题排查

    前言 首先问题是这样的,周五正在写文档,突然收到了线上报警,发现cpu占用达到了90多,上平台监控系统查看容器,在jvm监控中发现有一个pod在两个小时内产生了61次yo

    相关 CPU飙升排查思路

    最近公司有个需求是对接E签宝的,也就是CA认证,大致的情况就是我们拿着文件去E签宝做CA认定,简单的理解就是拿着合同去E签宝盖章。 因为是对接三方的吗,所以在调E签宝服务的