如何使用Java的HttpClient在慢速流响应主体上超时

当我需要以流方式处理响应时,我应该如何处理使用 Java 11 中包含的 HTTP 客户端挂起发送 HTTP 响应正文的服务器?

已经阅读文档,我知道,这是可以设置在连接超时和在请求超时:

HttpClient httpClient = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(2))
        .build();

HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("http://example.com"))
        .timeout(Duration.ofSeconds(5))
        .build();

HttpResponse<Stream<String>> httpResponse = httpClient
        .send(httpRequest, HttpResponse.BodyHandlers.ofLines());

Stream<String> responseLineStream = httpResponse.body();
responseLineStream.count();

在上面的代码中:

  • 如果在 2 秒内无法建立连接,则会抛出超时异常。
  • 如果在 5 秒内没有收到响应,则会抛出超时异常。通过实验,定时器在连接建立后启动,对于这种类型BodyHandler,当收到状态行和报头时,就认为收到了响应。

这意味着当代码执行时,在 7 秒内要么抛出异常,要么到达最后一行。但是,最后一行不受任何超时的限制。如果服务器停止发送响应正文,最后一行将永远阻塞。

在这种情况下,如何防止最后一行挂起?

回答

我的猜测是留给流的消费者,因为这是处理逻辑的一部分,所以身体处理仍然可以用以下方式处理CompletableFuture

HttpResponse<Stream<String>> httpResponse = httpClient.send(httpRequest,
                                                            HttpResponse.BodyHandlers.ofLines());

Stream<String> responseLineStream = httpResponse.body();
CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> responseLineStream.count());
long count = future.get(3, TimeUnit.SECONDS);

或者只是简单地Future由 Java 执行Executor


以上是如何使用Java的HttpClient在慢速流响应主体上超时的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>