我试图每隔几分钟就不断将GET和POST请求发送到REST API。问题是,在恰好有1000个请求之后,我收到了 GOAWAY
框架(和IOException
):
我做了相当多的研究,发现不仅1000个请求nginx's default maximum,Cloudfront(related Chromium issue)和Discord也表现出相同的行为。
我尝试使用具有默认HTTP/2配置的本地Nginx服务器重现此问题:
server { listen 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
错误:... Image 998 processed Exception in thread "main" java.io.IOException: /127.0.0.1:49259: GOAWAY received
My first thought would be to check if the exception message contains the string "GOAWAY"
and then retry the request accordingly:
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之外)? 最佳答案
服务器有权以任何理由随时关闭连接。
在HTTP/2 GOAWAY
帧中,指示了服务器最后处理的流是什么,因此客户端可以知道关闭连接后需要重新发送什么流。
不幸的是,lastStreamId
没有出现在java.net.http.HttpClient
中,因此没有办法知道它并采取适当的措施。
您的替代方法是使用其他支持lastStreamId
的客户端,或者使用较低级别的HTTP/2客户端,在该客户端上您将可以使用GOAWAY
框架,从而访问lastStreamId
。
[免责声明,我是Jetty HTTP/2实现者]
Jetty支持可用于您的用例的较低级别的HTTP/2客户端-您可能需要尝试一下。
您可以找到有关如何使用Jetty的HTTP2Client
here的示例。
关于java - 如何使用HttpClient处理HTTP/2 GOAWAY?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55087292/