如何在 Java HTTP 客户机中设置套接字超时

2022-09-04 02:58:30

我们希望将所有apache-httpclient-4.x代码迁移到java-http-client代码中,以减少依赖性。在迁移它们时,我在java 11下遇到了以下问题:

如何在Java HTTP客户端中设置套接字超时?

使用apache-httpclient-4.x,我们可以设置连接超时和套接字超时,如下所示:

DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);

使用java-http-client,我只能像这样设置连接超时:

HttpClient httpClient = HttpClient.newBuilder()
                                  .connectTimeout(Duration.ofSeconds(5))
                                  .build()

但是我发现没有办法设置套接字超时。将来有什么方法或一个悬而未决的问题来支持它吗?


答案 1

您可以通过超时方法在级别指定它:HttpRequest.Builder

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

HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(URI.create("..."))
                .timeout(Duration.ofSeconds(5)) //this
                .build();


httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

如果已成功连接,但无法在所需的时间量接收响应,则将抛出(与未获得成功连接时将引发的响应相反)。java.net.http.HttpTimeoutException: request timed outjava.net.http.HttpConnectTimeoutException: HTTP connect timed out


答案 2

似乎没有办法在 Java Http 客户端上指定数据包流的超时(套接字超时)。

我在OpenJDK上发现了一个增强请求,它似乎涵盖了这种可能性 - https://bugs.openjdk.org/browse/JDK-8258397

链接中的内容

HttpClient允许您设置连接超时(HttpClient.Builder)和请求超时(HttpRequest.Builder)。但是,一旦读取响应标头,请求超时将被取消。目前没有超时覆盖身体的接收。

调用方的一种可能性是使用ComppletableFuture API(get/join将接受超时,或者可以调用CF::orTimeout)。IIRC - 在这种情况下,调用方仍有责任取消请求。我们可能想要重新审视并改变这种可能性。这里的缺点是我们的一些BodyHandlers(ofPublisher,ofInputStream)会立即返回 - 所以CF API在这种情况下没有帮助。这可能是一件好事(也可能不是)。

另一种可能性是在HttpRequest.Builder上添加一个正文超时。这将涵盖所有情况 - 但是如果调用方没有足够快地读取正文,我们真的想在InputStream或publisher的情况下超时吗?


推荐