首页 > 解决方案 > okhttp 客户端超时和 apache 超时之间的区别

问题描述

过去我使用apache的http客户端。我有以下设置:

我正在迁移到 OkHttp 客户端,它有不同的超时:

它们如何相互映射?

问候,

瑞克

标签: javaspring-bootokhttpapache-httpcomponents

解决方案


摘自 Baeldung上写的优秀文章,这里有一些细节:

  1. 连接超时:

    连接超时定义了我们的客户端应该与目标主机建立连接的时间段。 默认情况下,对于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当连接尝试超过配置的超时时,客户端抛出一个。

  2. 通话超时:

    调用超时与我们已经讨论过的连接、读取和写入超时有点不同。它定义了一个完整的 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);
    }
    
  3. 读取超时:

    从客户端和目标主机之间的连接成功建立的那一刻起,就会应用读取超时。

    它定义了等待服务器响应时两个数据包之间不活动的最长时间

    可以使用 更改 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

  4. 写超时:

    写超时定义了向服务器发送请求时两个数据包之间不活动的最长时间

    同样,对于连接和读取超时,我们可以使用 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);
    }
    

推荐阅读