首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

HttpClient重试机制 --自定义HttpRequestRetryHandler

HttpClient重试机制 --自定义HttpRequestRetryHandler

通过http做接口调用请求的时候,常常会因为网络抖动或者其他未知原因,造成接口在某个瞬间访问不了。此时需要增加重试机制。

HttpClient有重试机制,通过设置httpclient 的retryHandler来实现。

封装了一个HttpClientUtils的工具类中的获取线程池并设置retry机制的方法,代码如下:

    package com.ly.storm.config;
     
    import com.alibaba.fastjson.JSON;
    import com.google.common.collect.ImmutableMap;
    import com.google.common.collect.Lists;
    import org.apache.commons.httpclient.ConnectTimeoutException;
    import org.apache.commons.httpclient.HttpStatus;
    import org.apache.http.HttpEntityEnclosingRequest;
    import org.apache.http.HttpRequest;
    import org.apache.http.NameValuePair;
    import org.apache.http.NoHttpResponseException;
    import org.apache.http.client.HttpRequestRetryHandler;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.protocol.HttpClientContext;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.protocol.HttpContext;
    import org.apache.http.util.EntityUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
     
    import javax.annotation.PostConstruct;
    import javax.net.ssl.SSLException;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.UnknownHostException;
    import java.util.Enumeration;
    import java.util.List;
    import java.util.Map;
     
    /**
     * @Auther: fc.w
     * @Date: 2018/12/12
     */
    public class HttpClientUtils {
     
        private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
     
        private static final RequestConfig REQUEST_CONFIG_TIME_OUT = RequestConfig.custom()
                .setSocketTimeout(20000)
                .setConnectTimeout(50000)
                .setConnectionRequestTimeout(50000)
                .build();
     
        private static PoolingHttpClientConnectionManager cm = null;
     
        @PostConstruct
        public void init() {
            cm = new PoolingHttpClientConnectionManager();
            cm.setMaxTotal(1000);
            cm.setDefaultMaxPerRoute(1000);
        }
     
        /**
         *
         * @param isPooled 是否使用连接池
         * @return
         */
        public static CloseableHttpClient getClient(boolean isPooled) {
            HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() {
                @Override
                public boolean retryRequest(IOException e, int retryTimes, HttpContext httpContext) {
                    if (retryTimes > 2) {
                        return false;
                    }
                    if (e instanceof UnknownHostException || e instanceof ConnectTimeoutException
                            || !(e instanceof SSLException) || e instanceof NoHttpResponseException) {
                        return true;
                    }
     
                    HttpClientContext clientContext = HttpClientContext.adapt(httpContext);
                    HttpRequest request = clientContext.getRequest();
                    boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
                    if (idempotent) {
                        // 如果请求被认为是幂等的,那么就重试。即重复执行不影响程序其他效果的
                        return true;
                    }
                    return false;
                }
            };
            if (isPooled) {
                return HttpClients.custom().setConnectionManager(cm).setRetryHandler(retryHandler).build();
            }
            return HttpClients.createDefault();
     
        }
返回列表