HTTP 的进化 – 理解真实的 HTTP 是如何工作的
原文: https://medium.com/platform-engineer/evolution-of-http-69cfe6531ba0
自从在 1989-1991 年间被 CERN(译注:即“欧洲核子研究组织”的原称 – Conseil Européen pour la Recherche Nucléaire)的 Tim Berners-Lee 发明出来以后,HTTP(超文本传输协议) 就一直是万维网的基础传输协议。在 C/S 计算模型中,HTTP 起到了一个“请求/响应”协议的作用。HTTP 标准由 IETF(因特网工程任务组) 和 W3C(万维网联盟)负责开发,并以一系列注释请求(RFCs – Requests for Comments)的形式被发布。HTTP 有 4 个版本:HTTP/0.9、HTTP/1.0、HTTP/1.1 以及 HTTP/2.0。当前通常使用 HTTP/1.1 版本,未来会是 HTTP/2.0。
HTTP/0.9 — 单行协议
- HTTP 的首个版本 — 一个简单的 客户端/服务器、请求/响应、对 telenet 友好的协议
- 请求: 单行 (method + 所请求文档的 path)
- 支持的方法: 仅
GET
- 响应类型: 仅 超文本
- 响应后马上结束的连接
- 没有 HTTP headers (无法传输其他内容类型的文件), 没有 status/error 代码, 没有 URLs, 没有版本控制
$> telnet ashenlive.com 80
(连接1建立 - TCP 三次握手)
Connected to xxx.xxx.xxx.xxx
(请求)
GET /my-page.html
(超文本响应)
<HTML>
A very simple HTML page
</HTML>
(连接1关闭 - 断掉 TCP)
复制代码
流行的 web 服务器(Apache, Nginx)始终支持 HTTP/0.9。可以打开一个 Telnet 会话访问 google.com 试试。
HTTP/1.0 — 构建可扩展性
- 对浏览器友好的协议
- 提供了对请求和响应都包含丰富元数据的 header 域 (HTTP 版本号、status code 和 content type)
- 响应:不再只限于超文本 (Content-Type 头部提供了传输 HTML 之外文件的能力 — 如脚本、样式或媒体文件)
- 支持的方法:
GET
,HEAD
,POST
- 响应后马上结束的连接
(连接1建立 - TCP 三次握手)
Connected to xxx.xxx.xxx.xxx
(请求)
GET /my-page.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
(响应)
HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 137582
Expires: Thu, 01 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 1 May 1996 12:45:26 GMT
Server: Apache 0.84
<HTML>
A page with an image
<IMG SRC="/myimage.gif">
</HTML>
(连接1关闭 - 断掉 TCP)
------------------------------------------
(连接2建立 - TCP 三次握手)
Connected to xxx.xxx.xxx.xxx
(请求)
GET /myimage.gif HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
(响应)
HTTP/1.0 200 OK
Content-Type: text/gif
Content-Length: 137582
Expires: Thu, 01 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 1 May 1996 12:45:26 GMT
Server: Apache 0.84
[image content]
(连接2关闭 - 断掉 TCP)
复制代码
HTTP/0.9 和 HTTP/1.0 的主要问题 — 为每个请求建立一个新连接
HTTP/0.9 和 HTTP/1.0 都需要为每次请求建立一个新的连接(并在收到对应的响应后立即关闭该连接)。每次新连接建立时,都要经历一遍 TCP 三次握手。考虑到更好的性能,应该着重减少这些 C/S 之间的往返通信。HTTP/1.1 用持久化连接解决了这个问题。
典型的 TCP 三次握手(观察一下 TCP 状态机是如何改变其状态的吧)
HTTP/1.1 — 标准化的协议
- 这是当前普遍使用的 HTTP 版本
- 进行了重大的性能优化和特性增强,分块传输、压缩/解压、内容缓存磋商、虚拟主机(有单个 IP 地址的主机具有多个域名)、更快的响应,以及通过增加缓存节省了更多的带宽
- 支持的方法:
GET
,HEAD
,POST
,PUT
,DELETE
,TRACE
,OPTIONS
- 长久的连接
(连接1建立 - TCP 三次握手)
Connected to xxx.xxx.xxx.xxx
(请求1)
GET /en-US/docs/Glossary/Simple_header HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header
(响应1)
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Wed, 20 Jul 2016 10:55:30 GMT
Etag: "547fa7e369ef56031dd3bff2ace9fc0832eb251a"
Keep-Alive: timeout=5, max=1000
Last-Modified: Tue, 19 Jul 2016 00:59:33 GMT
Server: Apache
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding
[content]
(请求2)
GET /static/img/header-background.png HTTP/1.1
Host: developer.cdn.mozilla.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header
(响应2)
HTTP/1.1 200 OK
Age: 9578461
Cache-Control: public, max-age=315360000
Connection: keep-alive
Content-Length: 3077
Content-Type: image/png
Date: Thu, 31 Mar 2016 13:34:46 GMT
Last-Modified: Wed, 21 Oct 2015 18:27:50 GMT
Server: Apache
[image content of 3077 bytes]
(连接1关闭 - 断掉 TCP)
复制代码
TCP 三次握手会在任何连接被建立之前发生一次。最终,当发送了所有数据之后,服务器发送一个消息,表示不会再有更多数据向客户端发送了;则客户端才会关闭连接(断开 TCP)。HTTP/1.0 存在的问题是,对于每个 请求/响应 轮回,也要建立并关闭一个连接。而改用 HTTP/1.1 后的优点则在于,可以复用同一个连接,来完成多次 请求/响应 轮回
Keep-Alive 和 Upgrade 头部
Keep-Alive 头部
Connection: Keep-Alive
头部在 HTTP/1.1 之前就存在,但在 HTTP/1.1 中该头部被废弃了,因为持久化连接变成了默认的行为(译注:除非用Connection: Close
显式关闭)。Keep-Alive
头部可以被用于在主机之间定义持久连接通信策略(比如使一个连接在某个事件发生之前都保持激活)。这奠定了持久化、连接复用、管道化及其他很多现代 web 通信协议中被加强能力的基础。- 可以对客户端、服务器,或任何中间人分别设置独立的
Keep-Alive
头部。同时,主机可以增加timeout
参数以设置一个超时,或用max
参数限制每个连接的最大请求数。
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Thu, 11 Aug 2016 15:23:13 GMT
Keep-Alive: timeout=5, max=1000
Last-Modified: Mon, 25 Jul 2016 04:32:39 GMT
Server: Apache
[body]
复制代码
`Keep-Alive` 头部的用法。所有连接都是独立协商的
- 受益于
Keep-Alive
头部,HTTP 管道化实现了多个连接,以及其他更多改进。
HTTP 管道化和多个并行连接
Upgrade 头部
- 借助 HTTP/1.1 带来的
Upgrade
头部,便可用一个常用的协议起步,比如 HTTP/1.1,然后让该连接切换到增强的协议类型,如 HTTP/2.0 或 WebSockets。 - 在一个升级过的连接中,不再有
max
参数了。升级后的协议为timeout
参数提供了新的策略(如果没有特别定义,使用基础协议默认的 timeout 值)。
由 HTTP/1.1 升级到 WebSocket[RFC6455]
HTTPS
- 加密超文本传输协议(HTTPS)是 HTTP 的安全版本,使用 SSL/TLS 完成安全加密通信。
- 最初由网景公司在 90 年代中期开发,SSL(安全套接字层)是一种增强 HTTP 的密码学协议,定义了客户端和服务器之间如何安全的互相通信。TLS(安全传输层协议)是 SSL 的继承者。
- 因为在客户端和服务器间提供了双向加密,HTTPS 连接可以在数据传输中防止中间人攻击和常见的安全威胁。
访问 msdn.microsoft.com 站点时的 SSL 握手过程 — TCP 连接 -> SSL/TLS 客户端 Hello -> SSL/TLS 服务器 Hello -> SSL/TLS 认证 -> SSL/TLS 客户端交换秘钥 -> SSL/TLS 新会话 Ticket -> HTTPS 加密数据传输
SSL/TLS 握手 — HTTPS 中的主要问题
- 尽管 HTTPS 设计上是安全的,但 SSL/TLS 握手过程在 HTTPS 连接之前消耗了显著的时间;通常会耗费 1 至 2 秒,极大影响了网站启动性能。
HTTP/2.0 和未来
所有以上提及的特性,当今都已经被主要的服务器和浏览器所使用了。但像 HTTP/2.0、Server Side Events (SSE) 以及 WebSocket 这样的现代增强功能,则改变了传统 HTTP 的工作方式。
参考:
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP
- https://tools.ietf.org/id/draft-thomson-hybi-http-timeout-01.html
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism
- https://hpbn.co/brief-history-of-http/
—————————————-
长按二维码或搜索 fewelife 关注我们哦