HTTP 协议栈学习笔记
学 HTTP 协议栈的时候,我一开始以为重点只是方法、状态码和请求头。后来真正排查过接口超时、跨域、缓存和证书问题之后,才发现 HTTP 不是孤立的一层:它下面有 DNS、TCP/QUIC、TLS,上面又连着网关、缓存、鉴权、限流和监控。
这篇笔记按我的学习过程来整理:先建立协议栈地图,再补网络基础和 HTTPS,最后把 HTTP/1.1、HTTP/2、HTTP/3 以及生产排障串起来。目标不是把每个 RFC 细节都背下来,而是形成一个能解释问题、定位问题、优化问题的理解框架。
定位:学习过程记录 / 面试复盘 / 工程排障笔记
适合人群:前后端开发、测试工程师、运维与 SRE 初学者
我先记住的 3 个结论
- HTTP 只负责应用层语义(请求/响应),真正传输依赖 TCP 或 QUIC,安全由 TLS 提供。
- 性能优化的核心是减少 RTT、提升缓存命中、降低字节体积、避免无效重试。
- 工程上要同时关注协议正确性与系统稳定性:超时、重试、限流、熔断、可观测性缺一不可。
目录
- 第一部分:协议栈全景(先建立地图)
- 第二部分:网络基础(IP/TCP/UDP/DNS)
- 第三部分:HTTPS 与 TLS(安全层)
- 第四部分:HTTP/1.1 核心语义(高频重点)
- 第五部分:缓存、压缩、鉴权、跨域(工程四件套)
- 第六部分:HTTP/2 与 HTTP/3(性能演进)
- 第七部分:生产实践(Nginx/CDN/网关/监控)
- 第八部分:常见故障排查流程(能落地)
- 第九部分:面试高频问答(速记版)
- 附录:学习路线(4 周版)
第一部分:协议栈全景(先建立地图)
把一次 HTTP 请求想象成“寄快递”:
- 应用层(HTTP):写明寄什么、寄给谁(方法、路径、头、Body)
- 安全层(TLS):给包裹加密封条,防窃听篡改
- 传输层(TCP/QUIC):确保数据可靠/高效送达
- 网络层(IP):决定路径和转发
- 链路层(以太网/Wi‑Fi):在局域网里一跳一跳传输
一句话总结:
HTTP 负责“说什么”,TCP/QUIC 负责“怎么送”,TLS 负责“安全地送”。
第二部分:网络基础(IP/TCP/UDP/DNS)
1. DNS:域名如何变成 IP
- 浏览器先查本地缓存
- 再走递归解析(本地 DNS -> 根 -> 顶级域 -> 权威 DNS)
- 返回 A/AAAA 记录并按 TTL 缓存
2. TCP:原理与实现(为什么“可靠”)
TCP 是面向连接、可靠、按序、字节流协议。它的核心目标是:即使网络存在丢包、乱序、重复,也要让应用看到一条稳定的数据流。
2.1 建连与断连
- 三次握手:同步双方初始序号与收发能力,建立可靠连接
- 四次挥手:TCP 全双工,两个方向分别关闭
2.2 可靠传输的 4 个支柱
- 序号(Seq)+ 确认号(ACK):保证按序确认与重组
- 重传机制:超时重传(RTO)+ 快速重传(重复 ACK 触发)
- 流量控制(rwnd):防止发送方压垮接收方缓冲区
- 拥塞控制(cwnd):慢启动、拥塞避免、快恢复,防止压垮网络
2.3 内核实现视角(简版)
- 连接状态机:
LISTEN、SYN_SENT、ESTABLISHED等 - 发送/接收缓冲区:管理未确认数据与应用读取数据
- 重传队列与定时器:负责丢包恢复
- 乱序重排逻辑:保证应用层读取顺序正确
一句话: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 是什么
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-MatchLast-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: br或gzip - 若未压缩:可不返回
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 场景建议启用:
HttpOnly、Secure、SameSite - Token 需要设置过期时间、刷新机制与吊销策略
- 不要把长期有效高权限 token 存在不安全位置
- 统一处理
401与403:前者未认证,后者无权限
4. CORS 跨域(浏览器安全边界)
4.1 为什么会跨域失败
浏览器默认同源策略限制跨域脚本读取响应;服务端“允许跨域”必须显式声明响应头。
4.2 简单请求与预检请求
- 简单请求:满足方法/头部限制,可直接发起
- 预检请求:不满足简单请求条件时,浏览器先发
OPTIONS
4.3 关键响应头
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Allow-CredentialsAccess-Control-Max-Age(预检缓存时间)
4.4 常见误区
- 误以为 CORS 是“服务端拦截规则”,实际上是“浏览器读取限制”
Allow-Origin: *与Allow-Credentials: true不能同时使用- 只配主请求,忘配
OPTIONS导致预检失败
5. 幂等性与重试(稳定性的根)
5.1 幂等定义
幂等指同一请求执行多次,结果与执行一次一致(副作用不额外增加)。
5.2 方法语义与重试建议
- 常见幂等:
GET、PUT、DELETE - 通常非幂等:
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. 标准排查路径
- 先确认问题范围(全局还是单接口)
- 拆分链路:DNS -> TCP/TLS -> 网关 -> 应用 -> DB/下游
- 用日志与指标定位瓶颈段
- 先止血(限流/降级/扩容),再修根因
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 语义和缓存,最后结合服务端指标判断是不是系统治理问题。
评论
欢迎友好交流,理性讨论