打印日志会不会影响性能?怎么办?

问题

刚开始做开发的时候就有一个疑问, 我们开发一般为了调试方便都会给自己的业务代码加上一些日志, 那么问题来了, 打印这么多日志不会影响性能吗? 这个肯定是必然的, 毕竟需要计算机分出一些性能来打印日志的, 但一般要求不苛刻的场景可以忽略这个问题

前面说了一般情况下日志影响的性能是可以忽略的, 既然有一般那肯定就有不一般的情况, 今天来了解一下如何减少日志对性能的影响

方案

解决日志慢的问题,主要有两种方案,一个是异步,一个是降级。

因为日志写入操作通常是一个相对耗时的IO操作,如果每次日志记录都同步写入磁盘,可能会导致主线程阻塞,影响应用程序的性能。通过使用异步日志,主线程可以继续执行其他任务,而日志写入操作则由后台线程负责处理,提高了应用程序的响应性和吞吐量。

目前常用的日志框架,如Log4j2、Logback等都是支持异步日志的。都提供了AsyncAppender来实现异步的日志写入。

异步

如log4j2中做如下配置即可实现异步日志:

XML 复制代码
<!-- 异步日志依赖 -->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
</dependency>

Log4j2提供了三种异步日志实现方法:全局异步AsyncLogger(推荐使用)、混合异步AsyncLogger(推荐使用)、AsyncAppender。

log4j2的全局异步AsyncLogger性能最好,其次是混合异步AsyncLogger,性能最差的是AsyncAppender(和同步日志相比没有什么性能提升。和logback性能一样)。

如果使用异步日志,全局异步AsyncLogger、混合异步AsyncLogger、AsyncAppender,不要同时使用。否则会使用性能较低的一种异步方式。

全局异步

所有appender的所有日志级别的日志都异步的记录,不需要改动log4j2.xml配置文件。只需要在classpath,比如resources目录下,新建log4j2.component.properties配置文件。内容如下:

bash 复制代码
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

混合异步AsyncLogger

可以同时使用同步日志和异步日志,这使得日志的配置方式更加灵活

log4j2.xml配置如下:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="30">
 
 
    <Appenders>
		<!--这个输出控制台的配置 -->
		<console name="Console" target="SYSTEM_OUT">
			<!--输出日志的格式 -->
			<PatternLayout pattern="${log_pattern}" />
		</console>
    </Appenders>
 
    <Loggers>
        <!-- 自定义异步logger对象, name必须是LoggerFactory.getLogger(Log4j2Test.class)对应 -->
        <!-- 如果设置includeLocation=true, 开启日志记录行号信息会急剧降低异步日志的性能,比同步日志还要慢 -->
        <!-- 这里设置includeLocation=false,则PatternLayout的%l将不会打印出来 -->
        <!-- additivity="false": 不再继承RootLogger对象. 这里建议强制设置成false -->
        <AsyncLogger name="Log4j2Test" level="WARN" includeLocation="false" additivity="false">
            <AppenderRef ref="Console"/>
        </AsyncLogger>
 
        <!-- RootLogger是同步的。除Log4j2Test外,其它名称的logger使用RootLogger进行输出 -->
        <Root level="INFO">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

AsyncAppender

log4j2.xml配置如下:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="5">
 
    <properties>
        <property name="LOG_HOME">/Users/userName/Logs/appName</property>
    </properties>
 
    <Appenders>
        <File name="File" fileName="${LOG_HOME}/myFile.log">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-5level] %l --- %msg%n" />
        </File>
 
        <!-- AsyncAppender引用appender -->
        <Async name="Async">
            <AppenderRef ref="File"/>
        </Async>
    </Appenders>
 
    <Loggers>
        <Root level="INFO">
            <!-- 直接引用AsyncAppender -->
            <AppenderRef ref="Async" />
        </Root>
    </Loggers>
</Configuration>

降级

日志降级一般用的也不多,但是在大促场景中,也是会用到的,一般是配合预案一起做,就是在极端情况下,通过开关来调节, 让日志直接不输出。或者只打印ERROR级别的日志。或者做的更加精细一点,就是采样打印日志,比如采样1%进行日志输出,但是其实用的比较少,很多时候,采样和直接不打差别也不大。

因为这种场景基本使用不到的,了解一下他得原理就可以了, 有感兴趣的可以深入研究一下

相关推荐
benbenAItalk8 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
sunshine22 girl8 小时前
Java学习二 基本语法2, 算术运算符
java·学习
2601_966949658 小时前
为什么量化策略需要大量历史股票数据?从回测可信度理解数据规模
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
niucloud-admin8 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
2601_962885728 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
滕州市燕猫虎计算机科技工作室个体工商户8 小时前
Java锁
java·开发语言
多加点辣也没关系9 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
菜鸟~noob2339 小时前
【电子战】 第09篇:阵列信号处理——波束形成、MVDR、MUSIC【含matlab代码】
开发语言·matlab·信号处理
ocean21039 小时前
2025-2026年Python面试高频知识点洞察
开发语言·python·面试·python八股文
零依赖极客9 小时前
Day 6·1 ARMv8.2 dotprod——vdotq_s32 一条指令做 4 个点积
c语言·开发语言·人工智能·矩阵·arm·vllm