Skip to main content

5. 连接关闭 (Connection Closure)

一旦建立, HTTP/3 连接可以在关闭之前用于许多请求和响应。连接关闭可以以几种不同的方式发生。

5.1. 空闲连接 (Idle Connections)

每个 QUIC 端点在握手期间声明一个空闲超时。如果 QUIC 连接保持空闲 (未接收数据包) 的时间超过此持续时间, 对等方将假定连接已关闭。HTTP/3 实现需要为新请求打开新的 HTTP/3 连接, 如果现有连接已空闲时间超过 QUIC 握手期间协商的空闲超时, 并且如果接近空闲超时则应当这样做; 参见 [QUIC-TRANSPORT] 的第 10.1 节。

预期 HTTP 客户端会请求传输在有请求或服务器推送的响应未完成时保持连接打开, 如 [QUIC-TRANSPORT] 的第 10.1.2 节中所述。如果客户端不期望来自服务器的响应, 允许空闲连接超时比花费精力维护可能不需要的连接更可取。网关可以维护连接以预期需求, 而不是承担与服务器建立连接的延迟成本。服务器不应当主动保持连接打开。

5.2. 连接关闭 (Connection Shutdown)

即使连接不空闲, 任一端点都可以决定停止使用连接并发起优雅的连接关闭。端点通过发送 GOAWAY 帧来发起 HTTP/3 连接的优雅关闭。GOAWAY 帧包含一个标识符, 该标识符向接收方指示在此连接中已处理或可能已处理的请求或推送的范围。服务器发送客户端发起的双向流 ID; 客户端发送推送 ID。具有指示标识符或更大标识符的请求或推送被 GOAWAY 的发送方拒绝 (第 4.1.1 节)。如果未处理请求或推送, 此标识符可以为零。

GOAWAY 帧中的信息使客户端和服务器能够就在 HTTP/3 连接关闭之前接受了哪些请求或推送达成一致。在发送 GOAWAY 帧后, 端点应当明确取消 (参见第 4.1.1 节和第 7.2.3 节) 具有大于或等于指示标识符的任何请求或推送, 以便清理受影响流的传输状态。随着更多请求或推送到达, 端点应当继续这样做。

端点禁止在从对等方收到 GOAWAY 帧后发起新请求或承诺新推送。客户端可以建立新连接以发送其他请求。

某些请求或推送可能已经在传输中:

  • 在收到 GOAWAY 帧后, 如果客户端已经发送了流 ID 大于或等于 GOAWAY 帧中包含的标识符的请求, 则不会处理这些请求。客户端可以在不同的 HTTP 连接上安全地重试未处理的请求。无法重试请求的客户端会在服务器关闭连接时丢失所有正在进行的请求。

    流 ID 小于服务器的 GOAWAY 帧中的流 ID 的请求可能已被处理; 在收到响应, 单独重置流, 收到另一个流 ID 低于所讨论请求的 GOAWAY, 或连接终止之前, 无法知道它们的状态。

    如果这些请求未被处理, 服务器可以拒绝指示 ID 以下流上的个别请求。

  • 如果服务器在承诺推送 ID 大于或等于 GOAWAY 帧中包含的标识符后接收到 GOAWAY 帧, 则不会接受这些推送。

当提前知道连接关闭时, 服务器应当发送 GOAWAY 帧, 即使提前通知很小, 以便远程对等方可以知道请求是否已被部分处理。例如, 如果 HTTP 客户端在服务器关闭 QUIC 连接的同时发送 POST, 如果服务器不发送 GOAWAY 帧来指示它可能作用于哪些流, 则客户端无法知道服务器是否开始处理该 POST 请求。

端点可以发送指示不同标识符的多个 GOAWAY 帧, 但每个帧中的标识符禁止大于任何先前帧中的标识符, 因为客户端可能已经在另一个 HTTP 连接上重试了未处理的请求。接收包含比先前接收的更大标识符的 GOAWAY 必须被视为类型为 H3_ID_ERROR 的连接错误。

尝试优雅关闭连接的端点可以发送值设置为最大可能值 (对于服务器为 2^62-4, 对于客户端为 2^62-1) 的 GOAWAY 帧。这确保对等方停止创建新请求或推送。在允许任何正在进行的请求或推送到达的时间之后, 端点可以发送另一个 GOAWAY 帧, 指示它可能在连接结束之前接受哪些请求或推送。这确保可以干净地关闭连接而不会丢失请求。

客户端在它发送的 GOAWAY 中为推送 ID 字段选择的值具有更大的灵活性。值 2^62-1 表示服务器可以继续履行已承诺的推送。较小的值表示客户端将拒绝推送 ID 大于或等于此值的推送。与服务器一样, 客户端可以发送后续的 GOAWAY 帧, 只要指定的推送 ID 不大于任何先前发送的值。

即使 GOAWAY 指示在收到后不会处理或接受给定的请求或推送, 底层传输资源仍然存在。发起这些请求的端点可以取消它们以清理传输状态。

一旦所有已接受的请求和推送都已处理, 端点可以允许连接变为空闲, 或者可以发起连接的立即关闭。完成优雅关闭的端点应当在关闭连接时使用 H3_NO_ERROR 错误码。

如果客户端已使用所有可用的双向流 ID 用于请求, 则服务器无需发送 GOAWAY 帧, 因为客户端无法发出进一步的请求。

5.3. 立即应用关闭 (Immediate Application Closure)

HTTP/3 实现可以随时立即关闭 QUIC 连接。这会导致向对等方发送 QUIC CONNECTION_CLOSE 帧, 指示应用层已终止连接。此帧中的应用错误码向对等方指示连接关闭的原因。有关关闭 HTTP/3 连接时可以使用的错误码, 请参见第 8 节。

在关闭连接之前, 可以发送 GOAWAY 帧以允许客户端重试某些请求。将 GOAWAY 帧包含在与 QUIC CONNECTION_CLOSE 帧相同的数据包中可提高客户端接收该帧的可能性。

如果有未明确关闭的打开流, 则在连接关闭时它们会被隐式关闭; 参见 [QUIC-TRANSPORT] 的第 10.2 节。

5.4. 传输关闭 (Transport Closure)

由于各种原因, QUIC 传输可能向应用层指示连接已终止。这可能是由于对等方的显式关闭、传输级错误或中断连接的网络拓扑变化。

如果连接在没有 GOAWAY 帧的情况下终止, 客户端必须假定发送的任何请求 (无论是全部还是部分) 可能已被处理。