Logger性能优化

  最近排查线上问题,无意中发现了Logger堵塞的情况,排查的同时也做下总结,做个笔记,以防备用。

  先上图,看下实际堵塞的情况

 

从图中可以清楚的看到标黄的都在 waiting to lock <0x000000054011c380> 这个锁,这个锁被标红线程持有,如果标红的线程处理业务逻辑不够快,哪其它线程就会一直处在 BLOCKED 中。

关于org.apache.logging.log4j.core.appender.OutputStreamManager的说明,可以查看官方文档 点击查看,关于Write重载的几个方法如下

 

都有排它锁,这样在一个线程持有的时候,如果因为业务逻辑复杂、或者网络延迟 等等 都有机会造成线上发生的堵塞情况。

         下面说下自己整理的主要优化方案

  1. 升级版本

    a)         Logback

    Logback与Log4j的对比可以看官方文档 点击查看,如果升级到Logback记得要开启异步功能,进一步提高性能,异步配置如下

1
2
3
4
5
<appender name ="async" class= "ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold >0</discardingThreshold>
    <queueSize>512</queueSize>
    <appender-ref ref ="file"/>
</appender>

  l  discardingThreshold     

默认情况下,当BlockingQueue还有20%容量,他将丢弃TRACE、DEBUG和INFO级别的event,只保留WARN和ERROR级别的event。为了保持所有的events,设置该值为0。

  l  queueSize

BlockingQueue的最大容量,默认情况下,大小为256。

  l  appender-ref

关联的appender

    b)         Log4f2

是log4j的升级版,详细资料可以查看官方文档,点击查看,我比较喜欢功能就是支持lambda,延迟加载就是利用这个功能实现的

  2. 延迟加载

延迟加载说直白点就是按需加载,只有在用到的时候触发。你是否在项目中经常这样写日志

logger.info("消息提示:"+e.getMessage()+",业务数据:"+e.getData()+",级别别:"+e.getLevel().getName());

或者这样

logger.info("消息提示:{},业务数据:{},级别别:{}", e.getMessage(), e.getData(), e.getLevel().getName());    

不管你用上面两个示例中的哪种写法,运行的时候,不管设置的级别是多少,都会执行e的方法,如果有序列化的情况会更糟糕。理想情况是根据设置的日志级别,只在真正调用的时候再执行,这时可以用如下写法,做到按需索取日志

 logger.info("消息提示:{},业务数据:{},级别别:{}", () -> e.getMessage(), () -> e.getData(), () -> e.getLevel().getName());
  3. 根据环境设置不同的级别
根据程序运行的环境设置不同的日志级别,一般分为开发、测试、预上线、生产 环境,日志级别应该逐步提高,避免日志的IO频繁读写提高性能,建议设置为debug、info、warn、warn
posted @   架构师聊技术  阅读(3330)  评论(2编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
历史上的今天:
2010-07-31 C#使用Jmail实现邮件的接收与发送详细示例
2010-07-31 Jmail:C# 利用Jmail属性,接收邮件
2010-07-31 C#中如何使用Jmail库
点击右上角即可分享
微信分享提示