2. HTTP请求生命周期与故障注入点

日志这东西,说白了就是系统的「黑匣子」。你想想看,线上一个请求突然超时了,你连它在哪个环节卡住都不知道,那还怎么修?我刚开始做运维那会儿,就吃过这个亏——日志全打在一个级别,线上一查,几万行全是废话,真正有用的信息早被淹没了。

所以这一章,咱们把日志的底子打牢。级别怎么分、格式怎么写、怎么在大量日志里找到真正有价值的信息。嗯,这些基本功,决定了你排障的速度。

日志级别:你的「报警分级」体系

日志级别不是随便定的。每个级别都有明确的语义,用错了,要么漏报,要么噪音爆炸。

级别 含义 典型场景 我个人的使用习惯
DEBUG 调试信息,开发阶段用 变量值、函数入参、循环次数 只在本地或测试环境开启,线上绝对关掉
INFO 正常业务流程的关键节点 请求开始/结束、用户登录、订单创建 每个请求至少一条 INFO,标记生命周期
WARN 非预期但可容忍的情况 重试、降级、限流触发、配置缺失使用默认值 需要关注,但不一定立即处理
ERROR 功能受损,需要人工介入 数据库连接失败、第三方接口超时、数据校验不通过 必须告警,但不要重复刷屏
FATAL 系统不可用,立即停机 内存溢出、配置加载失败、核心服务崩溃 极少用,一旦出现就是 P0 事故

我曾经踩过一个坑:把数据库连接超时打成了 WARN,结果连接池耗尽时还在默默重试,直到整个服务挂掉才触发 FATAL。后来我改了——所有影响用户请求的异常,至少打 ERROR。

日志格式标准:让机器和人都能读懂

日志格式不统一,你连 grep 都懒得写。我见过最离谱的日志,时间戳是「2024-3-5 14:2:3」,连补零都没有。解析的时候直接报错。

我个人推荐的标准格式:

[时间] [级别] [线程] [追踪ID] [类名:行号] - 消息内容

举个例子:

[2025-03-21 14:32:18.123] [ERROR] [http-nio-8080-exec-3] [trace_id=abc123] [OrderService:45] - 订单创建失败: 库存不足, sku=10086

这里面有几个关键点:

  • 时间戳:必须带毫秒,用 ISO 8601 格式。别用「2024/3/5」这种,排序都排不了。
  • 追踪 ID:这是日志关联的核心。一个 HTTP 请求从网关到微服务,所有日志带上同一个 trace_id,你才能串起来看。
  • 类名:行号:定位代码位置。没有这个,你看到 ERROR 还得去翻源码找谁打的。
  • 消息内容:结构化,关键参数用 key=value 形式。别写「订单创建失败,库存不足」,要写「订单创建失败: 库存不足, sku=10086」。

一个小技巧:日志里不要拼接用户输入。比如用户昵称带换行符,直接拼进去会把你的日志格式打乱。用占位符,比如 user={},让日志框架帮你转义。

日志采样与降噪:别让日志成为新的故障

日志打太多,磁盘写满、CPU 飙升,系统先把自己打挂了。我遇到过一台 4C8G 的机器,INFO 日志每秒输出 2 万行,结果业务没挂,日志先写爆了磁盘。

所以,采样和降噪是必须的。

采样策略

  • 按请求比例采样:比如高并发接口,只记录 10% 的请求日志。用 trace_id 的哈希值取模,保证同一个请求的日志完整。
  • 按错误级别采样:ERROR 和 FATAL 全量记录,WARN 按 50% 采样,INFO 按 10% 采样,DEBUG 直接关掉。
  • 按接口维度采样:核心接口(支付、下单)全量,非核心接口(查询、列表)按比例。

降噪手段

  • 合并重复日志:同一个错误在 1 秒内出现 100 次,只打一条,后面加个 count=100。
  • 忽略已知噪音:比如健康检查的请求、心跳包、某些第三方 SDK 的 DEBUG 日志。直接过滤掉。
  • 动态调整级别:线上默认 INFO,出问题时通过配置中心临时降到 DEBUG,排查完再改回来。

核心原则:日志是给人看的,不是给磁盘看的。每一行日志都要有明确的「为什么打」和「谁来看」。

知识体系:日志基础全景图

下面这张图,把日志级别、格式、采样降噪串起来了。你可以把它当作一个检查清单——每次设计日志方案时,对着过一遍。

日志基础知识体系 日志基础:级别 · 格式 · 降噪 日志级别 日志格式 采样与降噪 DEBUG INFO WARN ERROR FATAL 时间戳 追踪ID 类名:行号 结构化消息 按比例采样 按级别采样 合并重复 过滤噪音 动态调级 核心原则 每一行日志都要有明确的「为什么打」和「谁来看」

实战建议:从零搭建日志规范

如果你现在要在一个新项目里落地日志规范,我建议按这个顺序来:

  1. 定级别:和团队对齐每个级别的使用场景,写进开发规范。
  2. 定格式:统一模板,强制所有模块使用。用日志框架的 Pattern 配置,别让开发手写拼接。
  3. 定采样:评估接口 QPS,算一下日志量。如果单机每秒超过 5000 行,就要考虑采样了。
  4. 定降噪:上线后观察一周,把重复率高的日志找出来,该合并的合并,该过滤的过滤。
  5. 定监控:ERROR 和 FATAL 的日志量要配告警。突然暴涨,说明系统出问题了。

一个小工具推荐:用 logreduce 或者 log-similarity 这类工具,可以自动识别相似日志并合并。我有个项目,用这个工具把日志量从每天 200GB 降到了 30GB,而且关键信息一条没丢。

日志基础打好了,后面讲链路追踪、日志分析、故障定位,你才能用得上。不然日志都是乱的,再好的工具也救不了你。