Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Rest模板org.apache.http.NoHttpResponseException_Java_Spring_Spring Boot_Resttemplate - Fatal编程技术网

Java Rest模板org.apache.http.NoHttpResponseException

Java Rest模板org.apache.http.NoHttpResponseException,java,spring,spring-boot,resttemplate,Java,Spring,Spring Boot,Resttemplate,我有两个Spring引导服务A和B,还有一个外部服务C。 这是请求路径: Web浏览器服务A服务B外部服务C 外部服务正在返回返回到前端的资源。对于A、B和C之间的通信,我使用Rest模板。 进入Web应用程序时一切正常,但只要我运行并行运行的BDD测试(9个线程),调用外部服务C时,服务B中就会出现NoHttpResponseException org.apache.http.NoHttpResponseException Service_C failed to respond at org.

我有两个Spring引导服务A和B,还有一个外部服务C。 这是请求路径:

Web浏览器服务A服务B外部服务C

外部服务正在返回返回到前端的资源。对于A、B和C之间的通信,我使用Rest模板。 进入Web应用程序时一切正常,但只要我运行并行运行的BDD测试(9个线程),调用外部服务C时,服务B中就会出现NoHttpResponseException

org.apache.http.NoHttpResponseException Service_C failed to respond
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
以下是我的Rest模板配置:

    @Bean
public RestTemplate restTemplateExternal() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
    HttpComponentsClientHttpRequestFactory requestFactory = getRequestFactoryWithDisabledSSLValidation();
    RestTemplate restTemplate = new RestTemplate(requestFactory);

    return restTemplate;
}

private HttpComponentsClientHttpRequestFactory getRequestFactoryWithDisabledSSLValidation() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
    TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

    SSLContext sslContext = SSLContexts.custom()
            .loadTrustMaterial(null, acceptingTrustStrategy)
            .build();

    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();

    CloseableHttpClient httpClient = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .setSSLSocketFactory(csf)
            .build();

    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();

    requestFactory.setHttpClient(httpClient);

    return requestFactory;
}
我已经尝试调用
connectionManager.setValidateAfterInactivity(0)但它没有帮助

让我补充一下,从服务B到外部服务C的所有请求都是到同一个端点的。只有参数(x)正在更改:
/resource?param={x}

老实说,我不能100%确定HttpClient是否将使用每个服务请求创建(RESTTemplatebean是单例的),或者每个服务只有一个实例


也许我需要在连接管理器中设置DefaultMaxPerRoute?如果是,那么如何区分正确的数字?如果能简单介绍一下在这种情况下如何正确配置RestTemplate,我将不胜感激。

U可以尝试启用更多额外的日志记录,以便从服务器中搜索隐藏的异常。
服务器似乎断开了连接。

这里的问题类似:


尝试使用
clientBuilder.setRetryHandler(新的DefaultHttpRequestRetryHandler(3,true))成功了。如果有人能更深入地解释这个问题,我仍将不胜感激。

问题可能是因为响应包含标题
connections=close
。因此,一个连接被关闭,但下一个请求尝试重用现有连接(已关闭)并获得错误

setRetryHandler
在第一次连接重用时总是失败,但在第二次重试时启动新连接,然后将成功

您可以通过以下行禁用以重用连接:
httpClient.setReuseStrategy(新的NoConnectionReuseStrategy())

如果您想在日志中看到重试,可以使用如下重试解决方案:

private void addRetryHandler( HttpClientBuilder httpClientBuilder ) {
    logger.debug("adding retry handler to httpClient");
    httpClientBuilder.setRetryHandler(( exception, executionCount, context ) -> {
        if (executionCount > 3) {
            logger.debug("Maximum http request tries reached for client http pool ");
            return false;
        }
        if (exception instanceof org.apache.http.NoHttpResponseException) {
            logger.debug("No response from server on {} call, got NoHttpResponseException", executionCount);
            return true;
        }
        return false;
    });
}

由连接管理器保持活动状态的最有可能的持久连接会过时。也就是说,当连接处于空闲状态时,目标服务器在其端关闭连接,而HttpClient无法对该事件做出反应,从而导致连接半关闭或“过时”。