【问题标题】:Difference between okhttp client timeouts and apache timeoutsokhttp 客户端超时和 apache 超时之间的区别
【发布时间】:2021-08-18 13:42:57
【问题描述】:
以前我用的是apache的http客户端。我有以下设置:
- 连接请求超时
- 连接超时
- 读取/套接字超时
- 连接池大小
我正在迁移到 OkHttp 客户端,它有不同的超时:
- 连接超时
- 通话超时
- 读取超时
- 写入超时
- max-idle-connections(连接池设置)
- keep-alive-duration-minutes(连接池设置)
它们如何相互映射?
问候,
瑞克
【问题讨论】:
标签:
java
spring-boot
okhttp
apache-httpcomponents
【解决方案1】:
摘自Baeldung写的优秀文章,这里有一些细节:
-
连接超时:
连接超时定义了一个我们的客户端应该与目标主机建立连接的时间段。
默认情况下,对于OkHttpClient,此超时设置为 10 秒。
但是,我们可以使用OkHttpClient.Builder#connectTimeout 方法轻松更改其值。零值表示根本没有超时。
现在让我们看看如何构建和使用带有自定义连接超时的OkHttpClient:
@Test
public void whenConnectTimeoutExceeded_thenSocketTimeoutException() {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.MILLISECONDS)
.build();
Request request = new Request.Builder()
.url("http://203.0.113.1") // non routable address
.build();
Throwable thrown = catchThrowable(() -> client.newCall(request).execute());
assertThat(thrown).isInstanceOf(SocketTimeoutException.class);
}
上面的例子显示,当连接尝试超过配置的超时时间时,客户端会抛出一个SocketTimeoutException。
-
通话超时:
调用超时与我们已经讨论过的连接、读取和写入超时有点不同。 它定义了一个完整的 HTTP 调用的时间限制。这包括解析 DNS、连接、写入请求正文、服务器处理以及读取响应正文。与其他超时不同,它的默认值设置为零,这意味着没有超时。但当然,我们可以使用OkHttpClient.Builder#callTimeout 方法配置自定义值。
我们来看一个实际的使用例子:
@Test
public void whenCallTimeoutExceeded_thenInterruptedIOException() {
OkHttpClient client = new OkHttpClient.Builder()
.callTimeout(1, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url("https://httpbin.org/delay/2")
.build();
Throwable thrown = catchThrowable(() -> client.newCall(request).execute());
assertThat(thrown).isInstanceOf(InterruptedIOException.class);
}
-
读取超时:
从客户端和目标主机之间的连接成功建立的那一刻起,就会应用读取超时。
它定义了一个等待服务器响应时两个数据包之间不活动的最长时间。
可以使用OkHttpClient.Builder#readTimeout 更改默认超时时间 10 秒。与连接超时类似,零值表示没有超时。
现在让我们看看如何在实践中配置自定义读取超时:
@Test
public void whenReadTimeoutExceeded_thenSocketTimeoutException() {
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(10, TimeUnit.MILLISECONDS)
.build();
Request request = new Request.Builder()
.url("https://httpbin.org/delay/2") // 2-second response time
.build();
Throwable thrown = catchThrowable(() -> client.newCall(request).execute());
assertThat(thrown).isInstanceOf(SocketTimeoutException.class);
}
正如我们所见,服务器不会在定义的 500 毫秒超时内返回响应。结果,OkHttpClient 抛出 SocketTimeoutException。
-
写入超时:
写入超时定义了向服务器发送请求时两个数据包之间不活动的最长时间。
同样,对于连接和读取超时,我们可以使用 OkHttpClient.Builder#writeTimeout 覆盖默认值 10 秒。按照惯例,零值意味着根本没有超时。
在以下示例中,我们将写入超时设置为 10 毫秒,并将 1 MB 的内容发布到服务器:
@Test
public void whenWriteTimeoutExceeded_thenSocketTimeoutException() {
OkHttpClient client = new OkHttpClient.Builder()
.writeTimeout(10, TimeUnit.MILLISECONDS)
.build();
Request request = new Request.Builder()
.url("https://httpbin.org/delay/2")
.post(RequestBody.create(MediaType.parse("text/plain"), create1MBString()))
.build();
Throwable thrown = catchThrowable(() -> client.newCall(request).execute());
assertThat(thrown).isInstanceOf(SocketTimeoutException.class);
}