8. Connections (连接)
8.1 Persistent Connections (持久连接)
8.1.1 Purpose (目的)
在持久连接之前,需要建立单独的 TCP 连接来获取每个 URL,这增加了 HTTP 服务器的负载并导致互联网拥塞。内联图像和其他关联数据的使用通常要求客户端在短时间内向同一服务器发出多个请求。对这些性能问题的分析和原型实现的结果可用 [26] [30]。实际 HTTP/1.1 (RFC 2068) 实现的实施经验和测量显示了良好的结果 [39]。还探索了替代方案,例如 T/TCP [27]。
持久 HTTP 连接具有许多优势:
-
通过打开和关闭更少的 TCP 连接,可以在路由器和主机(客户端、服务器、代理、网关、隧道或缓存)中节省 CPU 时间,并且可以在主机中节省用于 TCP 协议控制块的内存。
-
HTTP 请求和响应可以在连接上进行流水线处理 (pipelining)。流水线允许客户端发出多个请求而无需等待每个响应,允许更有效地使用单个 TCP 连接,且经过的时间大大缩短。
-
通过减少由 TCP 打开引起的数据包数量,以及通过允许 TCP 有足够的时间来确定网络的拥塞状态,减少了网络拥塞。
-
后续请求的延迟减少,因为不需要花费时间在 TCP 的连接打开握手上。
-
HTTP 可以更优雅地演进,因为可以报告错误而无需承受关闭 TCP 连接的代价。使用未来版本 HTTP 的客户端可能会乐观地尝试新功能,但如果与较旧的服务器通信,则在报告错误后使用旧语义重试。
HTTP 实现应该 (SHOULD) 实现持久连接。
8.1.2 Overall Operation (总体操作)
HTTP/1.1 与早期版本的 HTTP 之间的一个重大区别是,持久连接是任何 HTTP 连接的默认行为。也就是说,除非另有说明,客户端应该 (SHOULD) 假定服务器将维护持久连接,即使在来自服务器的错误响应之后也是如此。
持久连接为 HTTP/1.0 和 HTTP/1.1 应用程序提供了一种机制来表示连接关闭。这种信号是通过 Connection 头字段(第 14.10 节)提供的。一旦发送或接收到 "close" 连接选项,该连接就不得 (MUST NOT) 被视为 "持久"。
HTTP/1.1 应用程序不得 (MUST NOT) 与 HTTP/1.0 客户端建立持久连接。
8.1.3 Proxy Servers (代理服务器)
特别重要的是,代理正确实现 Connection 头字段的属性,如第 14.10 节所述。
代理服务器必须 (MUST) 向客户端和上游服务器分别发出持久连接信号。每个持久连接仅适用于一个传输链路。
8.1.4 Practical Considerations (实际考虑)
服务器通常会有一些超时值,超过该值它将不再维护非活动连接。代理服务器可能会使此超时值更高,因为客户端可能已经在现有连接上建立了连接。使用持久连接并不要求服务器无限期地维护连接。实际上,服务器可以 (MAY) 随时关闭连接,但应该 (SHOULD) 优雅地这样做。
客户端、服务器和代理必须 (MUST) 能够从异步关闭事件中恢复。客户端软件应该 (SHOULD) 在没有用户交互的情况下重新打开传输连接并重传中止的请求序列,只要请求序列是幂等的(参见第 9.1.2 节)。非幂等方法或序列禁止 (MUST NOT) 自动重试,尽管用户代理可以 (MAY) 为用户提供人工重试请求的手段。
服务器应该 (SHOULD) 始终响应至少一个请求,然后再关闭连接。服务器不应该 (SHOULD NOT) 在传输响应的中间关闭连接,除非网络或客户端故障怀疑。
希望发送持久连接的客户端可以 (MAY) "流水线化" 它们的请求(即,在等待每个响应到达之前发送多个请求)。服务器必须 (MUST) 按照接收相应请求的顺序发送其响应。
8.2 Message Transmission Requirements (消息传输要求)
8.2.1 Persistent Connections and Flow Control (持久连接和流量控制)
HTTP/1.1 服务器应该 (SHOULD) 为自己维护持久连接,尽管可能。但是,如果它们确实维护持久连接,那么对于给定的 TCP 连接,它们应该 (SHOULD) 使用该连接至少有一个请求-响应序列。
8.2.2 Monitoring Connections for Error Status Messages (监控连接的错误状态消息)
HTTP/1.1(或更高版本)客户端发送请求时(尤其是对身份验证至关重要或具有不安全方法的请求),如果传输连接关闭或在客户端完成发送请求消息之前重置,则必须 (MUST) 重新发送请求。
8.2.3 Use of the 100 (Continue) Status (使用100 (Continue) 状态)
100 (Continue) 状态(参见第 10.1.1 节)的目的是允许发送请求消息主体的客户端确定源服务器是否愿意在客户端发送请求主体之前接受请求(基于请求头)。在某些情况下,如果服务器拒绝消息而不读取主体,则客户端发送主体可能不恰当或效率低下。
包含请求消息主体的 HTTP/1.1(或更高版本)客户端的要求:
-
如果客户端将在合理的时间量内等待 100 (Continue) 响应,则客户端必须 (MUST) 发送 Expect 请求头字段(第 14.20 节),其中包含 "100-continue" 期望值。
-
客户端禁止 (MUST NOT) 向 HTTP/1.0(或更早)服务器发送带有 "100-continue" 期望值的 Expect 请求头字段。
-
发送 100 (Continue) 期望但未接收到 100 (Continue) 状态的客户端应该 (SHOULD) 等待一段不确定的时间;客户端随后可以 (MAY) 超时并发送请求(使用其消息主体)或关闭连接。
从 HTTP/1.1(或更高版本)客户端接收请求的 HTTP/1.1(或更高版本)源服务器的要求:
-
收到包含 Expect 请求头字段且包含 "100-continue" 期望值的请求后,源服务器必须 (MUST) 以 100 (Continue) 状态响应,如果它打算读取和处理请求消息主体,或者以最终状态码响应。源服务器不得 (MUST NOT) 等待请求主体在发送 100 (Continue) 响应之前。如果它以最终状态码响应,它可以 (MAY) 关闭传输连接或它可以 (MAY) 继续读取和丢弃请求的其余部分。它不得 (MUST NOT) 执行请求的方法(如果它打算拒绝请求)。
-
源服务器应该 (SHOULD) 在从 HTTP/1.1(或更高版本)客户端接收请求头之后立即响应 100 (Continue),除非请求包含 Expect 请求头字段,其中包含不包含 "100-continue" 的期望值。
8.2.4 Client Behavior if Server Prematurely Closes Connection (如果服务器过早关闭连接,客户端行为)
如果 HTTP/1.1 客户端在接收响应之前发送 HTTP 请求,并且接收到指示服务器不希望在该连接上接收更多请求的响应,客户端应该 (SHOULD) 重新发送请求,提供它可以确定序列中的所有请求是幂等的(参见第 9.1.2 节)。
非幂等方法或序列禁止 (MUST NOT) 自动重传,但用户代理可以 (MAY) 提供人工重试此序列的手段。在自动重传请求之前,如果之前的请求序列无法全部完成,客户端应该 (SHOULD) 确认其当前状态与预期状态的任何差异。