1990 年前后, 由当时在欧洲核子研究中心工作的前端祖师爷迪姆帕纳斯李 (Tim Berners Lee) 提出草案, 基于 TCP、IP 协议实现了 HTTP 协议 0.9 版本简单却不简陋, 一经发布, 就让浏览器和服务器对 HTTP 协议产生了旺盛的需求, 在随后的纪念里社区对 0.9 版本的协议自发的进行了许多修补和增强 一开始没有版本号, 后来约定俗成称为 0.9 版本
欧洲核子研究中心内部文档管理混乱, 信息交流不方便
最早的 HTTP 协议版本, 他只有 GET 方法, 仅支持传输 HTML 内容, 没有实现 HTTP 请求头和请求体, HTTP 请求只有 1 行内容: GET /index.html
除了 HTTP 协议, 还一并实现了 HTML, 主要用于学术交流, 仅支持纯文本信息. 也正是因为简单好用, HTTP 协议迅速在互联网上流行开来, 被众多浏览器和服务器接纳
1996 年前后, 为了强化 HTTP 协议、解决不同浏览器、服务器之间基于 HTTP/0.9 协议通信靠相互试探的问题, 由蒂姆帕纳斯李发起了一份意见征求稿: RFC 1945, 从众多自发的实践经验中汲取精华, 讨论确立了 HTTP/1.0 版本
队头阻塞 (HOL blocking) 问题: 浏览器和服务器通信过程中, 因为部分请求长期无响应, 导致阻塞后续请求发送和响应接受
例如: 浏览器请求一个 1MB 的 JS 文件时, 如果响应较慢, 就会导致后续 1KB 的 CSS 文件长时间等待、无法加载. 就像我们去或者站排队买票时, 排在队头的第一个客户长时间占据窗口, 就会导致后续用户等待较长时间
与 1.0 版本几乎相同, 更正式的规范讨论也在进行, 并于 1997 年发布了意见征询稿: RFC 2068, 进一步解决了 HTTP 协议的诸多痛点. HTTP/1.1 版本后续虽有小修小补, 但总体上稳定了长达 15 年之久
Etag
, If-None-match
, Cache-Control
等专用头部OPTIONS
, HEAD
, PUT
, DELETE
等新一批的 HTTP 请求方法, 以及 307 永久重定向等一批新的 HTTP 状态码2009 年前后, 为了解决 HTTP/1.1 版本性能, Google 实现了名为 SPDY 的实验性协议. 2015 年, 由 Google 推动, 在 SPDY 协议的基础上, 标准化了 HTTP/2 协议
十几年过去, HTTP/1.1 版本的性能表现日渐落后, 急需大幅优化性能
多路复用
服务端推送
建立连接后, 即使还没有收到浏览器的请求, 服务器也可以主动把各种类型的资源推送给浏览器 比如, 浏览器只请求了 index.html, 但是服务器把 index.html、style.css、example.png 全部都发送给浏览器. 这样的话只需要一轮 HTTP 通信, 浏览器就得到了全部资源, 提高了性能 不建议一次推送太多资源, 这样反而会拖累性能, 因为浏览器不得不处理所有推送过来的资源. 只推送 CSS 样式表可能是一个比较好的选择
头部压缩
将有大量重复内容的 HTTP 请求响应头进行压缩, 节省网络流量
全面基于二进制格式传输
此前的 HTTP/1.1 版本, 头部必须是文本格式, 数据支持文本、二进制两种格式. HTTP/2 进一步全面支持二进制格式, 以及基于二进制数据分帧, 从客户端乱序发送, 到服务端再按帧内数据排序组装
2013 年, Google 为了进一步优化 HTTP 协议的性能, 加快网页传输, 设计并实现了快速 UDP 互联网连接 (Quick UDP internet Connection, 简称 QUIC), 为 2018 年 HTTP/3 的确立奠定了基础
HTTP/2 连接建立时长较短, 因为基于 TCP 协议, 三握四挥的过程开销无法避免
TCP 队头阻塞问题: HTTP/2 运行在单个 TCP 连接上, 因此 TCP 层进行丢包检测和重传时可能会阻塞后续数据
HTTP/2 在弱网环境, 尤其是移动互联网场景中性能较差, 因为移动设备连接互联网时, 往往会时不时切换网络环境, 例如从 4G 切换到 WiFi, 这种情况下 HTTP/2 不得不重新创建 TCP 连接, 开销较大
基于 UDP 协议实现
减少了连接延迟, 避免了 TCP 三握四挥的开销, 避免网络环境变化时需要重新连接的问题, 优化了移动设备的连接性能
囊括 TLS 协议
更快的实现了 TLS 握手, 进一步减少往返时间 (Round Trip Time, RTT) 延迟