开发软件时,加个日志输出好像再平常不过了。出问题能查,上线后安心,谁还能离得开 log?但你有没有发现,某个接口突然变慢,查来查去最后发现是日志写得太猛?
日志不是免费的
很多人觉得打印一行 info 或 debug 日志,不就是一条字符串输出吗?其实背后涉及 I/O 操作、线程调度、磁盘写入甚至网络传输。特别是高并发场景下,每秒几千次请求都打日志,CPU 和磁盘 IO 可能先扛不住。
举个例子:某电商系统在大促时接口响应从 50ms 涨到 400ms,排查发现是因为每个请求都记录详细参数到文件,还用了同步写入。结果日志成了性能瓶颈,业务反而被拖垮。
不同日志级别代价不一样
debug 级别的日志在生产环境开着,等于给自己埋雷。这类信息本该只在调试阶段使用,一旦开启,大量冗余内容不仅占磁盘,还会挤占正常业务的资源。
建议的做法是在配置里控制日志级别:
logging:
level:
com.example.service: INFO
org.springframework.web: WARN
这样既能保留关键信息,又避免过度输出。
异步日志是个好选择
主流日志框架比如 Logback 和 Log4j2 都支持异步日志。Log4j2 的 AsyncAppender 能把写日志操作扔进单独线程,主线程不用等,响应自然更快。
启用方式也很简单,在 log4j2.xml 中配置:
<AsyncLogger name="com.example" level="info" includeLocation="true"/>
实测在高吞吐服务中,开启异步后整体延迟下降约 30%,尤其对 RT 敏感的系统帮助明显。
别忘了日志格式和位置
有些人喜欢在日志里打印完整对象 JSON,看着清晰,但序列化过程本身就很耗 CPU。更别说把日志直接写到 NFS 或远程服务器,网络抖动一下,整个应用卡住。
本地服务尽量写本地磁盘,格式精简,关键字段前置。像 trace ID、用户 ID 这类用于追踪的信息保留即可,其他能省则省。
推荐几个轻量又高效的日志工具
SLF4J + Logback:Java 项目经典组合,配置灵活,性能稳定,适合大多数中小型应用。
Log4j2:吞吐量更高,尤其是异步模式表现突出,适合高并发后台服务。
Serilog(.NET/C#):结构化日志做得好,配合 Elasticsearch 查起来特别方便,适合微服务架构。
Zap(Go 语言):Uber 开源的日志库,号称比标准库快 10 倍以上,零内存分配设计,对性能敏感的服务很友好。
选日志工具不只是看功能,更要看它对系统性能的实际影响。有时候少打一条日志,比加一台服务器还管用。