Log4j2AsyncLoggerConfig导致线程Block

文章讲述了在Log4j2中,由于未配置Log4jContextSelector,使用同步Logger而非AsyncLogger导致的日志处理线程Block问题。AsyncLoggerConfig利用Disruptor队列异步处理日志,但在大量异常堆栈输出时,由于类加载机制,特别是反射调用的优化字节码加载慢,引发了线程阻塞现象。
摘要由CSDN通过智能技术生成

AsyncLoggerConfig 导致线程 Block

​ 通过监控平台查看线程监控指标,从 Blocked 线程堆栈不难看出是和日志打印相关。分析异常线程堆栈 与(AsyncAppender 导致线程 Block)业务异常一样。

解析异常堆栈

Log4j2 关于日志的几个重要概念:

● ,日志配置标签,用于 XML 日志配置文件中,对应 Log4j2 框架中的 LoggerConfig 类,同步分发日志事件到对应 Appender。

● ,日志配置标签,用于 XML 日志配置文件中,对应 Log4j2框架中的 AsyncLoggerConfig 类,内部使用 Disruptor 队列异步分发日志事件到对应 Appender。

● Logger,同步日志类,用于创建同步日志实例,同步调用 ReliabilityStrategy处理日志。

● AsyncLogger**,异步日志类,用于创建异步日志实例**,内部使用 Disruptor 队列实现异步调用 ReliabilityStrategy 处理日志

​ 由于未配置 Log4jContextSelector 参数,所以使用的是同步 Logger,即通过 LoggerFactory.getLogger 方法获取的是 Logger 类实例而不是 AsyncLogger类实例,同时由于项目的 log4j2.xml 配置文件里配置了 标签,所以其底层是 Logger 和 AsyncLoggerConfig 组合

​ AsyncLoggerConfig 处理日志事件,其内部使用 Disruptor队列,在生成队列元素时,由 translator 来负责填充元素字段,并把填充后的元素放入 RingBuffer 中,于此同时,独立的异步线程从 RingBuffer 中消费事件,并调用配置在该 AsyncLoggerConfig 上的 Appender 处理日志请求。

AsyncLoggerConfig 提 供 了 带 有 Disruptor 队 列 实 现 的 代 理 类 即 AsyncLoggerConfigDisruptor, 在 日 志 事 件 进 入 RingBuffer 时, 由 于 项 目 使 用 的 是ReusableLogEventFactory,所以由 MUTABLE_TRANSLATOR 负责初始化日志事件,在此过程中会调用 getThrownProxy 方法创建 ThrowableProxy 实例,进而在 ThrowableProxy 构造函数内部触发解析、加载异常堆栈类

问题小结

Log4j2 打印异常日志时AsyncLoggerConfig 会初始化 Disruptor RingBuffer 日志元素字段,并进一步触发解析、加载异常堆栈类JVM 通过生成字节码的方式优化反射调用性能,但该动态生成的类无法被 WebAppClassLoader 类加载器加载,因此当大量包含反射调用的异常堆栈被输出到日志时会频繁地触发类加载,由于类加载过程是 synchronized 同步加锁的,且每次加载都需要读取文件,速度较慢,从而导致线程 Block。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值