日志爆炸防护机制:异常打印刷爆磁盘?动态限频+异步落盘救急
公司有一次线上故障——某个下游服务挂了,调用方在 catch 块里打了 log.error("调用失败", e)。这行代码每分钟被执行了 5 万次,5 万条堆栈日志,每条 3KB,一分钟就写了 150MB 的日志文件。运维发现的时候磁盘已经满了,其他服务也跟着挂。灾难的起点不是下游挂了,而是日志把磁盘写爆了。 这种日志爆炸场景的典型特征是突发性——平时打日志没问题,一旦某个循环里遇到了异常,日志量瞬间暴涨。今天聊聊怎么给日志加上限频和异步落盘,让它在异常场景下也不会失控。 问题出在哪:日志写入是同步阻塞的 Logback 默认的 FileAppender 是同步写盘的。log.error() 调用时,线程会等日志写完了才继续执行。平时没感觉,但一旦日志量暴增,磁盘 IO 就成了瓶颈——所有打日志的线程都堵在等磁盘写入。 而且同步模式下,每行日志都是一次 write() 系统调用。一分钟 5 万条就是 5 万次系统调用,再加上堆栈的格式化,CPU 也被打满。 方案一:异步落盘,业务线程不等 IO Logback 的 AsyncAppender 就是干这个的: <appende....