首页 > 编程语言 >java RestTemplate集成HttpClient池化及异常重试

java RestTemplate集成HttpClient池化及异常重试

时间:2023-10-11 13:22:04浏览次数:35  
标签:http java RestTemplate return 重试 static import apache org

解决存在网络隔离,首次连接请求被拒绝情况SocketException
首次请求超时情况SocketTimeoutException
无返回数据清空NoHttpResponseException进行重试

import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.net.SocketException;
import java.net.SocketTimeoutException;

/**
 * @ClassName: RestTemplateConfig
 * @Description: 请求客户端配置
 *  <a href="https://www.saoniuhuo.com/question/detail-2235180.html">报异常首次连接超时等问题</a>
 * @Application: 云上公交-应用管理平台
 * @author: wangwenying
 * @date: 2023/9/22
 * @version: 1.0.0
 * @Copyright: 智达信科技术股份有限公司版权所有。
 */
@Configuration
public class RestTemplateConfig {
    
    private static final Logger logger = LoggerFactory.getLogger(RestTemplateConfig.class);

    /**
     * 连接超时时间
     */
    private static final int CONNECT_TIMEOUT = 5000;
    
    /**
     * 连接管理器连接请求超时时间
     */
    private static final int CONNECTION_MANAGER_CONNECTION_REQUEST_TIMEOUT = 0;
    
    /**
     * socket请求超时时间
     */
    private static final int SOCKET_TIMEOUT = 5000;
    
    /**
     * 最大连接数
     */
    private static final int MAX_TOTAL = 200;
    
    /**
     * 每个路由的最大连接数
     */
    private static final int MAX_PER_ROUTE = 200;
    
    /**
     * 重试次数
     */
    private static final int RETRY_TIMES = 3;

    /**
     * 重试延迟
     */
    private static final int RETRY_INTERVAL_TIME = 1000;

    /**
     * @return {@link PoolingHttpClientConnectionManager }
     * @Description 请求池
     * @author wangwenying
     * @date 2023-10-11
     */
    @Bean
    public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(MAX_TOTAL);
        connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
        connectionManager.setValidateAfterInactivity(CONNECT_TIMEOUT);
        return connectionManager;
    }

    /**
     * @return {@link RequestConfig }
     * @Description 请求配置
     * @author wangwenying
     * @date 2023-10-11
     */
    @Bean
    public RequestConfig requestConfig() {
        return RequestConfig.custom()
                .setConnectionRequestTimeout(CONNECTION_MANAGER_CONNECTION_REQUEST_TIMEOUT)
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build();
    }

    /**
     * @param poolingHttpClientConnectionManager 池管理
     * @param requestConfig 请求配置
     * @return {@link CloseableHttpClient }
     * @Description httpclient 配置
     * @author wangwenying
     * @date 2023-10-11
     */
    @Bean
    public CloseableHttpClient httpClient(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager, RequestConfig requestConfig) {
        HttpRequestRetryHandler handler = (exception, curRetryCount, context) -> {
            logger.error("请求发生错误,错误信息ExceptionName:{}", exception.getClass().getName(), exception);
            // curRetryCount 每一次都会递增,从1开始
            if (curRetryCount > RETRY_TIMES) {
                return false;
            }
            try {
                //重试延迟
                Thread.sleep((long) curRetryCount * RETRY_INTERVAL_TIME);
            } catch (InterruptedException e) {
                logger.error("延迟时间发生错误", e);
            }
            if (exception instanceof ConnectTimeoutException
                    || exception instanceof NoHttpResponseException
                    || exception instanceof SocketException
                    || exception instanceof SocketTimeoutException) {
                return true;
            }

            HttpClientContext clientContext = HttpClientContext.adapt(context);
            org.apache.http.HttpRequest request = clientContext.getRequest();
            // 如果请求被认为是幂等的,那么就重试。即重复执行不影响程序其他效果的
            return !(request instanceof HttpEntityEnclosingRequest);
        };
        return HttpClientBuilder
                .create()
                .setConnectionManager(poolingHttpClientConnectionManager)
                .setDefaultRequestConfig(requestConfig)
                .setRetryHandler(handler)
                .build();
    }

    /**
     * @return {@link RestTemplate }
     * @Description 请求5A接口配置
     * @author wangwenying
     * @date 2023-10-11
     */
    @Bean("restTemplate")
    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(httpClient(poolingHttpClientConnectionManager(), requestConfig()));
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(factory);
        return restTemplate;
    }
}

