1. 课程导入与HTTP故障诊断全景

做运维这些年,我处理过成百上千的HTTP故障。说实话,每次接到告警,我脑子里都会快速过一遍那个请求从发起到返回的全过程。你想想看,一个请求从用户浏览器出发,经过DNS、负载均衡、网关、应用服务、缓存、数据库……中间任何一个环节出问题,用户感知到的就是“打不开”或“好慢”。

所以这一章,我们先搭个全景框架。后面29章的所有技巧,都建立在这个框架之上。

1.1 HTTP请求的生命周期

一个典型的HTTP请求,从客户端到服务端再返回响应,大致经历这么几个阶段。我习惯把它分成“前端链路”和“后端链路”来看。

核心链路速览:

  1. DNS解析 — 域名变IP,这一步挂了就是“无法解析主机”。
  2. TCP连接 — 三次握手,建立可靠通道。
  3. TLS握手 — HTTPS场景下协商加密套件、交换证书。
  4. 发送请求 — 客户端发出HTTP报文(方法、路径、头、体)。
  5. 负载均衡 — 转发到后端某台真实服务器。
  6. 应用处理 — 业务逻辑、数据库查询、调用外部服务。
  7. 返回响应 — 状态码、响应头、响应体回传客户端。
  8. 连接关闭/复用 — keep-alive或四次挥手。

每个阶段都有对应的日志可以追踪。我个人习惯把日志按“入口、中间、出口”三个位置来组织,这样排查时思路特别清晰。

HTTP 请求生命周期 DNS 解析 TCP 握手 TLS 握手 发送请求 负载均衡 应用处理 返回响应 每个阶段都可能产生故障,每个阶段都有对应的日志可以追踪 入口日志(Nginx/网关)→ 中间日志(应用/中间件)→ 出口日志(数据库/外部服务) 日志分层追踪模型 入口层(Nginx / 网关) 业务层(应用 / 中间件) 数据层(DB / 缓存)

1.2 日志的价值

日志是什么?说白了,就是系统在关键时刻留下的“黑匣子”。没有日志,你排查故障就像蒙着眼睛找东西。

我记得有一次线上告警,用户反馈下单接口超时。我第一反应是看Nginx的access.log,发现upstream_status全是504。再翻应用日志,看到一条SQL执行了30秒。最后定位到是数据库连接池被慢查询打满了。整个过程不到10分钟,全靠日志串联。

日志的三大核心价值:

  • 还原现场 — 请求从哪里来、经过了哪些服务、花了多长时间。
  • 定位根因 — 错误栈、异常信息、参数快照,直接告诉你哪里崩了。
  • 量化分析 — 平均响应时间、错误率、P99延迟,帮你判断系统健康度。

但这里有个坑——日志不是越多越好。我曾经见过一个团队,每个接口都打印完整的请求体和响应体,一天产生几百GB日志。结果排查问题时,光翻文件就花了半小时。嗯,这里要注意:日志要有结构、有分级、有关联ID。

日志类型 典型来源 排查价值
访问日志 Nginx、网关、负载均衡 请求来源、状态码、响应时间、上游地址
应用日志 业务代码、框架(Spring Boot、Gin等) 业务逻辑、异常栈、调用链、参数快照
慢日志 MySQL、Redis、MongoDB 慢查询、慢操作、索引缺失
错误日志 系统组件、中间件 OOM、连接超时、配置错误
审计日志 安全组件、操作记录 谁在什么时间做了什么操作

1.3 常见的故障类型

故障千奇百怪,但归纳起来就那么几类。我按“现象”来分,这样排查时更容易对号入座。

1.3.1 连接类故障

客户端连不上服务端,或者连接被重置。典型表现:Connection refused、Connection timeout、Connection reset by peer。

  • 原因:端口没开、防火墙拦截、后端服务挂了、连接池耗尽。
  • 日志看哪里:Nginx的upstream状态、应用层的网络异常栈。

1.3.2 超时类故障

请求发出去,等了很久才返回,或者直接超时。典型表现:504 Gateway Timeout、upstream timed out。

  • 原因:后端处理慢、数据库慢查询、外部API响应慢、线程池阻塞。
  • 日志看哪里:应用日志的执行耗时、慢日志、调用链追踪。

避坑指南:我曾经遇到一个案例,Nginx的proxy_read_timeout设了60秒,但应用层的接口超时设了30秒。结果Nginx还在等,应用已经断了,返回给客户端的是502。排查时两边日志对不上,浪费了半天。所以超时配置一定要上下游对齐。

1.3.3 状态码异常类故障

请求正常返回了,但状态码不对。比如该200的返回了500,或者该302的返回了404。

  • 原因:代码bug、路由配置错误、权限校验失败、资源不存在。
  • 日志看哪里:应用日志的异常信息、业务日志的参数快照。

1.3.4 数据类故障

接口返回了,状态码也是200,但数据不对。比如字段为空、数值错误、乱码。

  • 原因:缓存与数据库不一致、序列化/反序列化问题、字符集不匹配。
  • 日志看哪里:业务日志的入参和出参、数据库查询结果。

1.3.5 性能类故障

接口能正常返回,但响应时间远超预期。比如平时10ms的接口突然变成2秒。

  • 原因:慢查询、锁竞争、GC停顿、网络带宽瓶颈、CPU飙高。
  • 日志看哪里:慢日志、GC日志、系统监控指标、调用链耗时。
故障类型 典型现象 排查切入点
连接类 Connection refused / timeout 端口、防火墙、服务状态、连接池
超时类 504 / upstream timed out 应用耗时、慢查询、线程池
状态码异常 500 / 404 / 403 代码异常、路由、权限
数据类 数据为空 / 乱码 / 不一致 缓存、序列化、字符集
性能类 响应慢 / 延迟高 慢日志、GC、监控指标

1.4 小结

这一章我们搭好了全景框架。你记住三件事就行:

  • HTTP请求有8个关键阶段,每个阶段都可能出问题。
  • 日志是排查故障的“第一手证据”,要有结构、有关联ID。
  • 故障分5大类,先看现象再找日志,别瞎猜。

后面每一章,我都会带着你深入一个具体的故障场景,手把手教你怎么看日志、怎么定位、怎么修复。准备好了吗?