从 “裸奔传纸条” 到 “UDP 开火箭”:HTTP 协议进化史全解,看完面试再也不慌了

0 阅读18分钟

家人们,做前端、后端开发的,谁不是天天和 HTTP 打交道?

写接口要掰扯 GET 和 POST 的区别,调接口要处理 Header 头,优化页面要搞缓存策略,就连面试,HTTP 各个版本的特性、队头阻塞、多路复用都是必问的送命题。但很多同学天天用 HTTP,却只停留在 “发请求拿数据” 的层面,一问起 HTTP 0.9 到 3.0 到底改了啥?为啥要这么改?队头阻塞到底是个啥?各个版本是怎么填坑的?瞬间就懵了。

别慌!今天咱们就用唠嗑的方式,从最原始的 “石器时代版本” 一路讲到最新的 “火箭版本”,把 HTTP 协议的进化打怪史扒得明明白白。全程大白话 + 接地气比喻,没有晦涩的天书,看完不仅能轻松应付面试,还能彻底搞懂咱们天天用的 HTTP,到底是个啥东西。

先给个核心定义定调:HTTP(HyperText Transfer Protocol)超文本传输协议,是基于 TCP/IP 的应用层协议,是互联网数据通信和网页传输的基石。它天生是请求 - 响应模式、无状态,特别适配海量用户的网页访问和高并发互联网场景

而它的整个进化史,本质就是一部「填坑史」:上一个版本留下的痛点,下一个版本疯狂补全,补完又发现新坑,再继续迭代,一路从 “只能传文本” 进化到了 “能扛住 4K 直播、实时游戏” 的地步。


HTTP 0.9:原始人版本,只会传小纸条的极简工具

1991 年,HTTP 的初代版本诞生。那时候互联网还只是科研机构的 “内部玩具”,大家的需求特别简单:就是在不同的电脑之间,互相传个文本文件看看。

所以蒂姆・伯纳斯・李老爷子,直接搞了个极简到极致的协议,核心特性就一条:只支持 GET 请求

你给服务器发一句 GET /index.html,服务器就给你返回一段 HTML 纯文本,连请求头、响应头都没有,连状态码、错误码都不存在,传完内容直接断开 TCP 连接,多一句话都不说。

这就好比你给同桌传小纸条,只写了 “把你的笔记给我”,对方直接把笔记扔给你,没有多余的包装、没有备注,完事直接拉黑。

优点是极致简单,零学习成本;缺点也肉眼可见:只能传纯文本,图片、音频、视频想都别想,没有任何交互能力,更别说现在的登录、下单这些操作了。说白了,它就是个科研用的 “文本传输小工具”,完全没想过能撑起后来的整个互联网。


HTTP 1.0:从 “传纸条” 到 “寄快递”,终于有包装了

互联网的发展速度,远超所有人的想象。很快大家就不满足于只传文本了:我要传图片、传音频,要做登录交互,要给不同的设备返回不同的内容,HTTP 0.9 完全不够用了。

于是 1996 年,HTTP 1.0 正式发布,直接把 HTTP 从 “小纸条” 升级成了 “标准化快递”,核心升级全是硬货:

1. 新增「Header 请求头 / 响应头」,终于有 “快递面单” 了

这绝对是 HTTP 1.0 最伟大的升级,没有之一。

以前的传输只有 “内容本身”,现在有了 Header,就好比寄快递有了标准化面单:上面写清楚了包裹里是什么、寄件人是谁、收件人能收什么、要怎么处理这个包裹。

我们天天打交道的核心 Header,全是这时候定下来的:

  • Content-Type:告诉对方,我发的请求体是什么格式(JSON / 表单 / 图片 / 文件)
  • Accept:告诉对方,我能接收什么样的响应格式,别给我发我看不懂的
  • Authorization:带个令牌,证明我是谁,用来做权限校验
  • Cookie:直接解决了 HTTP「无状态」的天生缺陷 ——HTTP 本身不会记住你上一次请求了什么,每次请求都是独立的,有了 Cookie,网站就能记住 “你已经登录了”,不用每次访问都重新输密码。

这里必须唠唠大家天天见,却很少有人搞懂的User-Agent(UA)头。我们现在看到的所有浏览器 UA,几乎都是Mozilla/5.0开头,比如:

plaintext

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36

为啥?这其实是个历史遗留的 “行业潜规则”。早期网景浏览器叫 Mozilla,率先支持了框架、图片等高级特性,服务器会判断 UA:如果是 Mozilla,就返回带高级特性的页面;其他浏览器,就返回纯文本降级页面。于是后来的 IE、Chrome、Safari,全都在自己的 UA 前面加上了Mozilla/5.0,就为了告诉服务器 “我也能支持高级特性,别给我降级”,这个传统就一直延续到了现在。

