HTTP 协议栈学习笔记

学 HTTP 协议栈的时候,我一开始以为重点只是方法、状态码和请求头。后来真正排查过接口超时、跨域、缓存和证书问题之后,才发现 HTTP 不是孤立的一层:它下面有 DNS、TCP/QUIC、TLS,上面又连着网关、缓存、鉴权、限流和监控。

这篇笔记按我的学习过程来整理:先建立协议栈地图,再补网络基础和 HTTPS,最后把 HTTP/1.1、HTTP/2、HTTP/3 以及生产排障串起来。目标不是把每个 RFC 细节都背下来,而是形成一个能解释问题、定位问题、优化问题的理解框架。

定位:学习过程记录 / 面试复盘 / 工程排障笔记
适合人群:前后端开发、测试工程师、运维与 SRE 初学者

我先记住的 3 个结论

  1. HTTP 只负责应用层语义(请求/响应),真正传输依赖 TCP 或 QUIC,安全由 TLS 提供。
  2. 性能优化的核心是减少 RTT、提升缓存命中、降低字节体积、避免无效重试。
  3. 工程上要同时关注协议正确性与系统稳定性:超时、重试、限流、熔断、可观测性缺一不可。

目录


第一部分:协议栈全景(先建立地图)

把一次 HTTP 请求想象成“寄快递”:

  1. 应用层(HTTP):写明寄什么、寄给谁(方法、路径、头、Body)
  2. 安全层(TLS):给包裹加密封条,防窃听篡改
  3. 传输层(TCP/QUIC):确保数据可靠/高效送达
  4. 网络层(IP):决定路径和转发
  5. 链路层(以太网/Wi‑Fi):在局域网里一跳一跳传输

一句话总结:

HTTP 负责“说什么”,TCP/QUIC 负责“怎么送”,TLS 负责“安全地送”。


第二部分:网络基础(IP/TCP/UDP/DNS)

1. DNS:域名如何变成 IP

  • 浏览器先查本地缓存
  • 再走递归解析(本地 DNS -> 根 -> 顶级域 -> 权威 DNS)
  • 返回 A/AAAA 记录并按 TTL 缓存

2. TCP:原理与实现(为什么“可靠”)

TCP 是面向连接、可靠、按序、字节流协议。它的核心目标是:即使网络存在丢包、乱序、重复,也要让应用看到一条稳定的数据流。

手搓TCP协议栈

2.1 建连与断连

  • 三次握手:同步双方初始序号与收发能力,建立可靠连接
  • 四次挥手:TCP 全双工,两个方向分别关闭

2.2 可靠传输的 4 个支柱

  • 序号(Seq)+ 确认号(ACK):保证按序确认与重组
  • 重传机制:超时重传(RTO)+ 快速重传(重复 ACK 触发)
  • 流量控制(rwnd):防止发送方压垮接收方缓冲区
  • 拥塞控制(cwnd):慢启动、拥塞避免、快恢复,防止压垮网络

2.3 内核实现视角(简版)

  • 连接状态机:LISTENSYN_SENTESTABLISHED
  • 发送/接收缓冲区:管理未确认数据与应用读取数据
  • 重传队列与定时器:负责丢包恢复
  • 乱序重排逻辑:保证应用层读取顺序正确

一句话:TCP 用“确认 + 重传 + 窗口 + 拥塞控制”换来可靠性。

3. UDP:原理与实现(为什么“快但不保底”)

UDP 是无连接、尽力而为、面向报文协议。它把协议复杂性降到最低,以换取低时延与低开销。

3.1 协议特性

  • 无连接:发送前无需握手,启动快
  • 保留报文边界:发送一个报文,接收也是一个报文
  • 无内建重传/排序/拥塞控制:丢了通常不补、乱序不自动重排
  • 校验和:用于检测传输出错(出错一般丢弃)

3.2 内核实现视角(简版)

  • 按端口分发报文到对应 socket
  • 无连接状态机、无重传队列,处理路径更轻量
  • 更适合实时业务把可靠性策略放到应用层

3.3 和 QUIC 的关系

  • QUIC 运行在 UDP 之上
  • 在应用层补齐可靠传输、拥塞控制和加密(TLS)能力
  • 这也是 HTTP/3 选择 UDP 作为承载的关键原因

一句话:UDP 追求“轻量和实时”,可靠性由上层按需补齐。

4. 关键性能概念

  • RTT:往返时延
  • 带宽:单位时间最大传输量
  • 丢包率:重传与延迟抖动的重要来源

第三部分:HTTPS 与 TLS(安全层)

1. HTTPS 是什么

HTTPS=HTTP+TLSHTTPS = HTTP + TLS

2. TLS 握手做了什么

  • 协商加密套件
  • 验证服务器证书
  • 完成密钥交换,建立会话密钥

