在一段时间间隔后调用 API 时第一次获取连接重置异常

Getting Connection reset exception first time while calling API after sometime of interval

我们正在对 API 进行 post 调用,当我们在一段时间间隔后开始调用此 API 时(在我们的例子中大部分时间是 10 分钟,很少我们get if interval is 5 mins) 第一次尝试时我们得到 Connection reset exception,然后立即调用的其余部分工作正常,但如果调用此 API 的间隔为 10 分钟然后再次调用,我们得到这样该间隔后第一次调用的异常。 我们正在使用 Java spring-boot Restamplate 进行 API 调用并使用 Apache httpclient-4.5.2

apache 日志 "[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;
    }

如果我们在 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;
            }
        };
    }

不确定为什么此类异常随 connectionKeepAliveStrategy 一起消失。它在其中扮演什么角色? 提前致谢。

检查 these 两个要点:
2.6 节 - 连接保持活动策略:

  1. Keep-Alive header 在响应中

If the Keep-Alive header is not present in the response, HttpClient assumes the connection can be kept alive indefinitely.

我猜您的 api 响应中有一个 Keep-Alive header,值为 600 秒。

  1. 自定义keep-alive策略:

However, many HTTP servers in general use are configured to drop persistent connections after a certain period of inactivity in order to conserve system resources, quite often without informing the client. In case the default strategy turns out to be too optimistic, one may want to provide a custom keep-alive strategy.