间隔一段时间后调用 API 时首次出现连接重置异常

Ank*_*iya 5 java spring connection-pooling http spring-boot

我们正在对一个 API 进行后调用,当我们在一段时间间隔后开始调用这个 API 时(在我们的例子中大多数时间是 10 分钟,如果间隔是 5 分钟,我们很少会得到),我们在第一次尝试时会遇到连接重置异常,那么其余的立即调用工作正常,但是如果调用此 API 时有 10 分钟的间隔然后再次调用,我们会在该间隔之后的第一次调用中遇到此类异常。我们使用 Java spring-boot Resttamplate 进行 API 调用并使用 Apache httpclient-4.5.2

阿帕奇日志 "[read] I/O error: Read timed out"

Java日志 Connection reset; nested exception is java.net.SocketException: Connection reset

重新标记配置

@Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
        return restTemplate;
    }

@Bean
    public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setHttpClient(httpClient());
        return clientHttpRequestFactory;
    }

@Bean
    public CloseableHttpClient httpClient() {
        RequestConfig requestConfig = RequestConfig.custom()
            .setConnectionRequestTimeout(180000)
            .setConnectTimeout(180000)
            .setSocketTimeout(180000).build();

        return HttpClients.custom()
            .setDefaultRequestConfig(requestConfig)
            .setConnectionManager(poolingConnectionManager())
           // .setKeepAliveStrategy(connectionKeepAliveStrategy())
            .build();
    }

@Bean
    public PoolingHttpClientConnectionManager poolingConnectionManager() {
        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
        poolingConnectionManager.setMaxTotal(50);
        return poolingConnectionManager;
    }
Run Code Online (Sandbox Code Playgroud)

如果我们在 HttpClients.custom() 中添加 set connectionKeepAliveStrategy ,如下所述,我们将不会收到任何此类异常。

@Bean
    public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
        return new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                HeaderElementIterator it = new BasicHeaderElementIterator
                    (response.headerIterator(HTTP.CONN_KEEP_ALIVE));
                while (it.hasNext()) {
                    HeaderElement he = it.nextElement();
                    String param = he.getName();
                    String value = he.getValue();

                    if (value != null && param.equalsIgnoreCase("timeout")) {
                        return Long.parseLong(value) * 1000;
                    }
                }
                return 20000;
            }
        };
    }
Run Code Online (Sandbox Code Playgroud)

不知道为什么这种异常会随着connectionKeepAliveStrategy而消失。它在这其中的作用是什么?提前致谢。

jum*_*key 4

检查以下两个要点:第 2.6
- 连接保持活动策略

  1. Keep-Alive响应中的标头

如果响应中不存在 Keep-Alive 标头,则 HttpClient 假定连接可以无限期地保持活动状态。

我猜测Keep-Alive您的 api 响应中有一个标头的值为 600 秒。

  1. 定制keep-alive策略:

然而,许多常用的 HTTP 服务器被配置为在一段时间不活动后断开持久连接,以节省系统资源,通常不会通知客户端。万一默认策略过于乐观,人们可能需要提供自定义的保持活动策略。