【问题标题】:How to handle HTTP/2 GOAWAY with HttpClient?如何使用 HttpClient 处理 HTTP/2 GOAWAY?
【发布时间】:2022-03-23 03:43:00
【问题描述】:

我正在尝试每隔几分钟连续向 REST API 发送 GET 和 POST 请求。问题是,恰好在 1000 个请求之后,我收到了一个 GOAWAY 帧(和一个 IOException):

GOAWAY 帧(类型=0x7)用于启动关闭连接或发出严重错误情况的信号。
§ 6.8, RFC 7540


我进行了大量研究,发现不仅 1000 个请求 nginx's default maximum、Cloudfront (related Chromium issue) 和 Discord 也表现出相同的行为。

我尝试使用默认 HTTP/2 配置的本地 nginx 服务器重现此问题:

服务器 { 听 443 http2 ssl; http2_max_requests 1000; ... }
var client = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_2)
        .build();

for (var i = 0; i < 1100; i++) {
    var url = URI.create(String.format("https://localhost/images/test%d.jpg", i));

    var request = HttpRequest.newBuilder().uri(url).build();

    client.send(request, HttpResponse.BodyHandlers.discarding());
    System.out.printf("Image %d processed%n", i);
}

在大约 1000 个请求之后,我得到了一个 GOAWAY 错误,正如预期的那样:

... 图片 998 已处理 线程“主”java.io.IOException 中的异常:/127.0.0.1:49259:收到 GOAWAY

我的第一个想法是检查异常消息是否包含字符串"GOAWAY",然后相应地重试请求:

try {
    client.send(request, HttpResponse.BodyHandlers.discarding());
} catch (IOException e) {
    if (e.getMessage().contains("GOAWAY")) {
        client.send(request, HttpResponse.BodyHandlers.discarding());
    } else throw e;
}

我对这种方法的问题是字符串比较似乎很脆弱。此外,由于我所拥有的只是带有消息的 IOException,因此我无法区分带有真正错误代码的 GOAWAY 帧(在这种情况下,我可能应该停止发送请求)和带有 NO_ERROR 的帧(在这种情况下,我可能会重试请求)。

我应该如何正确处理/处理GOAWAY 错误(除了改用HTTP/1.1)?

【问题讨论】:

    标签: java http2 java-11 java-http-client


    【解决方案1】:

    服务器有权随时以任何理由关闭连接。

    在 HTTP/2 GOAWAY 帧中指示服务器处理的最后一个流是什么,因此客户端可以知道当连接关闭时需要重新发送哪个流。

    很遗憾,lastStreamId 没有出现在 java.net.http.HttpClient 中,因此无法知道它并采取适当的措施。

    您的替代方案可能是使用支持显示lastStreamId 的其他客户端,或使用较低级别的HTTP/2 客户端,您可以在其中使用GOAWAY 框架,从而访问lastStreamId

    [免责声明,我是 Jetty HTTP/2 的实施者]
    Jetty 支持较低级别的 HTTP/2 客户端,您可以将其用于您的用例 - 您可能想尝试一下。 您可以找到如何使用 Jetty 的 HTTP2Client here 的示例。

    【讨论】:

    • 流是否以任何特定顺序处理?例如如果 lastStreamId=2
    • 流处理顺序未定义。实现可以选择最适合他们的方法。
    猜你喜欢
    • 2021-03-21
    • 2021-07-05
    • 2017-05-26
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 2013-10-08
    • 2022-01-16
    • 2020-01-06
    相关资源
    最近更新 更多