而 UA 里的每一段,都藏着关键信息:

  • (Macintosh; Intel Mac OS X 10_15_7):你的硬件设备和操作系统
  • AppleWebKit/537.36:浏览器的渲染引擎
  • Chrome/146.0.0.0:浏览器的具体型号和版本
  • Safari/537.36:兼容 Safari 浏览器的标识

2. 支持更多请求方法,终于能做交互了

除了 GET,新增了POSTHEAD方法:

  • POST:可以给服务器提交数据,登录、注册、下单这些交互操作,终于能实现了
  • HEAD:只返回响应头,不返回响应正文。就好比你寄快递前先问一句 “你在不在家?”,不用等对方把整个包裹给你,就能知道资源是否存在、服务器是否正常,特别省流量。

3. 致命短板:短连接,每次请求都要 “重新打电话”

HTTP 1.0 虽然牛,但有个致命的缺陷:默认使用短连接

什么意思?每发起一次 HTTP 请求,都要先经过 TCP 三次握手建立连接,请求完成之后,再经过四次挥手断开连接。下一次请求,还要再重复一遍这个流程。

这就好比你买 10 件东西,每一件都要单独给快递员打个电话、约上门、取件、送完直接拉黑,下次再买再重新打电话。那时候一个网页里,少说有几个 CSS、JS、图片文件,多的有几十上百个,每个文件都要单独建一次 TCP 连接,握手挥手的开销,比传文件本身还大,网页加载慢得要死,网速稍微差点,直接卡成 PPT。


HTTP 1.1:互联网基建狂魔,一用就是二十多年

1997 年,HTTP 1.1 发布,直接把 HTTP 1.0 的坑填了大半,还加了一堆王炸特性,硬生生撑起了互联网二十多年的爆发式增长,直到现在,它还是市面上的主流版本。

核心升级 1:长连接(Keep-Alive),终于不用反复打电话了

HTTP 1.1 直接把长连接设为默认开启,彻底解决了短连接的痛点。

TCP 连接建立之后,不会马上断开,同一个域名下的多个请求,都可以复用这一个 TCP 连接,不用每次都三次握手、四次挥手。只有当连接空闲一段时间,或者页面关闭的时候,才会断开连接。

这就好比你买 10 件东西,不用每个都单独叫快递,直接把所有东西打包,用同一个快递员一次性送完,直接把 TCP 连接的开销砍到了最低,网页加载速度直接起飞。

核心升级 2:管道化(Pipelining),理想很丰满,现实很骨感

基于长连接,HTTP 1.1 又搞了个管道化特性:不用等上一个请求的响应回来,就可以连续发送多个请求。

以前的长连接,就算不用重新建连,还是要 “发一个请求→等响应回来→再发下一个”,网速还是有浪费。管道化就好比,你一口气把 10 个快递都交给同一个快递员,不用等第一个快递签收了,再发第二个,听起来简直完美。

但它有个致命的缺陷,直接把这个特性给干废了:响应必须严格按照请求的顺序返回

这就是臭名昭著的「应用层队头阻塞(Head-of-Line Blocking)」。

我给大家打个最形象的比方:这就好比一条单行道,你前面排了 10 辆车,就算你开的是超跑,只要前面第一辆车抛锚了,你后面所有的车,全都得堵在原地,一步都动不了。

对应到 HTTP 里就是:你连续发了 10 个请求,第一个请求服务器处理了 10 秒,后面 9 个请求哪怕 1 毫秒就能处理完,也必须等第一个请求的响应返回之后,才能依次返回后面的。只要有一个请求卡住,后面所有的请求都得跟着排队堵死。

这个问题太致命了,所以市面上几乎所有的浏览器,都默认禁用了管道化特性,这个看似美好的升级,基本等于没落地。

核心升级 3:分块传输(Chunked),边生成边发,不用等全量内容

HTTP 1.0 里,服务器必须把整个内容全部生成完,算出Content-Length,才能发给浏览器。如果是超大文件、或者实时生成的内容,用户就得等半天,体验极差。

于是 HTTP 1.1 新增了分块传输,通过Transfer-Encoding: chunked标识,服务器可以把内容切成一块一块的,生成一块就发一块,浏览器收到一块就解析一块,不用等整个文件全部生成完成。

这就好比你看直播,不用等整个视频全部录完再看,而是边播边看,延迟直接拉满。我们现在用的 SSE 流式传输、大文件下载、AI 对话的流式回复,全都是靠这个特性实现的。

核心升级 4:Host 头,直接把建站成本打下来了

在 HTTP 1.0 里,一个 IP 地址只能对应一个网站,因为服务器根本不知道你要访问这个 IP 下的哪个网站。

而 Host 头的出现,直接打破了这个限制:一个 IP 地址,可以托管成百上千个网站,服务器会根据请求里的 Host 字段,判断你要访问的站点,把请求转发给对应的服务。