标签:http,java,RestTemplate,return,重试,static,import,apache,org
From: https://www.cnblogs.com/stubborn-dude/p/17756839.html

相关文章

  • kali-Java版本管理-update-alternatives
    kali-Java版本管理-update-alternativeshttps://blog.csdn.net/qq_44029310/article/details/126086895列出软件的所有版本update-alternatives--config软件名update-alternatives--configjava的示例输出Thereare3choicesforthealternativejava(providing/usr......
  • Redis的Java客户端——SpringDataRedis、RedisTemplate、StringRedisTemplate
     版权声明:本文为CSDN博主「我爱布朗熊」的原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/weixin_51351637/article/details/127502799一、初步了解SpringDataRedisSpringData是Spring中数据操作的模块,包括对各种数据库的集......
  • Java算法之动态规划详解
    ①动态规划动态规划(DynamicProgramming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事......
  • 解决 jmeter 压测Non HTTP response code: java.net.NoRouteToHostException/Non HTTP
    针对centos:先检查下tcp port range在合理范围内: cat /proc/sys/net/ipv4/ip_local_port_range 102465535上述为centos合理范围,不合理作出修改解决方法:1.调低端口释放后的等待时间,默认为60s,修改为15~30secho30>/proc/sys/net/ipv4/tcp_fin_timeout2.修改tc......
  • 【Java】对两个Set取交集,差集,并集
    1、取交集(取两个集合中都存在的元素)HashSet<String>setA=newHashSet<>();HashSet<String>setB=newHashSet<>();//用于存放结果HashSet<String>resSet=newHashSet<>();resSet.addAll(setA);resSet.retainAll(setB);returnresSet;2、取差集(取存......
  • struts2调用javabean中的方法
    1.<s:setname="str"value="helloworld"></s:set><s:propertyvalue="%{@com.Test@func(#str)}"/>其中func是com.Test中的一个静态方法2.<s:beanname="com.Test"id="t"><......
  • java内部类有什么好处
    内部类:一个内部类的定义是定义在另一个内部的类。原因是:1.一个内部类的对象能够访问创建它的对象的实现,包括私有数据。2.对于同一个包中的其他类来说,内部类能够隐藏起来。3.匿名内部类可以很方便的定义回调。4.使用内部类可......
  • java如何做大体积的文件上传和下载
    在Java中,实现大体积文件的上传和下载涉及到处理文件的分片、并发上传、断点续传等问题。本文将详细介绍如何通过Java实现大体积文件的上传和下载。1.文件上传文件上传是将本地文件上传到服务器的过程。对于大体积文件的上传,我们可以将文件分成多个小片段进行并发上传。1.1文件......
  • 10月TIOBE榜Java跌出前三!要不我转回C#吧
    前言Java又要完了,又要没了,你没看错,10月编程语言榜单出炉,Java跌出前三,并且即将被C#超越,很多资深人士预测只需两个月,Java就会跌出前五。看到这样的文章,作为一名Java工程师我感到一阵发自灵魂的战栗,三魂丢了两魂,七魄去了六魄,现在已经躺在床上奄奄一息,对未来产生了极大的迷茫,眼泪不......
  • 盘点KendoReact五大功能,让JavaScript数据网格构建更轻松!
    在本文中,我们将为大家分享KendoReact DataGrid中最受欢迎的五大功能:性能、数据组织、列和行交互、编辑自定义以及导出。有了这些功能,开发者大可不必从头开始构建JavaScript数据网格了!KendoUI是带有jQuery、Angular、React和Vue库的JavaScriptUI组件的最终集合,无论选择哪种Jav......