http persistent Connections 持久化连接

来源:互联网 发布:数据库前端展示 编辑:程序博客网 时间:2024/06/05 14:34

8.1持久连接( Persistent Connections

8.1.1目的

在提出持久连接之前,每获取一个URL都有创建一个单独的TCP连接,不断的加重HTTP服务器的负担并导致网络的拥塞。使用内联的图片或者相关数据常常使得客户端在很短时间内发送众多的请求。问题分析和原型实现的结果的分析已经有了[26][30]HTTP/1.1的实现的执行体验和测算都有很好的结果[39]。实现方式也都被研究过,例如T/TCP[27]

持久HTTP连接具有一下优势:

l         通过打卡和关闭更少的TCP连接,节省了路由和主机的CPU耗时,以及TCP协议控制阻塞使用的主机内存。

l         HTTP请求和响应可以在一个连接的基础上管道化。管道技术允许客户端发送多个请求而不用等待响应,使得TCP连接更加高效地使用从而更少的浪费时间。

l         通过减少TCP打开导致的包的消息来减少网络拥塞,通过给TCP充分的时间来确定网络的拥塞状态。

l         HTTP可以进化的更加优美,因为错误可以被报告而不用直接关闭TCP连接。使用高HTTP版本的客户端可能尝试一些新的功能,但是如果与旧版本服务端通信时在有错误报告后用要重试旧的语义。

HTTP实现应该实现持久连接。

8.1.2概述(Overall Operation

HTTP/1.1和早期HTTP版本最大的不同是持久连接是HTTP连接的默认行为。也就是说,除非有其他的标识,客户端应该假设服务器会持有一个持久连接,即使服务端返回错误的响应。

持久化连接提供了一个机制可以让客户端和服务端给出TCP连接关闭的信号。信号用Connection报头域给出(14.10章)。一旦关闭信号发出,客户端就不能再通过那个连接发送任何请求。

8.1.2.1协商( Negotiation

一个HTTP/1.1服务端可以假定HTTP/1.1客户端会持有一个持久连接,除非发送的请求里有一个Connection报头域里包括连接符号“close”。如果服务器选择在发送响应后立刻关闭连接,它应该发送一个有关闭连接符号的Connection报头域。

HTTP/1.1客户端可以认为一个连接是始终打开的,但决定其保持打开是基于服务端的响应里是否包含一个有关闭连接符的Connection报头。如果客户端不想在请求之后继续持有连接,那么他应该发送一个有关闭连接符号的Connection报头。

如果客户端或者服务端发送了有关闭符号的Connection报头,那个请求就是连接的最后一次使用。

为了保持持久连接,所有经由连接的消息都必须有一个自定义的消息长度(例如关闭连接所没有定义的那个),4.4章对消息长度有描述。

8.1.2.2流水线( Pipelining

支持持久连接的客户端可以“管道”其请求(例如发送多个请求而不用等待每个响应)。服务必须按照接收请求的顺序发送响应。

采取持久化连接和在创建连接后立即管道化的客户端应该在其第一次管道化尝试失败时重试其连接。如果客户端进行这样的重试,它在确定连接是持久的之前不能进行管道化。客户端也必须准备好重发那些请求,如果服务端在没有返回相应响应就关闭了连接的话。

客户端不应该使用non-idempotent方法或者non-idempotent方法序列来管道化请求。否则的话,一个传输连接的过早的中止可能会导致不确定的结果。那些想发送non-idempotent请求的客户端应该等到它接收到前一个请求的响应状态码之后再发送请求。

8.1.3代理服务器(Proxy Servers

代理正确地实现14.10章指出的Connection报头域的属性是非常重要的。

代理服务器必须分别想其连接的客户端和源服务端(或者是另一个代理服务器)通知持久化连接。没一个持久化连接只能应用到一个传输链接上。

代理服务器不能同HTTP/1.0客户端创建一个HTTP/1.1连接。(不过可以看一下RFC 2068

[33]关于一些HTTP/1.0客户端实现的Keep-Alive报头的信息和问题讨论)。

8.1.4实际应用的考虑(Practical Considerations

服务端通常会有一些超时值,一旦超出之后将不再保持不活动的连接。代理服务器可以设一个大一些的值,因为客户端可能有很多连接经由同一个服务器。持久连接没有对服务端或者客户端的超时长度做出要求。

当一个客户端或者服务端认为超时时它应该给传输连接一个完美的中断。客户端和服务端都应该密切监视对方的传输中断,并做出适当的响应。如果客户端或者服务没有察觉对方的关闭可能会导致不必要的网络资源浪费。

客户端、服务端或者代理可能会在任何时候关闭传输连接。例如一个客户端可能已经发送新请求的同时服务端也决定关闭这个无用的连接。从服务的角度看是在关闭失效的连接,但客户端的角度则是正在发送一个请求。

这意味着客户端、服务端和代理应该有能力从异步连接关闭事件中恢复过来。客户端应该重新打开传输连接并且重发失败了请求序列而不用用户交互,只要请求序列是等价的(idempotent)(参看9.1.2章)不等价的方法或者序列不能自动重发,尽管用户代理可能会提交给用户一个重发请求的选择。有程序语义识别的用户代理可以代理用户做出确认。自动重发在第二次请求失败后不应该继续重复。

服务端应该始至少响应每个连接中的一个请求,如果可能的话。服务端不应该在传输响应的中途关闭连接,除非是网络或者客户端错误。

使用持久连接的客户端应该限制其与给定服务端维持的并行性连接数量。一个单用户保持的域服务器或者代理的连接不应该超过2个。代理应该使用最多2*N个与服务或者代理的连接,这里N是并发的活跃用户的数目。这些指导意见是用来改善HTTP响应时间并避免拥塞。

8.2 消息传输需求Message Transmission Requirements

8.2.1持久连接流控制 Persistent Connections and Flow Control

HTTP/1.1服务端应该保存一个持久连接并使用TCP的流控制机制来解决临时性的重载,而不是终止那些客户可能会重试的连接。后者会加剧网络的拥塞。

8.2.2监控连接中的错误信息Monitoring Connections for Error Status Messages

HTTP/1.1 (或者以后的)客户端在发送消息体时应该监控网络以便在其传输请求是发现错误状态。如果客户端发现了错误的状态,它应该立刻中止消息体的传输。如果消息体是用“”编码的方式传输,一个零长度块和空trailer可以用来提前标识消息的结束。如果消息体已经加上了Content-Length报头,客户端应该关闭连接。

8.2.3状态100的使用 Use of the 100 (Continue) Status

100(继续)状态(参看10.1.1章)的目的是允许一个正在发送有请求主体的请求消息的客户端在发送消息主体之前确定源服务是否接受该请求(取决于请求报头)。在一些情况下,如果服务端不用查看主体就拒绝消息而客户端继续发送消息主体是不合适也是很非常浪费时间的。

HTTP/1.1客户端的要求:

l         如果客户端在发送请求主体前会等待一个100Continue)响应,它必须发送一个有“100-continue”预期的请求报头。

l         客户端不能发送一个有“100-continue”请求报头域的请求,如果它不打算发送请求主体。

由于有老版本的实现,协议允许不明确的状态,这样客户端可以发送“Expect: 100-continue”而不用收到417(期望失败)或者100(继续)状态。因此,当客户端发送一个报头域给源服务端(或许经由代理)但未收到100Continue)状态时,客户端不应该无限等待下去。

HTTP/1.1源服务端的要求:

l         当接收到一个包含带有“100-continue”期望报头域的请求后,源服务端必须要么返回100Continue)状态继续读取输入流,要么给出一个最终响应代码。服务端在发出100Continue)响应之前不能等待请求主体。如果给出的是最终状态码,服务端可以关闭传输连接,也可以继续读取并丢弃请求的剩余部分。服务端不能执行请求的方法,如果它返回的是一个最终状态码。

l         一个源服务端不应该在请求信息里没有“100-contiune”期望报头域的情况下返回100Continue)响应,如果请求来自HTTP/1.0服务器那么它也不能返回100状态。这个规则有一个例外就是:为了兼容草案2068,服务端可以发送一个100状态响应给一个,没有包含有“100-continue”期望请求报头域的HTTP1.1PUT或者POST请求。这个例外的目的是为了最小化客户端处理未声明的等待100状态造成的延迟,这只能应用于HTTP1.1请求,不针对其他HTTP版本。

l         一个源服务应该不再发送一个100响应,如果它已经接收到相应请求的部分或者全部的请求实体。

l         一个发送过100响应的源服务端必须在请求实体接收并处理后发送一个最终状态代码,除非它提前中止了传输连接。

l         如果源服务接收到一个不包括含有“100-continue”期望值的期望请求报头域,请求包含一个请求实体,并且服务在从传输连接中读取全部请求体之前发送了最终状态码,那么服务端不应该关闭传输连接知道它已经读取了全部请求,或者知道客户端关闭了连接。否则的话,客户端可能没有可靠地接收响应信息。虽然如此,这个要求不是妨碍服务端防止拒绝服务式攻击或者有严重缺陷的客户端实现。

HTTP/1.1代理的要求:

l         如果代理接收到一个包含有“100-continue”期望值的期望请求报头域的请求,并且代理知道下一环服务端是HTTP/1.1或者更高版本,或者不知道下一环服务器HTTTP版本,它必须传递请求,包括期望报头域。

l         如果代理知道下一环服务端是HTTP1.0或者更低的版本,它必须不转寄请求,并且要返回一个417(期望失败)状态。

l         代理应该缓存最近引用的下一环服务器的HTTP版本号。

l         代理必须不能转寄100响应,如果请求消息来自于HTTP/1.0(或者更早的版本)客户端并且不包含有“100-continue”期望值的期望请求报头域。这个要求不考虑推进1xx响应的一般规则。

8.2.4服务端过早关闭连接后的客户端行为 Client Behavior if Server Prematurely Closes Connection

如果一个HTTP/1.1客户端发送了一个包含请求实体的请求,但是请求不包含有100-continue”期望值的期望请求报头域,并且如果客户端不是直接连接到一个HTTP/1.1源服务器上,并且如果客户端发现在从服务端接收到任何状态之前连接已经关闭,客户端应该重发这个请求。如果客户端不想重发这个请求,它也可以使用接下来的“binary exponential backoff”机制来确定获取一个可好的响应:

1.          创建一个到服务端的新连接

2.          传输请求报头域

3.          用估计服务的反馈时间(例如基于它创建连接所用的时间),或者一个5秒的常值来初始化一个变量R

4.          计算 T = R*(2**N),N是上一次重试的次数。

5.          等待到从服务返回一个错误响应,或者T秒(两者最先的那个)。

6.          如果没有错误返回,在T秒后传输请求实体。

7.          如果客户端发现连接提前关闭了,返回到步骤1知道请求被接收、接收到错误的响应或者用户不耐烦并中止重试过程。

如果在任一步接收到一个错误的状态,客户端

l         不应该继续并且

l         应该关闭连接,如果它没有完成请求信息的发送。

原创粉丝点击