2. HTTP/1.1 协议基础:请求-响应模型、文本协议格式与队头阻塞
HTTP/1.1 自 1997 年标准化以来,一直是 Web 和微服务间最广泛使用的应用层协议之一。在服务网格场景中,Envoy、Linkerd 等数据面代理需要解析 HTTP/1.1 流量以执行路由、熔断和指标采集。理解其请求-响应模型、文本协议格式以及固有的队头阻塞(Head-of-Line Blocking, HOL)问题,是诊断 API 延迟的起点。
2.1 请求-响应模型:半双工同步模式
HTTP/1.1 采用客户端主动发起、服务端被动响应的半双工通信模型。每个 TCP 连接上,客户端发送一个请求后必须等待服务端返回完整的响应,才能发送下一个请求。这种“一发一收”的串行模式在协议层面保证了消息顺序,但也引入了显著的延迟约束。
关键特征:
- 同步阻塞:客户端在等待响应期间不能复用同一连接发送其他请求。
- 请求-响应一一对应:通过请求行中的方法、URI 和版本号,以及响应中的状态码和原因短语完成配对。
- 连接复用有限:虽然支持 Keep-Alive 持久连接,但同一时刻只能处理一个请求-响应交换。
2.2 文本协议格式:人类可读的报文结构
HTTP/1.1 报文以纯文本形式在 TCP 连接上传输,由起始行、头部字段和可选的消息体三部分组成。这种设计便于调试和中间件处理,但文本解析和冗余头部也带来了额外的延迟开销。
2.2.1 请求报文格式
GET /api/v1/users?page=1 HTTP/1.1
Host: api.example.com
User-Agent: grpc-go/1.45.0
Accept: application/json
Authorization: Bearer <>
2.2.2 响应报文格式
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 245
Date: Mon, 15 May 2024 10:30:00 GMT
Server: envoy
{"users":[{"id":1,"name":"Alice"}]}
2.2.3 报文结构对比
| 组成部分 | 请求报文 | 响应报文 | 延迟影响 |
|---|---|---|---|
| 起始行 | 方法 + URI + 版本 | 版本 + 状态码 + 原因短语 | 文本解析需逐字节扫描 CRLF,增加 CPU 开销 |
| 头部字段 | Host、User-Agent、Cookie 等 | Content-Type、Set-Cookie、Cache-Control 等 | 冗余头部(如 Cookie)增大报文体积,增加传输延迟 |
| 空行分隔 | CRLF 标记头部结束 | CRLF 标记头部结束 | 解析器需等待完整头部到达才能开始处理 |
| 消息体 | 可选(GET 无体) | 可选(承载负载数据) | Content-Length 或 chunked 编码影响分帧延迟 |
服务网格诊断提示:在 Envoy 访问日志中,HTTP/1.1 请求的
%REQ(:METHOD)%、%REQ(X-ENVOY-ORIGINAL-PATH?)% 和 %RESPONSE_CODE% 字段直接对应报文起始行。头部字段如 x-request-id 可用于全链路追踪,但过大的头部(>8KB)会显著增加代理的解析延迟。
2.3 队头阻塞(HOL)问题:延迟的根本来源
队头阻塞是 HTTP/1.1 在延迟方面最严重的协议级缺陷。它发生在两个层面:TCP 层面的 HOL 和 HTTP 层面的 HOL。在服务网格中,代理之间的连接通常复用多个请求,HOL 问题会被放大。
2.3.1 HTTP 层面 HOL 的成因
- 串行化处理:同一 TCP 连接上,请求必须按顺序发送,响应必须按顺序返回。如果第一个请求的响应体很大或服务端处理慢,后续所有请求都会被阻塞。
- 连接数限制:浏览器通常限制每个域名最多 6 个并发连接。微服务场景下,客户端与服务端之间的连接数有限,HOL 更容易发生。
- 代理缓冲:Envoy 等代理默认会缓冲完整响应头部,在未收到完整头部前不会转发给下游,加剧了 HOL 效应。
2.3.2 HOL 对延迟的量化影响
| 场景 | 无 HOL 理想延迟 | 有 HOL 实际延迟 | 延迟放大倍数 |
|---|---|---|---|
| 3 个请求,每个服务端处理 10ms | 10ms(并行) | 30ms(串行) | 3x |
| 10 个请求,每个响应体 1MB | 10ms + 传输时间 | 100ms + 累积传输时间 | >10x |
| 慢客户端(TCP 窗口小) | 取决于带宽 | 受窗口限制,HOL 更严重 | 不确定 |
2.3.3 服务网格中的 HOL 放大效应
在服务网格架构中,Sidecar 代理(如 Envoy)通常与业务容器共享同一网络命名空间。当代理使用 HTTP/1.1 转发请求时,HOL 问题会在以下场景被放大:
- 连接池复用:Envoy 默认对上游集群使用连接池,多个请求可能共享同一 HTTP/1.1 连接。一个慢响应会阻塞该连接上的所有后续请求。
- 重试风暴:当请求因 HOL 超时触发重试时,重试请求会进一步加剧连接阻塞,形成延迟雪崩。
- 熔断误判:HOL 导致的延迟尖峰可能被熔断器误判为上游故障,触发不必要的熔断。
实践警告:在服务网格中,如果业务流量以 HTTP/1.1 为主,建议将 Envoy 的
upstream_http_protocol_options 设置为 auto_config 并启用 HTTP/2 上游连接。这可以彻底消除 HTTP 层面的 HOL 问题。如果必须保留 HTTP/1.1,应增加 max_requests_per_connection 并监控 upstream_rq_pending_total 指标。
2.4 本章小结
- HTTP/1.1 的半双工请求-响应模型要求请求必须串行发送,响应必须按序返回。
- 文本协议格式虽然易于调试,但头部冗余和 CRLF 解析增加了代理的 CPU 开销和传输延迟。
- 队头阻塞是 HTTP/1.1 延迟的核心问题,在服务网格中会被连接池复用和重试机制放大。
- 理解这些基础特性,是后续分析 gRPC 多路复用和低延迟优势的前提。