HTTP非持久连接和持久连接
HTTP既可以使用非持久连接(nonpersistent connection),也可以使用持久连接(persistent connection)。HTTP/1.0使用非持久连接,HTTP/1.1默认使用持久连接。
1.非持久连接
让我们查看一下非持久连接情况下从服务器到客户传送一个Web页面的步骤。假设该页面由1个基本HTML文件和10个JPEG图像构成,而且所有这些对象都存放在同一台服务器主机中。再假设该基本HTML文件的URL为:www.phei.com/somepath/index.html。
下面是具体步骤。
1)HTTP客户初始化一个与服务器主机www.phei.com中的HTTP服务器的TCP连接。HTTP服务器使用默认端口号80监听来自HTTP客户的连接建立请求。
2)HTTP客户经由与TCP连接相关联的本地套接字发出-个HTTP请求消息。这个消息中包含路径名/somepath/index.html。
3)HTTP服务器经由与TCP连接相关联的本地套接字接收这个请求消息,再从服务器主机的内存或硬盘中取出对象/somepath/index.html,经由同一个套接字发出包含该对象的响应消息。
4)HTTP服务器告知TCP关闭这个TCP连接(不过TCP要到客户收到刚才这个响应消息之后才会真正终止这个连接)。
5)HTTP客户经由同一个套接字接收这个响应消息。TCP连接随后终止。该消息标明所封装的对象是一个HTML文件。客户从中取出这个文件,加以分析后发现其中有10个JPEG对象的引用。
6)给每一个引用到的JPEG对象重复步骡1~4。
浏览器在接收Web页面的同时把它显示给用户。不同的浏览器可能会以略有不同的方式解释(也就是向用户显示)同一个Web页面。HTTP与客户如何解释Web页面没有任何关系,其规范[RFC 1945]和[RFC 2616I]仅仅定义HTTP客户程序和服务器程序之间的通信协议。
上述步骤之所以称为使用非持久连接,原因是每次服务器发出一个对象后,相应的TCP连接就被关闭,也就是说每个连接都没有持续到可用于传送其他对象。每个TCP连接只用于传输一个请求消息和一个响应消息。就上述例子而言,用户每请求一次那个Web页面,就产生11个TCP连接。
在上述步骡中,我们有意不说清楚客户是通过10个串行的TCP连接先后取得所有JPEG对象,还是通过并行的TCP连接同时取得其中某些JPEG对象的。实际上,现今的浏览器允许用户通过配置来控制并行连接的程度。大多数浏览器默认可以打开5到10个并行的TCP连接,每个连接处理一个请求--响应事务。用户要是喜欢,可以把最大并行连接数设为l,那样的话,这10个连接是串行建立的。
继续介绍之前,先估算一下从客户请求基本HTML文件到它收到该文件所经历的时间。为此我们定义往返时间(Round Trip Time,简称RTT),它是一个小分组从客户主机游动到服务器主机再返回客户主机所花的时间。RTT包括分组传播延迟、在中间路由器和交换机上的分组排队延迟以及分组处理延迟。下面考虑用户点击某个超链接时会发生什么。用户的点击导致浏览器发起建立一个与Web服务器的TCP连接,这里涉及·-次"三次握手"过程--首先是客户向服务器发送一个小的冗余消息,接着是服务器向客户确认并响应以一个小的TCP消息,最后是客户向服务器回确认。三次握手过程的前两次结束时,流逝的时间为1个RTT。此时客户把HTTP请求消息发送到TCP连接中,客户接着把三次握手过程最后一次中的确认捎带在包含这个消息的数据分节中发送出去。服务器收到来自TCP连接的请求消息后,把相应的HTML文件发送到TCP连接中,服务器接着把对早先收到的客户请求的确认捎带在包含该HTML文件的数据分节中发送出去。这个HTTP请求顺应交互也花去1个RTT时间。因此,总的响应时间粗略地算是2个RTT加上服务器发送这个HTMI文件的时间。
2.持久连接
非持久连接有些缺点。首先,客户得为每个待请求的对象建立并维护一个新的连接。对于每个这样的连接,TCP得在客户端和服务器端分配TCP缓冲区,并维持TCP变量。对于有可能同时为来自数百个不同客户的请求提供服务的Web服务器来说,这会严重增加其负担。其次,如前所述,每个对象都有2个RTT的响应延长--一个RTT用于建立TCP连接,另-个RTT用于请求和接收对象。最后,每个对象都遭受TCP慢启动,因为每个TCP连接都起始于慢启动阶段。不过并行TCP连接的使用能够部分减轻RTT延迟和慢启动延迟的影响。
在持久连接情况下,服务器在发出响应后让TCP连接继续打开着。同一对客户/服务器之间的后续请求和响应可以通过这个连接发送。整个Web页面(上例中为包含一个基本HTMLL文件和10个图像的页面)自不用说可以通过单个持久TCP连接发送:甚至存放在同一个服务器中的多个Web页面也可以通过单个持久TCP连接发送。通常,HTTP服务器在某个连接闲置一段特定时间后关闭它,而这段时间通常是可以配置的。持久连接分为不带流水线(without pipelining)和带流水线(with pipelining)两个版本。如果是不带流水线的版本,那么客户只在收到前一个请求的响应后才发出新的请求。这种情况下,Web页面所引用的每个对象(上例中的10个图像)都经历1个RTT的延迟,用于请求和接收该对象。与非持久连接2个RTT的延迟相比,不带流水线的持久连接已有所改善,不过带流水线的持久连接还能进一步降低响应延迟。不带流水线版本的另一个缺点是,服务器送出一个对象后开始等待下一个请求,而这个新请求却不能马上到达。这段时间服务器资源便闲置了。
HTTP/1.1的默认模式使用带流水线的持久连接。这种情况下,HTTP客户每碰到一个引用就立即发出一个请求,因而HTTP客户可以一个接一个紧挨着发出各个引用对象的请求。服务器收到这些请求后,也可以一个接一个紧挨着发出各个对象。如果所有的请求和响应都是紧挨着发送的,那么所有引用到的对象一共只经历1个RTT的延迟(而不是像不带流水线的版本那样,每个引用到的对象都各有1个RTT的延迟)。另外,带流水线的持久连接中服务器空等请求的时间比较少。与非持久连接相比,持久连接(不论是否带流水线)除降低了1个RTT的响应延迟外,慢启动延迟也比较小。其原因在于既然各个对象使用同一个TCP连接,服务器发出第一个对象后就不必再以一开始的缓慢速率发送后续对象。相反,服务器可以按照第一个对象发送完毕时的速率开始发送下一个对象。