HTTP 简史

有关作者:

 Ilya Grigorik

  网络生态系统工程师
  • Shopify 首席工程师
  • 高性能浏览器网络作者
  • 企业家、煽动者、摄影师

      

  Ilya Grigorik 是 Google 的 Web 性能工程师,也是 W3C Web 性能工作组的联合主席。在他的博客


  本文来自他的有的一本书中的第九章: https://hpbn.co/brief-history-of-http/

  

   HTTP 简史

    HTTP,第 9 章

       超文本传输​​协议 (HTTP) 是 Internet 上最普遍和广泛采用的应用程序协议之一:它是客户端和服务器之间的通用语言,支持现代网络。从最初作为单个关键字和文档路径的简单开始,它已成为不仅是浏览器的首选协议,而且是几乎所有与 Internet 连接的软件和硬件应用程序的首选协议。

  在本章中,我们将简要回顾一下 HTTP 协议的演变历史。对不同 HTTP 语义的全面讨论超出了本书的范围,但了解 HTTP 的关键设计变化以及每个变化背后的动机,将为我们讨论 HTTP 性能提供必要的背景,尤其是在上下文中HTTP/2 中许多即将进行的改进。

   §HTTP 0.9:单行协议

  Tim Berners-Lee  最初的 HTTP 提案在设计时考虑到了 简单性,以帮助采用他的另一个新生想法:万维网。该策略似乎奏效了:有抱负的协议设计者,请注意。(创建万维网的原始提案 点这里)

  1991 年,Tim Berners-Lee 概述了新协议的动机并列出了几个高级设计目标:文件传输功能、请求对超文本存档进行索引搜索的能力、格式协商以及将客户端引用到另一个服务器的能力. 为了证明理论的实际应用,构建了一个简单的原型,它实现了所提议功能的一小部分:

  • 客户端请求是单个 ASCII 字符串。
    客户端请求由回车符 (CRLF) 终止。
    服务器响应是一个 ASCII 字符流。
    服务器响应是一种超文本标记语言 (HTML)。
    文件传输完成后连接终止。
    然而,即使这听起来比实际上要复杂得多。这些规则启用的是一个极其简单、对 Telnet 友好的协议,一些 Web 服务器至今仍支持该协议:

$> telnet google.com 80
Connected to 74.125.xxx.xxx
GET /about/
(hypertext response)
(connection closed)

 

  请求由一行组成:GET方法和请求文档的路径。响应是一个单一的超文本文档——没有标题或任何其他元数据,只有 HTML。它真的再简单不过了。此外,由于之前的交互是预期协议的子集,因此它非正式地获得了 HTTP 0.9 标签。其余的,正如他们所说,是历史。

  从 1991 年的这些不起眼的开始,HTTP 开始了自己的生命,并在接下来的几年中迅速发展。让我们快速回顾一下 HTTP 0.9 的特性:

  • 客户端-服务器,请求-响应协议。

  • ASCII 协议,在 TCP/IP 链接上运行。

  • 设计用于传输超文本文档 (HTML)。

  • 每次请求后服务器和客户端之间的连接都会关闭。

流行的 Web 服务器,例如 Apache 和 Nginx,仍然支持 HTTP 0.9 协议——部分原因是它没有太多功能!如果您好奇,请打开 Telnet 会话并尝试通过 HTTP 0.9 访问 google.com 或您自己喜欢的站点,并检查此早期协议的行为和限制。

    § HTTP/1.0:快速增长和信息 RFC

       1991 年到 1995 年是 HTML 规范、一种被称为“网络浏览器”的新型软件以及面向消费者的公共互联网基础设施的出现和快速发展的时期之一。

    §完美风暴:1990 年代初期的互联网热潮

  在 Tim Berner-Lee 的初始浏览器原型的基础上,美国国家超级计算应用中心 (NCSA) 的一个团队决定实施他们自己的版本。于是,第一个流行的浏览器诞生了:NCSA Mosaic。NCSA 团队的一名程序员 Marc Andreessen 与 Jim Clark 合作于 1994 年 10 月创建了 Mosaic Communications。该公司后来更名为 Netscape,并于 1994 年 12 月发布了 Netscape Navigator 1.0。至此,很明显,万维网注定不仅仅是一种学术好奇心。

事实上,同年第一次万维网会议在瑞士日内瓦举行,这导致了万维网联盟 (W3C) 的成立,以帮助指导 HTML 的发展。同样,在 IETF 内部成立了一个并行的 HTTP 工作组 (HTTP-WG),专注于改进 HTTP 协议。这两个群体继续对 Web 的发展起到重要作用。

最后,为了创造完美风暴,CompuServe、AOL 和 Prodigy 开始在 1994-1995 年相同的时间范围内向公众提供拨号互联网访问。乘着这股快速普及的浪潮,网景公司在 1995 年 8 月 9 日以极其成功的 IPO 创造了历史——互联网热潮已经到来,每个人都想分一杯羹!

