java - okhttp 客户端超时和 apache 超时之间的区别
问题描述
过去我使用apache的http客户端。我有以下设置:
- 连接请求超时
- 连接超时
- 读取/套接字超时
- 连接池大小
我正在迁移到 OkHttp 客户端,它有不同的超时:
- 连接超时
- 通话超时
- 读超时
- 写超时
- max-idle-connections(连接池设置)
- keep-alive-duration-minutes(连接池设置)
它们如何相互映射?
问候,
瑞克
解决方案
摘自 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); }
读取超时:
从客户端和目标主机之间的连接成功建立的那一刻起,就会应用读取超时。
它定义了等待服务器响应时两个数据包之间不活动的最长时间。
可以使用 更改 10 秒的默认超时
OkHttpClient.Builder#readTimeout
。与连接超时类似,零值表示没有超时。现在让我们看看如何在实践中配置自定义读取超时:
@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。写超时:
写超时定义了向服务器发送请求时两个数据包之间不活动的最长时间。
同样,对于连接和读取超时,我们可以使用 10 秒覆盖默认值
OkHttpClient.Builder#writeTimeout
。按照惯例,零值意味着根本没有超时。在以下示例中,我们将写入超时设置为 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); }
推荐阅读
- pandas - 通过熊猫(python)中列名的子字符串融化列
- javascript - 'import' 和 'export' 可能只出现在 'sourceType: "module"' (16:0)
- xml - 如何使用 Groovy 获取 soapUI 配置设置
- azure - Azure Active Directory easy auth /.auth/me 的权限错误返回 401
- python-3.x - Flask App 模拟阻塞 API 以从基于 Web 挂钩的回调中抽象出来
- c - CMake 无法在 Windows 上创建 MakeFile
- javascript - ReactJS 中的 Zip 文件下载
- r - 为列表中的每个元素提取残差序列
- android - 在 Kotlin 中退出应用程序后如何保存变量
- firebase - 为什么我仍然可以通过浏览器打开存储在 Firebase 存储中的图像,即使它有规则?