核心是四层协同优化日志性能:启用真正异步模式(Log4j2需配置AsyncLoggerContextSelector)、分级降级+门控+采样限流日志量、禁用ConsoleAppender改用SSD上的RollingFileAppender、调整异步队列为丢弃策略并扩大RingBuffer至262144。

核心思路是切断日志写入对业务线程的同步依赖,同时控制日志产出节奏和落盘压力。不能只盯着“缓冲区大小”调参,而要从日志机制、级别、输出目标、异步策略四层协同优化。
关闭同步日志,启用真正异步模式
Logback 默认是同步写入;Log4j2 虽有异步能力,但若未显式配置 AsyncLoggerContextSelector 或使用 AsyncLogger,实际仍是同步行为。必须确保:
- Log4j2:在
log4j2.xml中声明系统属性Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector - 避免混用
Logger和AsyncLogger—— 全局统一用异步 logger,否则同步 logger 仍会阻塞 - 确认 Disruptor 环形缓冲区已初始化成功(启动日志中出现
Using Disruptor version)
限制日志量:分级 + 条件 + 削峰
大促期间不追求“全量可查”,而要保障“关键可观测”。重点做三件事:
-
动态降级日志级别:将非核心模块(如工具类、缓存操作、HTTP client debug)从
DEBUG临时切到WARN或ERROR;核心链路(支付、下单)保留INFO即可 -
加日志门控(Guarded Logging):不用字符串拼接,改用占位符 + 条件判断,例如:
if (logger.isDebugEnabled()) { logger.debug("order processed, id={}", orderId); } -
采样输出:对高频日志(如请求打点、参数校验)启用采样器,如 Log4j2 的
ThresholdFilter配合自定义RateLimitingFilter,每秒最多输出 10 条同类日志
更换低开销输出目标,避开控制台瓶颈
ConsoleAppender 是高并发下最危险的日志出口——System.out 内部锁竞争严重,性能比 FileAppender 差 20 倍以上,即使重定向到 /dev/null 也无效。
- 生产环境必须禁用
ConsoleAppender,全部切换为RollingFileAppender - 文件路径建议挂载到高性能本地 SSD,避免网络存储或 NFS
- 滚动策略设为
TimeBasedTriggeringPolicy+SizeBasedTriggeringPolicy组合,防止单文件过大影响追查效率
调优异步队列与缓冲区参数
异步不是万能的,队列满时策略决定是否反压业务线程:
- Log4j2 默认策略是
DefaultAsyncQueueFullPolicy(阻塞),应改为DiscardingAsyncQueueFullPolicy(丢弃)——丢日志远好于卡接口 - 增大 Disruptor 缓冲区大小:
log4j2.asyncLoggerRingBufferSize=262144(默认 256K,可按 2 的幂次提升) - 确认 JVM 堆外内存充足(Disruptor 使用堆外内存),避免因
OutOfDirectMemoryError导致异步退化为同步

















