高性能浏览器网络 --> 第三部分 HTTP --> 第9章 HTTP简史
HTTP是因特网上最广泛和普遍采用的应用协议之一:它是客户端与服务器之间共同的语言,造就了今天的web网络。HTTP诞生之初,只是简单作为一种关键字导航路径,现在它不仅仅用于浏览器,而是几乎被所有连网软件和硬件应用所采用。
本章,我们将对HTTP协议的进化史做一个简要概括。关于各种各样的HTTP语义的完整讨论超出了本书的范围,但对HTTP关键设计的变化,以及每一个变化之后的动机的理解,将给与我们讨论HTTP性能的必要的背景知识,特别是在HTTP 2.0的许多改进即将到来的背景下。
HTTP 0.9: 单行协议(The One-Line Protocol)
最初的HTTP协议由Tim Berners-Lee提出,当初设计时就尽量考虑简单性,以帮助实现他的一个新想法:万维网。该策略似乎已经奏效了。
在1991年,Berners-Lee概述了新协议的设计动机,并列出了几个高层设计目标:文件传输功能,能够请求搜索超文本文档,格式协商,能够把一个客户转介到另一个服务器。为了用行动证明这些理论,他创建了一个简单的原型,实现了部分规划功能:
- 客户端请求是一个单一的ASCII字符串
- 客户端请求由一个回车符号结束
- 服务器响应是一个ASCII字符流
- 服务器响应是一个HTML
- 文档传输完成后连接即终止
听起来好像很复杂,其实很简单。一个相当简单的,Telnet友好协议实现了这些规则。
这个请求由一个单行组成:GET 方法和请求文档的路径。响应是一个超文本文档 -- 没有头部信息和其它元数据,只有HTML。再简单不过了。此外,因为前面提到的交互只是 the intended protocol的一个子集,所以非正式的被称为HTTP 0.9。
HTTP诞生于1991年,并后面的几年迅速进化。让我们简明扼要概述HTTP 0.9的功能:
- C-S,请求响应协议
- ASCII协议,运行在TCP/IP链路上
- 用户传输超文本
- 每个请求之后关闭服务器与客户端之间的连接
一些流行的web服务器,比如Apache, Nginx,仍然部分支持HTTP 0.9协议,因为与现在的版本相比没有多大不同!你可以打开一个Telnet会话并试着通过HTTP 0.9 访问google.com,或者你喜欢的站点,以坚持这一早期协议的行为和限制。
HTTP 1.0: 快速增长以及非正式RFC(Rapid Growth and Informational RFC)
1991年到1995年这段时间,是HTML规范,一种新的被称为“web browser”的软件趋同进化时期,面向消费者的公共因特网基础设施也在这段时间出现并快速发展。
对这个新诞生的Web, 我们想要的功能越来越多,而且随着它的迅速普及,许多HTTP 0.9的局限被暴露出来:我们需要一个能做得更多的协议,不仅仅服务于超文本,还要能提供更丰富的关于请求和响应的元数据,允许内容协商,等等。In turn, 新生的web开发者社区对此作出了回应,他们通过一个特殊的过程,生产大量实验性的HTTP服务器和客户端实现:实现,部署,看其它人是否采用。
在这个快速试验区间,一套最佳实践和通用模式开始出现,1996年5月,HTTP工作组(HTTP -WG)发布了RFC 1945,该文档记录了坊间流传的许多HTTP 1.0实现的”常见用法“。注意这只是一个指导性的RFC:我们知道,HTTP 1.0不是一个正式的规范或因特网标准。
但话说回来,一个HTTP1.0请求应该与此类似:
带HTTP版本号的请求行,后面跟着请求头
响应状态,后面跟着响应头
前面所述的这个交换并没有战士HTTP 1.0的所有功能,不过它体现了协议的一些关键变化:
- 请求可能包括多行,每一行是一个头域
- 响应对象以一个响应状态行开始
- 响应对象有它自己的由换行符分割的头域
- 响应对象不只限于超文本
- 在每个请求之后端口服务器与客户端连接
请求和响应头均以ASCII编码,但响应对象可以是任何类型:一个HTML文件,一个普通文本文件,一张图片,或其它任何类型的内容。因此,HTTP的”超文本传输“部分在引入不久之后就成为了一个误称。现实中,HTTP进化很快,已经成为超媒体(hypermedia transport),但原来的名字一直流传下来。
除了媒体类型协商,这个RFC也记录了许多其它通用实现能力:内容编码,字符集支持,multi-part types,权限控制,缓存,代理行为,日期格式,等等。
HTTP 1.1:因特网标准
推动HTTP成为一个官方 IETF因特网标准的工作与围绕HTTP 1.0的文档工作并行进行已有大约四年之久:在1995和1999年间。事实上,第一个官方HTTP 1.1标准是在RFC 2068中定义的,该RFC正式发布于1997年1月,大约在HTTP 1.0发布之后六个月。两年半之后,1999年的六月,许多改进和更新被集成进标准中,并作为RFC 2616发布。
HTTP 1.1标准解决了之前的版本中一些含糊不清的地方,并引入了许多关键性能优化:keepalive连接,chunked编码传输,字节范围请求,额外的缓存机制,传输编码,还有请求流水线。
了解这些功能后,现在我们我们来看看一个由现代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)
请求HTML文件, 并指明编码,字符集以及cookie元数据 |
以Chunked方式响应之前的HTML请求 | |
一个16进制字符数字表示的chuank字节数 | |
chunked流响应结束 | |
通过同一个TCP连接请求一个icon文件 | |
通知服务器不重用连接 | |
响应icon文件,接着关闭连接 |
唷,信息量很大啊!第一个也是最明显的差异是,我们有两个请求对象,一个用于请求HTML网页,一个用于请求一副图像,两者通过同一个连接发送。这是连接keepalive在起作用,它允许我们重用已存在的HTTP连接,发送到同一个主机的多个请求,以提供快得多的端用户体验。 see “Optimizing for TCP”.
要终止持久连接,通知第二个客户端请求通过连接头发送一个显示的 close 字串给服务器。类似的,一旦响应传输完成,服务器也可以通知客户关闭当前连接。技术上,即使没有这样的信号,任意一边都能够终止TCP连接,但客户端和服务器应该尽可能的提供它,以使双方能够采用更好的重用策略。
HTTP 1.1改变了HTTP协议的语义,默认使用连接keepalive。意思是,除非说明(通过Connection:close头),服务器应该默认保持连接打开。然而,这个功能是向后兼容HTTP 1.0的,即通过Connection: Keep-Alive头。因此,如果你正在使用HTTP 1.1,技术上你不需要Connection: Keep-Alive头,尽管如此,许多客户端仍然选择提供它。
另外,HTTP 1.1协议添加了内容, 编码,字符集,甚至语言协商,传输编码,缓存目录,客户端cookies,加上其它十几种功能都能够在每个请求上进行协商。
我们不是详述每一个HTTP 1.1功能的语义。这要够写一本专门书籍了,而且已经有不少这样的书籍了。前面的例子很好的展示了HTTP的进步和进化,以及每个客户端-服务器交换的错综复杂的步骤。体现了很多东西!
原文:http://chimera.labs.oreilly.com/books/1230000000545/ch09.html