zoukankan      html  css  js  c++  java
  • Logger性能优化

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

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

     

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

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

     

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

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

    1. 升级版本

        a)         Logback

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

    <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
  • 相关阅读:
    @Repository、@Service、@Controller 和 @Component
    SSH简单搭建
    超详细的Maven使用教程
    Maven入门指南① :Maven 快速入门及简单使用
    MySQL建立一个连接工具类
    js分页demo
    Java通过JDBC 进行Dao层的封装
    Linux 上svn使用http访问设置
    Linux (Ubuntu)安装svn
    阿里云域名文档
  • 原文地址:https://www.cnblogs.com/lzh-boy/p/9395430.html
Copyright © 2011-2022 走看看