一次请求的生命周期¶
学习目标¶
学完本章后,学习者应该能够:
- 说清楚浏览器访问一个接口时,请求经历了哪些步骤。
- 理解 DNS、TCP、TLS、HTTP、网关、后端服务、数据库之间的关系。
- 知道一个请求失败时,可以从哪些节点排查。
- 建立端到端链路思维。
从输入 URL 开始¶
当用户在浏览器中访问一个地址时,例如:
背后大致会发生:
- 浏览器解析 URL。
- 查询 DNS,找到域名对应的 IP。
- 和目标 IP 建立 TCP 连接。
- 如果是 HTTPS,进行 TLS 握手。
- 发送 HTTP 请求。
- 请求经过网关或负载均衡。
- 后端服务接收请求。
- 后端执行业务逻辑。
- 后端访问数据库、缓存或其他服务。
- 后端返回 HTTP 响应。
- 浏览器解析响应并展示结果。
简化链路如下:
sequenceDiagram
participant Browser as 浏览器
participant DNS as DNS
participant LB as 网关/负载均衡
participant API as Go 后端服务
participant Redis as Redis
participant DB as 数据库
Browser->>DNS: 查询 api.example.com
DNS-->>Browser: 返回 IP
Browser->>LB: 建立连接并发送 HTTP 请求
LB->>API: 转发请求
API->>Redis: 查询缓存
alt 缓存命中
Redis-->>API: 返回缓存数据
else 缓存未命中
API->>DB: 查询数据库
DB-->>API: 返回数据
API->>Redis: 写入缓存
end
API-->>LB: 返回响应
LB-->>Browser: 返回 HTTP 响应
DNS:找到服务在哪里¶
DNS 负责把域名解析成 IP 地址。
如果 DNS 出问题,常见现象是:
- 域名无法访问。
- 某些地区访问失败。
- 新旧 IP 切换后仍访问旧服务。
- Kubernetes 集群内服务名解析失败。
排查工具:
TCP:建立可靠连接¶
HTTP/1.1 和 HTTP/2 通常运行在 TCP 之上。TCP 负责可靠传输。
常见问题:
- 连接超时。
- 连接被拒绝。
- 连接数过多。
TIME_WAIT很多。CLOSE_WAIT很多。
排查工具:
后续计算机网络章节会深入 TCP 三次握手、四次挥手、拥塞控制和状态机。
TLS:建立安全通道¶
HTTPS 会在 HTTP 之前先进行 TLS 握手。
TLS 解决的问题:
- 加密传输。
- 身份认证。
- 防止中间人攻击。
常见问题:
- 证书过期。
- 证书域名不匹配。
- 客户端不信任证书。
- TLS 版本或加密套件不兼容。
HTTP:表达请求和响应¶
HTTP 是客户端和服务端沟通的应用层协议。
一个请求通常包含:
- Method:
GET、POST、PUT、DELETE。 - Path:请求路径。
- Query:查询参数。
- Header:请求元信息。
- Body:请求体。
一个响应通常包含:
- Status Code:状态码。
- Header:响应元信息。
- Body:响应内容。
例如:
网关与负载均衡¶
请求通常不会直接打到业务服务,而是先经过网关或负载均衡。
它们可能负责:
- TLS 终止。
- 路由转发。
- 负载均衡。
- 鉴权。
- 限流。
- 日志。
- 跨域处理。
- 灰度发布。
如果网关配置错误,后端代码完全正确也可能访问失败。
常见现象:
- 404:路由没匹配到。
- 502:网关无法连接后端。
- 503:后端服务不可用。
- 504:后端处理超时。
后端服务处理请求¶
Go 后端服务接收到请求后,通常会经历:
- 路由匹配。
- 中间件处理。
- 参数解析。
- 参数校验。
- 鉴权和权限判断。
- 调用业务逻辑。
- 访问数据库、缓存、消息队列或其他服务。
- 组装响应。
- 记录日志和指标。
典型 Go HTTP 处理函数:
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"status":"ok"}`))
}
这里的代码很简单,但真实业务中还会有超时控制、错误处理、日志、指标和链路追踪。
数据库与缓存¶
很多请求最终都会访问数据。
常见模式:
- 先查 Redis 缓存。
- 缓存命中,直接返回。
- 缓存未命中,查数据库。
- 把数据库结果写入缓存。
- 返回响应。
这个模式能提升读取性能,但也带来一致性问题:
- 数据库更新后缓存如何更新?
- 缓存删除失败怎么办?
- 热点 Key 被大量访问怎么办?
- 缓存雪崩时数据库能否扛住?
这些内容会在数据库与缓存阶段深入学习。
请求失败如何排查¶
端到端链路越长,失败点越多。排查时可以按路径逐段确认:
| 阶段 | 常见问题 | 排查方向 |
|---|---|---|
| DNS | 域名无法解析 | dig、nslookup |
| TCP | 连接失败 | 端口、服务监听、防火墙 |
| TLS | 证书错误 | 证书有效期、域名、CA |
| HTTP | 状态码异常 | 路由、参数、权限、网关 |
| 后端服务 | 处理失败 | 日志、错误码、panic |
| 数据库 | 查询慢或失败 | 慢 SQL、连接池、索引 |
| 缓存 | 命中率低或超时 | Redis 状态、热点 Key |
| 外部服务 | 调用超时 | 超时配置、重试、降级 |
常见误区¶
- 误区一:访问失败就是后端代码问题。
也可能是 DNS、网关、证书、网络、端口、配置、数据库或缓存问题。
- 误区二:HTTP 500 就一定是服务器崩了。
500 只表示服务端处理失败,具体原因要看日志和错误链路。
- 误区三:重试可以解决所有超时。
盲目重试会放大流量,可能把依赖服务彻底打垮。
实战任务¶
使用当前知识库服务做一次请求链路观察:
步骤一:启动服务。
步骤二:访问首页。
步骤三:记录。
- HTTP 状态码。
- 响应内容大小。
- 端口监听进程。
- 如果服务停止,再访问会出现什么错误?
步骤四:思考。
- 这个请求有没有 DNS?
- 有没有 TLS?
- 有没有网关?
- 它和生产环境的请求链路有什么区别?
面试题¶
1. 从浏览器输入 URL 到页面返回,中间发生了什么?¶
参考答案
浏览器会先解析 URL,然后通过 DNS 查询域名对应的 IP。接着和目标地址建立 TCP 连接,如果是 HTTPS,还会进行 TLS 握手。连接建立后,浏览器发送 HTTP 请求,请求可能经过网关或负载均衡,再转发到后端服务。
后端服务接收请求后,会进行路由匹配、参数解析、鉴权、业务处理,可能访问数据库、缓存或其他服务,最后组装 HTTP 响应返回给浏览器。浏览器再解析响应内容并展示页面。
2. DNS、TCP、TLS、HTTP 分别解决什么问题?¶
参考答案
DNS 解决“域名对应哪个 IP”的问题。TCP 解决“如何在两端之间建立可靠传输连接”的问题。TLS 解决“如何加密传输并验证对方身份”的问题。HTTP 解决“客户端和服务端如何表达请求和响应”的问题。
可以把它们放在一条链路上理解:DNS 找地址,TCP 建连接,TLS 建安全通道,HTTP 传业务语义。
3. 502、503、504 通常分别可能意味着什么?¶
参考答案
502 通常表示网关从上游服务拿到了无效响应,可能是后端进程崩溃、连接被拒绝、协议不匹配或网关无法正确转发。503 通常表示服务暂不可用,可能是后端实例不可用、过载、维护或没有健康实例。
504 通常表示网关等待上游服务超时,后端可能处理太慢、数据库慢、外部依赖卡住或网络异常。实际排查时要结合网关日志、后端日志和链路追踪判断。
4. 如果一个接口偶发超时,你会从哪些方向排查?¶
参考答案
可以从请求链路逐段排查:客户端和网关是否有超时日志,后端服务是否有慢请求日志,数据库是否出现慢 SQL,Redis 或外部服务是否有超时,连接池是否耗尽,CPU、内存、GC、锁竞争是否异常。
偶发超时尤其要关注高峰流量、依赖抖动、连接复用、DNS、GC 暂停、慢查询和重试放大。好的排查方式是通过 Trace ID 串起一次具体慢请求,而不是只看平均耗时。
5. 为什么后端服务要记录请求日志和 Trace ID?¶
参考答案
请求日志用于记录请求发生了什么,包括路径、状态码、耗时、用户、错误信息等。Trace ID 用于把同一次请求在网关、服务、数据库、缓存、消息队列等多个组件中的日志串起来。
没有 Trace ID 时,排查分布式问题很容易变成在大量日志中猜测。记录请求日志和 Trace ID 能显著提高线上问题定位效率,也是可观测性的基础。