3. 你需要理解的关键词

  • CA/证书链:证明“你连的是谁”
  • SNI:同 IP 多域名证书选择
  • HSTS:强制走 HTTPS,减少降级攻击风险
  • 会话复用:减少重复握手成本

第四部分:HTTP/1.1 核心语义(高频重点)

1. 请求与响应结构

  • 请求:请求行 + Header + Body
  • 响应:状态行 + Header + Body

2. 常用方法

  • GET:读取资源
  • POST:创建/提交
  • PUT:整体更新(通常幂等)
  • PATCH:部分更新
  • DELETE:删除(通常幂等)
  • OPTIONS:探测能力/跨域预检
  • HEAD:仅响应头

3. 状态码速记

  • 200 成功
  • 201 创建成功
  • 204 成功但无响应体
  • 301/302 重定向
  • 304 缓存可用
  • 400 请求错误
  • 401 未认证
  • 403 已认证但无权限
  • 404 资源不存在
  • 429 触发限流
  • 500/502/503/504 服务端与网关问题

4. 长连接

HTTP/1.1 默认支持连接复用(Keep-Alive),减少重复建连开销。


第五部分:缓存、压缩、鉴权、跨域(工程四件套)

这一部分是 HTTP 工程实践的核心:很多线上性能问题和安全问题,本质都落在这 4 个主题上。

1. 缓存机制(从“会配”到“配对”)

1.1 强缓存与协商缓存

  • 强缓存:在缓存有效期内,浏览器不访问服务器
    • 常用头:Cache-Control: max-age=...
  • 协商缓存:缓存过期后,带条件头回源询问
    • ETag / If-None-Match
    • Last-Modified / If-Modified-Since
    • 命中返回 304 Not Modified

可记忆为:

  • 强缓存解决“要不要发请求
  • 协商缓存解决“要不要传实体

