超文本传输协议(HTTP)是互联网上最普遍并广泛采用的应用协议之一:它是客户端和服务器之间的通用语言,促成了现代网络的形成。最开始它以单关键字和文档路径的简单形式出现,目前已成为不仅仅是浏览器,几乎每个互联网连接的软件和硬件应用程序所选择的协议。
在本章中,我们将简要介绍HTTP协议的演进。对不同HTTP语义的完整讨论超出了本书的范围,但是了解HTTP的关键设计变更及其背后的动机将为我们讨论HTTP性能提供必要的知识储备,特别是在许多即将到来的HTTP/2改进的背景下。
HTTP0.9:单线协议
Tim Berners-Lee提出最初的HTTP提案设计时,考虑到了其简单性,这帮助了他采用他的新想法:万维网。似乎策略被应用之后,这位有抱负的协议设计者才进入大家的视野。
1991年,Berners-Lee概述了新协议的动机,列出了几个高级设计目标:文件传输,对超文本进行索引搜索并将其存档,格式协商以及由客户端向服务器发出请求。为了切实地证明理论,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接受了自己的生活,并在未来几年迅速发展。让我们快速回顾一下HTTP 0.9的特性:
客户端 - 服务器,请求 - 响应协议。
通过TCP / IP链路运行的ASCII协议。
被设计用于传输超文本文件(HTML)。
每次请求后,服务器和客户端之间的连接关闭。
流行的Web服务器,如Apache和Nginx,仍然支持部分的HTTP0.9协议(HTTP0.9内容并不多)。如果你好奇,打开Telnet会话,并尝试通过HTTP 0.9访问google.com或您自己喜欢的网站,并查看此早期协议的行为和局限性。
HTTP / 1.0:快速生长和信息RFC
1991年到1995年是HTML规范(一种被称为“网络浏览器”的新型软件)和 以消费者为导向的公共互联网基础设施的快速协同增长时期。
完美风暴:在20世纪90年代早期的互联网热潮
基于Tim Berner-Lee的浏览器原型,国家超级计算应用中心(NCSA)的一个团队决定实施自己的版本。这样,第一个流行的浏览器NCSA Mosaic诞生了。NCSA团队的一名程序员Marc Andreessen与Jim Clark合作,于1994年10月成立了Mosaic通讯公司,后来更名为Netscape,并于1994年12月发布了Netscape Navigator 1.0。至此,万维网在大家心中的意义已经不仅限于学术上的探索。
事实上,同年在瑞士日内瓦举办了第一次万维网会议,会议上万维网联盟(W3C)创建,以帮助指导HTML的发展。与此同时,在IETF内部建立并行的HTTP工作组(HTTP-WG)也致力于HTTP协议的改进。这两个组织持续推动了网络的发展。
最后,这场完美的风暴中,还有一个重大举措:CompuServe,AOL和Prodigy在1994 - 1995年的同一时间段内开始向公众提供拨号上网。在技术快速变现的浪潮中,Netscape在1995年8月9日成功举办了一次非常成功的IPO,互联网热潮已经到来,每个人都想参与其中!
HTTP 0.9并不能很好地满足新兴网络的需求,并且实际的使用也暴露了HTTP 0.9的许多基本限制:我们需要一个协议,不仅可以服务于超文本文档,还可以提供更多关于请求的元数据响应,启用内容协商等。而在实际应用中,网络开发人员的新生社区通过大家共同推动的过程,生成了大量实验性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 //请求行与HTTP版本号,后跟请求头
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)
上述消息机制不是HTTP / 1.0功能的详尽列表,但它说明了一些关键协议更改:
请求可能包含多个换行标题字段。
响应对象以响应状态行为前缀。
响应对象有自己的一行以换行符分隔的头部。
响应对象不限于超文本。
每个请求后,服务器和客户端之间的连接关闭。
请求头和响应头都保存为ASCII编码,但响应对象本身可以是任何类型:HTML文件,纯文本文件,图像或任何其他内容类型。因此,HTTP的“超文本传输”部分在引入后不久很容易被人们误会。在现实中,HTTP已迅速发展成为一个超媒体传输,但原来的名字依旧被保留。
除媒体类型协商外,RFC还记录了许多其他常用功能:内容编码,字符集支持,多类型,授权,缓存,代理行为,日期格式等。
今天,网络上几乎每个服务器仍是以HTTP / 1.0的协议传输的。除此之外,你应该很清楚!每个请求都要有新的TCP连接,对HTTP / 1.0是很大的性能损失; 参见三次握手,还有慢启动。
HTTP / 1.1:互联网标准
从1995年至1999年,HTTP / 1.0的文档化在逐步推进,历时4年,HTTP成为官方IETF互联网的标准。事实上,大约在HTTP / 1.0发布后六个月,第一个官方HTTP / 1.1标准定义在RFC 2068中,于1997年1月就正式发布。两年半后,1999年6月,一些改进和更新被纳入标准,并作为RFC 2616发布。
HTTP / 1.1标准规范了许多早期版本中的不清晰的协议内容,并引入了很多关键性能优化:持续连接,分块编码传输,以字节为单位的请求,另外还有缓存机制,传输编码和请求管线化(多个HTTP请求整批提交的技术)。
有了这些功能,我们现在可以通过在任何现代浏览器和客户端运用HTTP,观察典型的HTTP / 1.1会话:
$> telnet website.org 80
Connected to xxx.xxx.xxx.xxx
GET /index.html HTTP/1.1 //请求HTML文件,其中包含编码,字符集和Cookie元数据
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 //针对原始HTML请求的分块响应
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 //块中的八位字节数以ASCII十六进制数表示(256字节)
<!doctype html>
(snip)
100
(snip)
0 //分块流响应结束
GET /favicon.ico HTTP/1.1 //请求在同一个TCP连接上图标文件
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页面,另一个用于图像,两者都通过单个连接传递。每次连接都是持续的,这允许我们重复使用现有的TCP连接实现多个请求到相同的主机,并提供更快的终端用户体验; 参阅优化TCP。
要终止持久连接,你将会注意到,第二客户端在请求的连接头中发送了显式关闭令牌到服务器。类似地,服务器可以在传输响应时,通知客户端它意图关闭当前TCP连接。从技术上讲,任何一方都可以在任何时候终止TCP连接而无需这种信号,但客户端和服务器应尽可能提供它,以便使双方实现更好的连接重用策略。
默认情况下,HTTP / 1.1使用持续链接,这是在HTTP协议语义上做出的更改。这意味着,除非另行告知(通过 Connection: close头),服务器应该保持连接默认打开。
然而,这种相同的功能通过启用Connection: Keep-Alive报头,也被反向移植到HTTP / 1.0。因此,如果你正在使用HTTP / 1.1,在技术上你不需要的 Connection: Keep-Alive头,但许多客户选择仍然提供。
此外,HTTP / 1.1协议添加了内容,编码,字符集,甚至语言协商,传输编码,缓存指令,客户端cookie,以及可以在每个请求上协商的十几个其他功能。
我们不会讲述每个HTTP / 1.1功能的语义。这是一本专门的HTTP协议书该做的,许多伟大的书已经做得很好。而且,前面的例子很好地说明了HTTP的快速进展和进化,以及每个客户端 - 服务器错综复杂的优雅信息交换机制。那里有很多地方值得探索!
推荐一个有关HTTP协议所有工作机制的参考:O’Reilly’s HTTP: David Gourley 和 Brian Totty 写的权威指南.
HTTP / 2:提高传输性能
自从问世以来,RFC 2616已经成为互联网前所未有的发展基础:数十亿种各种形状和大小的设备,从台式电脑到我们口袋里的小型网络设备,每天都会传出HTTP,它提供新闻,视频,以及数百万其他我们生活中依赖的网络应用程序。
最开始的一个简单的单行协议检索超文本快速演变成一个通用的超媒体传输,十年以后的现在,它可以用来满足任何你可以想象的使用场景。可以说服务器使用协议之普遍,用户在客户端的使用之广泛,意味着许多应用程序现在是专门设计和部署在HTTP之上的。
需要一个协议来控制你的咖啡壶?RFC 2324已经覆盖了超文本咖啡壶控制协议(HTCPCP / 1.0) - 这是最初是IETF的愚人节玩笑,超链接为我们打开了新世界的大门。
超文本传输协议(HTTP)是用于分布式,协作的超媒体信息系统的应用级协议。它是一种通用的,无状态的协议,可以通过扩展其请求方法,错误代码和头部信息,将其用于许多超出超文本使用的任务,如域名解析和分布式对象管理系统。HTTP的一个特征是数据表示的归类和协商,允许系统独立于要传输的数据。RFC 2616:HTTP / 1.1,1999年6月
HTTP协议的简单性使其最初可以被采用并且能够快速发展。事实上,现在在嵌入式设备 - 传感器,执行器和咖啡壶中,使用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客户端。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。