ClientHttpRequestInterceptor报错Timeout waiting for connection from pool

restTemplate实现ClientHttpRequestInterceptor,报错org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool

代码如下:

@Configuration
public class HttpConfig {

    private static final Integer RETRY_COUNT = 3;

    @Bean
    public RestTemplate restTemplate() {
        //设置超时时间
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(10000);
        /** 连接超时参数 ConnectTimeout,让用户配置建连阶段的最长等待时间 **/
        httpRequestFactory.setConnectTimeout(10000);
        /** 读取超时参数 ReadTimeout,用来控制从 Socket 上读取数据的最长等待时间 5s**/
        httpRequestFactory.setReadTimeout(5000);
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        //设置UTF-8 编码
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        restTemplate.getInterceptors().add(new LoggingClientHttpRequestInterceptor());
        return restTemplate;
    }

    @Slf4j
    public static class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            /**
             * {@link InterceptingClientHttpRequest.InterceptingRequestExecution#execute(HttpRequest, byte[])} 当拦截器链处理完,开始执行真正请求
             */
            int retryCount = 1;
            ClientHttpResponse response = null;
            while (retryCount <= RETRY_COUNT) {
                try {
                    long start = System.currentTimeMillis();
                    response = execution.execute(request, body);
                    log.info("[method:{}] [url:{}] [reqBody:{}] [status:{}] [time:{}]", request.getMethod(), request.getURI(), new String(body, "UTF-8"), response.getStatusCode(), System.currentTimeMillis() - start);
                    if(response.getStatusCode().value() != HttpStatus.OK.value()){
                        throw new CommonApiException("[method:" + request.getMethod() +"]" +  "[url:"+ request.getURI() +"]"+"[status:"+response.getStatusCode()+"]"+"请求失败");
                    }
                    return response;
                } catch (Exception e) {
                
                    if (retryCount == RETRY_COUNT) {
                        throw new ResourceNotFoundException("[HttpConfig]重试异常:" + e);
                    }
                    log.info("准备进行重试:[url:{}]重试第{}次", request.getURI(), retryCount);
                }finally {
                    retryCount++;
                }

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    log.warn("[HttpConfig] [Thread.sleep] 错误", e);
                }
            }
            return null;
        }
    }
}

主要是针对restTemplate调用的接口进行重试处理,重试3次。上线后意外报错,幸好及时发现,问题不大。
分析产生报错的原因:调用的外系统接口调用404,本系统无法关闭连接资源,导致线程池超时,报错如下:
在这里插入图片描述
解决:报错后将连接资源关闭即可,即在catch中加入以下代码:

if (response != null) {
    response.close();
}

在这里插入图片描述
finish!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值