不断增长的新兴 Web 所需功能列表及其在公共 Web 上的用例迅速暴露了 HTTP 0.9 的许多基本限制:我们需要一个不仅可以服务于超文本文档的协议,还可以提供有关请求和请求的更丰富的元数据。响应、启用内容协商等。反过来,新生的 Web 开发者社区的响应是通过一个特别的过程产生大量实验性的 HTTP 服务器和客户端实现:实现、部署并查看其他人是否采用它。

从这段快速实验开始,一套最佳实践和通用模式开始出现,1996 年 5 月 HTTP 工作组 (HTTP-WG) 发布了 RFC 1945,其中记录了许多 HTTP/1.0 实现的“通用用法”在野外发现。请注意,这只是一个信息 RFC:HTTP/1.0,因为我们知道它不是正式的规范或 Internet 标准!

话虽如此,一个示例 HTTP/1.0 请求应该看起来很熟悉:

$> telnet website.org 80

Connected to xxx.xxx.xxx.xxx

GET /rfc/rfc1945.txt HTTP/1.0 
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Accept: */*

HTTP/1.0 200 OK 
Content-Type: text/plain
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

(plain-text response)
(connection closed)
  1. 带有 HTTP 版本号的请求行,后跟请求标头

  2. 响应状态,后跟响应标头

  前面的交流并不是 HTTP/1.0 功能的详尽列表,但它确实说明了一些关键的协议更改:

  • 请求可能包含多个换行符分隔的标头字段。

  • 响应对象以响应状态行为前缀。

  • 响应对象有自己的一组换行符分隔的标头字段。

  • 响应对象不限于超文本。

  • 每次请求后服务器和客户端之间的连接都会关闭。

  请求和响应标头都保存为 ASCII 编码,但响应对象本身可以是任何类型:HTML 文件、纯文本文件、图像或任何其他内容类型。因此,HTTP 的“超文本传输​​”部分在引入后不久就成为了一个误称。实际上,HTTP 已经迅速发展成为一种超媒体传输,但最初的名称仍然存在。

  除了媒体类型协商之外,RFC 还记录了许多其他常用实现的功能:内容编码、字符集支持、多部分类型、授权、缓存、代理行为、日期格式等。

  当今 Web 上的几乎每台服务器都可以并且仍然会使用 HTTP/1.0。除此之外,到现在为止,您应该知道得更多!每个请求都需要一个新的 TCP 连接会对 HTTP/1.0 造成显著的性能损失;请参阅三次握手,然后是慢启动

§HTTP/1.1:互联网标准

  将 HTTP 转变为官方 IETF 互联网标准的工作与围绕 HTTP/1.0 的文档工作同时进行,并发生在大约四年的时间里:1995 年至 1999 年。事实上,第一个官方 HTTP/1.1 标准定义在RFC 2068,于 1997 年 1 月正式发布,大约在 HTTP/1.0 发布六个月后。然后,两年半后的 1999 年 6 月,许多改进和更新被纳入标准并作为 RFC 2616 发布。

  HTTP/1.1 标准解决了早期版本中存在的许多协议歧义,并引入了许多关键的性能优化:keepalive 连接、分块编码传输、字节范围请求、附加缓存机制、传输编码和请求管道。

  有了这些功能,我们现在可以检查任何现代 HTTP 浏览器和客户端执行的典型 HTTP/1.1 会话:

$> telnet website.org 80
Connected to xxx.xxx.xxx.xxx

GET /index.html HTTP/1.1 
Host: website.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=P0-800083390... (snip)
HTTP/1.1 200 OK 
Server: nginx/1.0.11
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Via: HTTP/1.1 GWA
Date: Wed, 25 Jul 2012 20:23:35 GMT
Expires: Wed, 25 Jul 2012 20:23:35 GMT
Cache-Control: max-age=0, no-cache
Transfer-Encoding: chunked
100 
<!doctype html>
(snip)
100
(snip)
0 

GET /favicon.ico HTTP/1.1 
Host: www.website.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
Accept: */*
Referer: http://website.org/
Connection: close 
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=P0-800083390... (snip)

HTTP/1.1 200 OK 
Server: nginx/1.0.11
Content-Type: image/x-icon
Content-Length: 3638
Connection: close
Last-Modified: Thu, 19 Jul 2012 17:51:44 GMT
Cache-Control: max-age=315360000
Accept-Ranges: bytes
Via: HTTP/1.1 GWA
Date: Sat, 21 Jul 2012 21:35:22 GMT
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Etag: W/PSA-GAu26oXbDi

