首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >闪烁的HttpClient有时抛出IOException

闪烁的HttpClient有时抛出IOException
EN

Stack Overflow用户
提问于 2022-10-26 23:05:51
回答 1查看 54关注 0票数 0

我在Java19 (Temurin)下使用java.net.http.HttpClient.newHttpClient(),并在同一个实例上执行来自不同踏板的sendAsync(...)请求。我假设这是可以的,正如javadoc所述:

一旦建成,HttpClient是不可变的.

但是,有些请求失败了,因为:

代码语言:javascript
运行
复制
java.io.IOException: HTTP/1.1 header parser received no bytes

奇怪的是,这取决于我请求的速度:

  • 每5秒请求一次:失败30%
  • 每3秒请求一次: 0%失败

我已经为它写了一个测试:

代码语言:javascript
运行
复制
private final HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://..."))
    .setHeader("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofByteArray("[]".getBytes()))
    .build();

@ParameterizedTest
@ValueSource(ints = {3, 5})
void httpClientTest(int intervalSeconds) throws Exception {
    HttpClient httpClient = HttpClient.newHttpClient();

    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
}

我已经尝试过以下几种方法:

  • 在命令行上对curl执行同样的操作。无论我尝试什么时间间隔,都不会有请求失败。所以这可能不是服务器的问题。
  • 并行运行测试多次。尽管如此,5秒间隔仍然失败(然后多次并行)。所以这可能不是服务器的问题。
  • 为每个请求创建一个HttpClient.newHttpClient()。无论间隔多久,任何请求都不会失败。因此,这可能不是服务器的问题,而是HttpClient的内部状态(尽管它声称是不可变的?)。

您知道我可以做什么,而不需要为每个请求创建一个新的HttpClient吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-28 09:43:36

下面是记录的答案:java.net.HttpClient的默认HTTP/1.1 keepAlive时间很长,比通常配置的服务器要长。这通常导致服务器在客户机之前关闭空闲的HTTP/1.1连接。如果服务器在客户端试图重用连接的同时关闭连接,则可能引发一些IOException

如果这种异常被观察得太频繁,应用程序应该考虑将客户机中的默认keepAlive时间调整为比其连接到的服务器所使用的值更短的值。HttpClient HTTP/1.1 keepAlive时间的默认值可以是在命令行上指定 with:-Djdk.httpclient.keepalive.timeout=duration-in-seconds

因此,例如,如果服务器配置为keepAlive时间为5s,则可以考虑在客户端的java命令行上提供-Djdk.httpclient.keepalive.timeout=3-Djdk.httpclient.keepalive.timeout=4

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74215117

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档