为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 HttpClient 处理 HTTP/2 GOAWAY?

如何使用 HttpClient 处理 HTTP/2 GOAWAY?

忽然笑 2022-07-27 09:33:36
我正在尝试每隔几分钟连续向 REST API 发送 GET 和 POST 请求。问题是,恰好在 1000 个请求之后,我收到一个GOAWAY框架(和一个IOException):GOAWAY 帧(类型=0x7)用于启动连接关闭或发出严重错误情况的信号。§ 6.8,RFC 7540我做了一些研究,发现不仅 1000 个请求是nginx 的默认最大值,Cloudfront(相关 Chromium 问题)和 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)?
查看完整描述

1 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

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

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

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

lastStreamId您的替代方法可能是GOAWAY使用其他支持显示lastStreamId.

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


查看完整回答
反对 回复 2022-07-27
  • 1 回答
  • 0 关注
  • 633 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号