1.2 常见 Cache-Control 指令

  • public / private:是否允许共享缓存(CDN、代理)缓存
  • no-cache:可缓存,但使用前必须向源站再验证
  • no-store:完全不缓存(敏感数据优先)
  • max-age:资源新鲜期(秒)
  • s-maxage:共享缓存的专用新鲜期(优先于 max-age

1.3 缓存配置建议

  • 静态带 hash 资源(如 app.8f3c.js):max-age 设长,强缓存优先
  • HTML 文档:建议短缓存或 no-cache,保证发布可控
  • API 响应:按业务一致性要求精细化配置,避免“旧数据误命中”

1.4 容易踩坑的点

  • 忘了设置 Vary 导致内容协商错配(如 gzip 与非 gzip 混淆)
  • ETag 在多机环境策略不一致,导致协商缓存命中率低
  • 把用户私有数据配置为 public,造成缓存污染

2. 压缩机制(省带宽,但要算 CPU 账)

2.1 协商过程

  • 客户端声明:Accept-Encoding: br, gzip
  • 服务端选择:Content-Encoding: brgzip
  • 若未压缩:可不返回 Content-Encoding

2.2 实战选择

  • Brotli(br):通常压缩率更高,适合静态资源
  • gzip:兼容性好、成本可控,动态响应常用

2.3 压缩策略建议

  • 小响应体(如 < 1KB)通常不压缩,避免“压缩收益 < CPU 成本”
  • 图片/视频等已压缩格式不重复压缩
  • 对高 QPS 接口设置压缩阈值,避免 CPU 被压缩拖垮

3. 鉴权机制(认证与授权分开看)

3.1 常见模式

  • Cookie + Session(有状态):会话保存在服务端
  • JWT/Bearer Token(无状态):令牌放在请求头
  • 常见头:Authorization: Bearer <token>

3.2 认证 vs 授权

  • 认证(Authentication):你是谁(登录、验签)
  • 授权(Authorization):你能做什么(角色、权限点)

3.3 安全细节(高频)

  • Cookie 场景建议启用:HttpOnlySecureSameSite
  • Token 需要设置过期时间、刷新机制与吊销策略
  • 不要把长期有效高权限 token 存在不安全位置
  • 统一处理 401403:前者未认证,后者无权限

4. CORS 跨域(浏览器安全边界)

4.1 为什么会跨域失败

浏览器默认同源策略限制跨域脚本读取响应;服务端“允许跨域”必须显式声明响应头。

4.2 简单请求与预检请求

  • 简单请求:满足方法/头部限制,可直接发起
  • 预检请求:不满足简单请求条件时,浏览器先发 OPTIONS

4.3 关键响应头

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Credentials
  • Access-Control-Max-Age(预检缓存时间)

4.4 常见误区

  • 误以为 CORS 是“服务端拦截规则”,实际上是“浏览器读取限制”
  • Allow-Origin: *Allow-Credentials: true 不能同时使用
  • 只配主请求,忘配 OPTIONS 导致预检失败

5. 幂等性与重试(稳定性的根)

5.1 幂等定义

幂等指同一请求执行多次,结果与执行一次一致(副作用不额外增加)。

5.2 方法语义与重试建议

  • 常见幂等:GETPUTDELETE
  • 通常非幂等:POST
  • 实战中可通过“幂等键(Idempotency-Key)”让 POST 具备可重试能力

5.3 重试策略建议

  • 只对“可重试错误”重试(如超时、部分 5xx)
  • 使用指数退避 + 抖动(jitter),避免重试风暴
  • 设置总超时和最大重试次数,防止级联故障

一句话收束:缓存控成本,压缩控带宽,鉴权控风险,幂等与重试控稳定性。


第六部分:HTTP/2 与 HTTP/3(性能演进)

1. HTTP/2 改进点

  • 二进制分帧
  • 多路复用(同一连接并发多个流)
  • 头部压缩(HPACK)

2. HTTP/3 改进点

  • 基于 QUIC(UDP)
  • 更快握手(可 0-RTT)
  • 解决传输层队头阻塞问题(相对 TCP)

3. 版本对比一句话

  • HTTP/1.1:简单普及广,但并发效率有限
  • HTTP/2:多路复用显著提升页面加载效率
  • HTTP/3:弱网与高丢包环境下表现更稳

第七部分:生产实践(Nginx/CDN/网关/监控)

1. 反向代理与负载均衡

  • Nginx/Envoy 作为入口
  • L4/L7 负载分发
  • 健康检查 + 故障摘除

2. CDN

  • 静态资源边缘缓存
  • 降低回源压力
  • 就近访问减少 RTT

3. API 网关能力

  • 鉴权
  • 限流
  • 熔断
  • 重试与降级

4. 可观测性

建议监控:

  • 状态码分布(2xx/4xx/5xx)
  • 延迟分位数(P50/P95/P99)
  • QPS、错误率、超时率
  • 上下游 Trace ID 关联

第八部分:常见故障排查流程(能落地)

1. 标准排查路径

  1. 先确认问题范围(全局还是单接口)
  2. 拆分链路:DNS -> TCP/TLS -> 网关 -> 应用 -> DB/下游
  3. 用日志与指标定位瓶颈段
  4. 先止血(限流/降级/扩容),再修根因

2. 典型故障画像

  • 慢请求:DNS 慢、握手慢、应用慢、下游慢
  • 401/403 激增:令牌失效、权限配置变更
  • 404 激增:路由发布不一致、路径拼写问题
  • 502/504 激增:网关到上游超时或连接失败
  • 缓存失效:缓存头冲突或中间层被绕过
  • 跨域失败:CORS 响应头缺失/预检未放通

第九部分:面试高频问答(速记版)

Q1:HTTP 和 HTTPS 区别?

  • HTTP 明文传输;HTTPS 通过 TLS 提供机密性、完整性、身份认证。

Q2:HTTP/2 为什么更快?

  • 多路复用减少连接争用,二进制分帧更高效,头部压缩减少传输体积。

Q3:HTTP/3 为什么基于 UDP?

  • 通过 QUIC 在 UDP 上实现可靠传输与安全,减少 TCP 队头阻塞影响。

Q4:强缓存与协商缓存区别?

  • 强缓存命中直接本地使用;协商缓存需向服务端确认,命中返回 304

Q5:什么是幂等,为什么重要?

  • 幂等请求重复执行结果一致,是安全重试与故障恢复的基础。

附录:学习路线(4 周版)

第 1 周:打地基

  • TCP/IP、DNS、RTT、丢包影响
  • 抓包看一次完整握手与请求响应

第 2 周:HTTP/1.1 与 HTTPS

  • 方法、状态码、头部、缓存
  • TLS 握手、证书链、常见证书错误

第 3 周:HTTP/2 与 HTTP/3

  • 多路复用原理
  • QUIC 与 TCP 差异
  • 对比不同网络条件下表现

第 4 周:工程实践

  • 配置反向代理与缓存策略
  • 设计限流与重试策略
  • 建立监控看板并复盘一次真实慢请求

最终一句话总结

HTTP 协议栈学习的本质,是把“协议语义、传输机制、安全机制、工程治理”连成一条可观测、可优化、可排障的完整链路。

这次整理之后,我最大的感受是:学 HTTP 不能只停留在“请求和响应”的格式上。真正遇到问题时,慢可能是 DNS、TCP 握手、TLS、缓存策略、服务端排队、重试放大,也可能是网关和 CDN 配置。只有把这些层串起来,排障时才不会只盯着某一个状态码。

后面我再看网络问题,会优先按这条链路拆:先确认请求有没有发出去,再看连接和安全层是否正常,再看 HTTP 语义和缓存,最后结合服务端指标判断是不是系统治理问题。