Keep-alive首部只会对这条离开客户端的TCP链路产生影响;如果一台客户端正在与一台服务器对话,客户端可以发送一个Connection:Keep-alive首部来告诉服务器,它希望保持持久连接;如果服务器支持Keep-alive,就在响应中存在一个Connection:Keep-alive首部。
1. Connection首部和盲中继
在代理中,它们不理解Connection首部,而且不理解在沿着转发链路将其发送出去之前,应该将该首部删除,不会对Connection首部进行特殊处理。
假设一个Web应用程序正通过一个盲中继的哑代理与Web服务器进行通信。如下所示
(a). Web应用程序向代理发送了一条报文,其中包含了Connection: Keep-alive首部;客户端请求建立一条Keep-alive连接,需要等待响应,以确定对象是否可它对Keep-alive信道的请求。
(b). 哑代理收到了这个请求,但它并不理解Connection首部(只是将其作为一个扩展首部对待),因此,将报文一字不漏发送给服务器。但Connection首部是个逐跳首部,只适用于单条传输链路,报文在传输到代理时,应该得到处理,不应该沿着传输向下传输。
(c).在服务器端收到这条请求后,会以为是代理希望进行Keep-alive对话。对于服务器来说这没有问题,它同意了对话,并回送一个Connection:Keep-alive响应首部。因此,服务器会认为与代理进行Keep-alive对话,遵循Keep-alive规则。但代理对此一无所知。
(d). 哑代理将服务器的响应报文回送给客户端,并将响应Connection:Keep-alive首部(不处理)一起发送回去。
(e). 客户端收到这个首部后,就会认为服务器同意Keep-alive对话。实际情况是:服务器与代理建立Keep-alive对话,但代理(不会产生请求)一无所知;客户端以为已经与服务器建立了对话,其实这个链路在代理与服务器之间建立。当客户端继续发送请求时,请求被忽略,因为同一连接(数据必须由代理--源端点 产生)上会有其他请求。
后果:这种错误的通信方式会使客户端处于挂起状态,直到客户端或服务器将连接超时,并将其关闭。
2. 代理和逐跳首部
为了避免上述问题,现代代理都不转发Connection首部和所有Connection值中的首部。
插入Proxy-Connection
在不要求所有Web应用程序支持高版本HTTP(HTTP/1.1以上),网景提出一个对盲中继问题的变通方法。虽然解决在客户端后面紧跟着一个盲中继所带来的问题,但并没有解决所有其他情况下的问题。
问题:是由哑代理盲目地转发Connection:Keep-alive之类的逐跳首部惹出的麻烦。逐跳首部只与一条特定的连接有关,不能被转发。当下游服务器将转发来的Connection首部作为来自代理(源)自身请求时,就会引起问题。
网景的变通方法是:浏览器会向代理发送非标准的Proxy-Connection扩展首部,而不是官方支持的Connection首部。如果是盲中继,它会将无意的Proxy-Connection首部转发给服务器,服务器会忽略此首部,不会产生任何问题。
如果是一个聪明的代理(能够理解持久连接的握手动作),会将Connection首部取代Proxy-Connection首部,后将其发送给服务器。
如果只有一个代理时,可以用这种方法解决这个问题,但在哑代理任意一侧有一个聪明代理时,这个问题会再次露头。
HTTTP/1.1持久连接
HTTP/1.1逐渐停止了对Keep-alive连接的支持,用一种名为持久连接的改进型来取代它。
在所有的连接中默认情况是持久连接的,会在事务处理结束之后,或承诺时间之内将其关闭。要显式地关闭这个持久连接,需要在报文中加入Connection: close首部。而在之前HTTP版本中,Keep-alive连接是可选的,要不就不支持。
HTTP/1.1客户端收到响应后,除非报文中存在Connection:close首部,不然HTTP/1.1持久连接将维持打开状态。但是,客户端或服务器依然可以随时关闭这个持久连接,即使没有接到报文或报文中没有Connection:colse首部。
持久连接的限制和规则
- 发送了Connection: close请求首部之后,客户端将无法在这种连接发送请求(代理将忽略,除非再次握手)。
- 建立持久连接的条件: 报文的实体主体部分的长度和相应的Content-Length值一致,代理或服务器才能知道一个事务的结束和另一个事务的开始。
- 不建议HTTP/1.1服务器与HTTP/1.0客户端建立持久连接,实际还存在这种情况。
- HTTP/1.1设备可以在任意时刻关闭连接。
- 在异常的关闭连接后,HTTP/1.1应用程序能够从关闭中恢复出来,只要不存在可能的累积起来的副作用。
- 一个客户端对任何服务器或代理最多只能维护两条连接。