这就好比同一个写字楼地址(IP),里面有无数个公司(网站),你寄快递的时候写上公司名称(Host),前台就知道该把快递给谁。以前租个服务器建站一年要几千块,现在共享 IP 的虚拟主机,一年几十块就能搞定,直接推动了中小网站的爆发式增长。

除此之外,HTTP 1.1 还新增了OPTIONSPUTPATCHDELETE等请求方法,直接让 RESTful API 成为了可能,前后端分离的架构才有了落地的基础,web 开发终于从 “写静态页面”,进化到了 “做 web 应用” 的阶段。

绕不开的两大遗留坑

就算 HTTP 1.1 再能打,还是有两个解决不了的核心问题:

  1. 应用层队头阻塞没彻底解决:管道化废了,同一个 TCP 连接里,请求还是得排队,还是会堵
  2. 明文传输,数据全裸奔:所有内容都是明文传输,黑客随便抓个包,就能看到你传的账号密码、个人信息,安全隐患极大,这也是 HTTPS 诞生的核心原因(HTTP+SSL/TLS,给 HTTP 加了一层加密隧道,解决了窃听、篡改、冒充的问题)

HTTP 2.0:终于开上多车道高速,队头阻塞拜拜了

2015 年,HTTP 2.0 正式发布,而且主流实现都是基于 HTTPS 的,直接把 HTTP 1.1 的核心痛点给干碎了。

最核心的革命:二进制分帧层

HTTP 1.x 都是明文文本传输,就好比你写的一封信,必须一行一行按顺序读,不然就看不懂,根本没办法拆分、插队。

而 HTTP 2.0,直接把所有传输的内容,全部切成了一个个的二进制帧,并且给每个帧都加上了流 ID,标记这个帧属于哪个请求 / 响应。

我再给大家打个比方:HTTP 1.1 是单行道,所有车必须按顺序走,前面堵了后面全堵;而 HTTP 2.0 的二进制分帧,直接把单行道改成了多车道高速,每个请求就是一辆车,把车拆成了一个个的零件(帧),每个零件上都标了属于哪辆车(流 ID),所有零件可以在各个车道上随便跑,到了终点再按流 ID 把零件拼起来,还原成完整的车。

基于分帧的王炸:多路复用

有了二进制分帧,多路复用就顺理成章了:同一个 TCP 连接里,可以同时并发无数个请求,不用排队,不用按顺序返回

你同时发 100 个请求,每个请求的帧可以混在一起传输,哪个请求的响应先处理完,就先把哪个的帧发回去,完全不会互相阻塞。就算其中一个请求出问题了,也只会影响这一个请求,其他请求照样正常传输,彻底解决了应用层的队头阻塞问题

这就好比多车道高速,就算其中一个车道出了事故,其他车道照样能正常跑,不会整个路都堵死。以前浏览器为了减少阻塞,给同一个域名限制了 6-8 个 TCP 并发连接,现在有了多路复用,一个连接就搞定了,TCP 连接的开销直接降到了极致。

其他实用升级

  1. 服务器推送(Server Push) :以前浏览器请求 HTML,拿到之后解析里面的 CSS、JS 链接,再挨个发请求下载,一来一回浪费了很多时间。服务器推送可以做到:浏览器只请求 HTML,服务器主动把 HTML 里依赖的 CSS、JS、图片资源,提前推送给浏览器,不用等浏览器再发请求,进一步加快了页面加载速度(不过这个特性现在用得不多,因为很容易推送浏览器已经缓存的资源,反而浪费流量,很多站点都默认禁用了)。
  2. 头部压缩(HPACK) :HTTP 1.x 的 Header 头,很多时候都是重复的,比如 Cookie、User-Agent,每次请求都要带,浪费流量。HTTP 2.0 用 HPACK 算法对 Header 头进行压缩,重复的字段只需要传一次,大大减少了传输开销。
  3. 流优先级:可以给不同的请求设置优先级,比如 HTML、CSS 是核心资源,优先级设高一点,图片、视频优先级低一点,服务器会优先处理高优先级的请求,让页面更快渲染出来。

还是没绕开的坑:TCP 层的队头阻塞

HTTP 2.0 虽然解决了应用层的队头阻塞,但它还是基于 TCP 协议的,而 TCP 协议本身,天生就有队头阻塞的问题。

TCP 为了保证可靠传输,要求所有数据包必须按顺序到达,如果有一个包丢了,整个 TCP 连接都要停下来,等这个包重传成功之后,才能继续处理后面的包。就算 HTTP 2.0 的多路复用让应用层不阻塞了,TCP 层一丢包,整个连接还是会全部卡住,所有请求都得等着。