(icon data)
(connection closed)
Request for HTML file, with encoding, charset, and cookie metadata
Chunked response for original HTML request
Number of octets in the chunk expressed as an ASCII hexadecimal number (256 bytes)
End of chunked stream response
Request for an icon file made on same TCP connection
Inform server that the connection will not be reused
Icon response, followed by connection close

 

  呸,里面发生了很多事情!第一个也是最明显的区别是我们有两个对象请求,一个用于 HTML 页面,一个用于图像,两者都通过单个连接传递。这是连接保持活动,它允许我们将现有的 TCP 连接重用于对同一主机的多个请求,并提供更快的最终用户体验;请参阅为 TCP 优化

  要终止持久连接,请注意第二个客户端请求close通过标头向服务器发送显式令牌 Connection类似地,一旦响应被传输,服务器可以通知客户端关闭当前 TCP 连接的意图。从技术上讲,任何一方都可以在没有此类信号的情况下终止 TCP 连接,但客户端和服务器应尽可能提供它,以便在双方实现更好的连接重用策略。

  HTTP/1.1 更改了 HTTP 协议的语义,默认使用连接 keepalive。意思是,除非另有说明(通过 Connection: close标头),否则服务器应默认保持连接打开。

  但是,同样的功能也被反向移植到 HTTP/1.0 并通过Connection: Keep-Alive标头启用。因此,如果您使用的是 HTTP/1.1,从技术上讲,您不需要 Connection: Keep-Alive标头,但许多客户端仍然选择提供它。

  此外,HTTP/1.1 协议添加了内容、编码、字符集,甚至语言协商、传输编码、缓存指令、客户端 cookie,以及可以在每个请求上协商的十几个其他功能。

  我们不会详述每个 HTTP/1.1 特性的语义。这是一本专门书籍的主题,已经写了很多很棒的书。相反,前面的示例很好地说明了 HTTP 的快速进步和演变,以及每个客户端-服务器交换的错综复杂的舞蹈。里面发生了很多事情!

  有关 HTTP 协议的所有内部工作原理的良好参考,请查看 O'Reilly 的HTTP: David Gourley 和 Brian Totty 的权威指南。

    §HTTP/2:提高传输性能

  自发布以来,RFC 2616 已成为 Internet 空前增长的基础:数十亿台各种形状和大小的设备,从台式计算机到我们口袋里的微型 Web 设备,每天都使用 HTTP 来传递新闻、视频、以及我们生活中依赖的数百万其他 Web 应用程序。

  最初是一种用于检索超文本的简单的单行协议,很快演变为通用的超媒体传输,十年后的现在可以用于支持几乎任何你能想象到的用例。可以说协议的服务器无处不在,客户端使用它的广泛可用性意味着现在许多应用程序都是专门在 HTTP 之上设计和部署的。

  需要一个协议来控制你的咖啡壶?RFC 2324 为您提供了超文本咖啡壶控制协议 (HTCPCP/1.0) — 最初是 IETF 的愚人节玩笑,在我们新的超连接世界中越来越多的不是玩笑。

超文本传输​​协议 (HTTP) 是分布式、协作、超媒体信息系统的应用层协议。它是一种通用的、无状态的协议,通过扩展其请求方法、错误代码和标头,可用于超文本之外的许多任务,例如名称服务器和分布式对象管理系统。HTTP 的一个特性是数据表示的类型化和协商,允许独立于正在传输的数据构建系统。

RFC 2616:HTTP/1.1,1999 年6 月

  HTTP 协议的简单性是其最初采用和快速发展的原因。事实上,现在发现嵌入式设备(传感器、执行器和咖啡壶等)使用 HTTP 作为其主要控制和数据协议的情况并不少见。但在其自身成功的重压下,随着我们越来越多地继续将我们的日常互动迁移到网络上——社交、电子邮件、新闻和视频,以及越来越多的整个个人和工作工作空间——它也开始显示出压力的迹象。用户和 Web 开发人员现在都要求 HTTP/1.1 提供近乎实时的响应能力和协议性能,如果不进行一些修改,它根本无法满足。

  为了应对这些新挑战,HTTP 必须继续发展,因此 HTTPbis 工作组在 2012 年初宣布了 HTTP/2 的新计划:

对于保留 HTTP 语义而没有遗留 HTTP/1.x 消息框架和语法的协议正在出现新的实现经验和兴趣,这些已被确定为妨碍性能并鼓励滥用底层传输。

工作组将在有序的双向流中生成 HTTP 当前语义的新表达规范。与 HTTP/1.x 一样,主要目标传输是 TCP,但应该可以使用其他传输。

HTTP/2 章程,2012 年 1 月

  HTTP/2 的主要重点是提高传输性能并实现更低的延迟和更高的吞吐量。主要版本的增加听起来像是一个很大的进步,就性能而言,它现在是并且将会是,但重要的是要注意没有任何高级协议语义受到影响:所有 HTTP 标头、值和用例是相同的。

  任何现有的网站或应用程序都可以并且将通过 HTTP/2 交付而无需修改:您无需修改​​应用程序标记即可利用 HTTP/2。HTTP 服务器必须使用 HTTP/2,但这对于大多数用户来说应该是一个透明的升级。如果工作组实现其目标,唯一的区别应该是我们的应用程序以更低的延迟和更好的网络链接利用率交付!

  话虽如此,让我们不要超越自己。在我们了解新的 HTTP/2 协议功能之前,有必要退后一步,检查一下我们现有的 HTTP/1.1 部署和性能最佳实践。HTTP/2 工作组在新规范上取得了快速进展,但即使最终标准已经完成并准备就绪,在可预见的未来——实际上,十年或更长时间——我们仍然必须支持旧的 HTTP/1.1 客户端。

  « 返回目录

posted @ 2022-06-23 01:23  jinzi  阅读(2)  评论(0编辑  收藏  举报