高并发下log4j的性能瓶颈

简介: 开篇  近期由于业务需要进行业务迁移,期间因为误设置log4j的日志级别,导致系统性能整体下降,具体表现在QPS下降明显,系统RT上升。迁移期间由于各类系统环境较原来有较大差别,因为在排查过程中也走了一些弯路,总结起来避免他人再次踩坑。

开篇

 近期由于业务需要进行业务迁移,期间因为误设置log4j的日志级别,导致系统性能整体下降,具体表现在QPS下降明显,系统RT上升。迁移期间由于各类系统环境较原来有较大差别,因为在排查过程中也走了一些弯路,总结起来避免他人再次踩坑。


问题背景

 问题的背景其实很简单,线上系统的log4j的日志级别由warn调整为info,导致大量的调用log4j的日志接口,导致系统的rt上升伴随着qps下降,具体的影响效果可以看下图。
 需要额外解释的就是log4j的这个问题需要在qps较大的情况下才会复现,按照我遇到的情况基本上需要在2k/s以上会比较明显(数据不一定非常准确),只是为了说明需要在大量请求的情况才会触发synchronized的问题。
 当然问题的本质在于大量调用log4j的日志接口,导致竞争synchronized影响性能,影响的时间应该也是在ms级别,这其实在另外一个方面说明了只求非常极致追求性能问题才会细致的去分析这些问题。


优化效果

优化后qps的提升效果图,这边是以分钟进行统计的。
请求量



优化后系统的响应时间效果图。
响应时间


现象分析

 整个分析过程其实并不是那么具有条理性,只是现在总结起来看上去像那么回事。

  • 对比两套系统的差异点,发现系统的log4j的日志级别不一致,尝试修改日志级别观察效果。
  • 发现日志级别调高后系统性能明显提升,开始怀疑log4j的问题并网上查阅资料。
  • jstack打印对应的日志,发现在不同日志级别情况下下面的BLOCKED的日志数量不一样。
  • 发现竞争锁的日志waiting to lock <0x00007f3a04020830>。
  • 观察jstack日志并找到log4j的源码发现代码当中有同步锁关键字synchronized。
#514 daemon prio=5 os_prio=0 tid=0x00007f369002f800 nid=0x561a waiting for monitor entry [0x00007f348fb96000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.apache.log4j.Category.callAppenders(Category.java:204)
    - waiting to lock <0x00007f3a04020830> (a org.apache.log4j.spi.RootLogger)
    at org.apache.log4j.Category.forcedLog(Category.java:391)
    at org.apache.log4j.Category.log(Category.java:856)


#521 daemon prio=5 os_prio=0 tid=0x00007f367c042800 nid=0x5617 waiting for monitor entry [0x00007f348fe99000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.apache.log4j.Category.callAppenders(Category.java:204)
    - waiting to lock <0x00007f3a04020830> (a org.apache.log4j.spi.RootLogger)
    at org.apache.log4j.Category.forcedLog(Category.java:391)
    at org.apache.log4j.Category.log(Category.java:856)


原因分析

 直接定位log4j的源码位置,发现synchronized的关键字,基本上这时候其实是验证之前的猜想而已。
关于synchronized的性能问题,可以网上去参考java几种锁的性能对比,只记得一个简单的结论synchronized在大量竞争的情况下劣势比较明显各种同步方法性能比较(synchronized,ReentrantLock,Atomic)

  void callAppenders(LoggingEvent event) {
    int writes = 0;

    for(Category c = this; c != null; c=c.parent) {
      // Protected against simultaneous call to addAppender, removeAppender,...
      synchronized(c) {
    if(c.aai != null) {
      writes += c.aai.appendLoopOnAppenders(event);
    }
    if(!c.additive) {
      break;
    }
      }
    }

    if(writes == 0) {
      repository.emitNoAppenderWarning(this);
    }
  }


心得

 老大曾说过,凡事做个有心人,会发现更多的东西。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
缓存 算法 安全
高并发下解决AtomicLong性能瓶颈的方案——LongAdder
高并发下解决AtomicLong性能瓶颈的方案——LongAdder
118 0
高并发下解决AtomicLong性能瓶颈的方案——LongAdder
|
4月前
|
Java
在高并发环境下,再次认识java 锁
在高并发环境下,再次认识java 锁
36 0
|
4月前
|
消息中间件 NoSQL Java
Java高级开发:高并发+分布式+高性能+Spring全家桶+性能优化
Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师之路
|
10天前
|
缓存 负载均衡 Java
Java高并发性能指标
Java高并发是指在Java编程环境中,系统能够同时处理大量并发请求或操作的能力。这里的“高”强调的是并发处理的数量级较大,需要系统能够有效地管理多个并发的执行单元,如线程或进程,以确保它们能够高效且正确地执行。
10 0
|
15天前
|
JavaScript Java 测试技术
基于Java的高并发慕课网的设计与实现(源码+lw+部署文档+讲解等)
基于Java的高并发慕课网的设计与实现(源码+lw+部署文档+讲解等)
23 2
|
4月前
|
Java Go C语言
高并发时代到底是Go还是Java?
作为一名用过Java和Go开发过微服务架构程序的在校学生的角度思考,本文将从以下几个方便来讲述Go和Java的区别。
|
4月前
|
Java 数据库连接 微服务
Java程序员必学知识:高并发+微服务+数据结构+Mybatis实战实践
BATJ最全架构技术合集:高并发+微服务+数据结构+SpringBoot 关于一线互联网大厂网站的一些特点:用户多,分布广泛、大流量,高并发、海量数据,服务高可用、安全环境恶劣,易受网络攻击、功能多,变更快,频繁发布、从小到大,渐进发展、以用户为中心。 如果你工作中够仔细,你会发现这些特点跟高并发、分布式、微服务、Nginx这些技术密切相关的,是因为只要你的公司在上升,用户量级都会与日俱增,高性能、高并发的问题自然避免不了,话不多说往下看。
|
4月前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
5月前
|
缓存 容灾 网络协议
Java面试题 -高并发、高可用、分布式
Java面试题 -高并发、高可用、分布式
85 0
|
7月前
|
缓存 弹性计算 算法
Java高并发系统限流算法的应用
Java高并发系统限流算法的应用
63 0

热门文章

最新文章