这就好比高速路里面的车道再多,收费站只开了一个窗口,前面的车没交完费,后面所有的车都得等着,还是会堵。


HTTP 3.0:直接开上火箭,TCP 都给扬了

2022 年,HTTP 3.0 正式成为 IETF 国际标准,这一次,HTTP 直接干了件狠事:彻底抛弃了用了几十年的 TCP 协议,改用 UDP+QUIC 协议

大家都知道,UDP 是无连接的协议,不用三次握手,不用四次挥手,发了就完事,速度快到极致,但缺点也很明显:不可靠,不保证数据包顺序,不保证不丢包。

那 QUIC 是啥?QUIC 全称 Quick UDP Internet Connections,是在 UDP 的基础上,自己实现了 TCP 的可靠传输、拥塞控制、流量控制,同时内置了 TLS 1.3 加密、连接迁移等能力,相当于在 UDP 上搞了个 “增强版 TCP+TLS”,但又完美避开了 TCP 的所有坑。

1. 彻底解决了所有队头阻塞

QUIC 协议里,每个流都是完全独立的,一个流丢包了,只会重传这个流的数据包,其他流的传输完全不受影响。

比如你同时发了 10 个请求,其中一个请求丢包了,其他 9 个请求照样正常接收、正常解析,不会被卡住。这就好比直接把高速路的收费站给拆了,每个车道都是完全独立的,哪个车道出问题,只影响那个车道,其他车道完全不受影响,把队头阻塞给连根拔了。

2. 0-RTT 建连,速度直接拉满

TCP+TLS 1.3 建连,最少也要 1 次往返(1-RTT)才能发送业务数据,而 QUIC 协议,第一次连接只需要 1-RTT,第二次连接的时候,直接可以0-RTT发送业务数据。

什么概念?就是你刚给服务器打个招呼,连握手都还没完成,就直接把请求数据发过去了,延迟直接降到了最低。尤其是对移动端用户,网络经常在 WiFi 和 5G 之间切换,这个特性简直是福音,切换网络之后,连接可以秒恢复,不用重新握手。

3. 内置 TLS 1.3,安全和速度我全都要

HTTP 3.0 直接把 TLS 1.3 加密内置到了传输层,不像以前 HTTP 和 TLS 是分层的,现在直接整合在了一起,既保证了全程加密,解决了明文传输的安全问题,又不会因为加密带来额外的往返延迟,安全和速度直接拉满。

4. 连接迁移,切网再也不卡顿

我们用手机的时候,经常会遇到从 WiFi 切到 5G 的场景,这时候你的 IP 地址会变,TCP 连接就会直接断开,必须重新建连,刷视频、打游戏就会直接卡顿。

而 QUIC 协议,用一个唯一的连接 ID来标识连接,就算你的 IP 地址变了,只要连接 ID 没变,连接就不会断,不用重新握手,无缝切换。以后切网刷视频、打游戏,再也不会突然卡顿了。

现在很多大厂的产品,比如抖音、淘宝、Google、B 站,都已经全面支持 HTTP 3.0,我们刷短视频的流畅体验,很多都来自于 HTTP 3.0 的加持。


一张表总结:HTTP 各版本核心差异

表格

版本核心特性解决的核心痛点遗留的核心问题
HTTP 0.9仅支持 GET 请求,无 Header,纯文本传输实现了最基础的超文本传输功能极度受限,仅支持纯文本
HTTP 1.0新增 Header、多种请求方法、Cookie,支持多媒体传输满足了基础的网页交互和多媒体需求短连接开销极大,明文传输
HTTP 1.1长连接默认开启、分块传输、Host 头、RESTful 方法大幅降低 TCP 开销,支持虚拟主机,适配 web 应用开发应用层队头阻塞未解决,明文传输
HTTP 2.0二进制分帧、多路复用、头部压缩、服务器推送彻底解决应用层队头阻塞,大幅提升并发性能仍基于 TCP,存在 TCP 层队头阻塞
HTTP 3.0基于 UDP+QUIC 协议,0-RTT 建连,连接迁移,内置 TLS彻底解决全链路队头阻塞,极致降低延迟,安全性拉满部分老旧设备、网络环境对 UDP 的支持有限

最后唠两句

HTTP 协议的进化史,其实就是整个互联网的发展史。

从最开始只为了科研机构之间传文本,到现在能支撑起 4K 直播、实时游戏、AI 流式对话、全球高并发电商交易,HTTP 协议一直在跟着用户的需求,不断填坑、不断升级。

我们天天和它打交道,搞懂它的底层逻辑和进化思路,不仅能应付面试,更能在日常开发中,写出更高效的接口、做出更优的性能优化、排查问题的时候更快定位根因。

希望这篇文章,能帮你彻底搞懂 HTTP 协议,再也不怕面试官的灵魂拷问啦。