• httpClient连接池


    package com.my.client.utils;
    
    import org.apache.http.*;
    import org.apache.http.client.HttpRequestRetryHandler;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.methods.HttpRequestBase;
    import org.apache.http.client.protocol.HttpClientContext;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.ConnectTimeoutException;
    import org.apache.http.conn.routing.HttpRoute;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.StringEntity;
    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.protocol.HttpContext;
    import org.apache.http.util.EntityUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import javax.net.ssl.SSLException;
    import javax.net.ssl.SSLHandshakeException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InterruptedIOException;
    import java.net.UnknownHostException;
    import java.nio.charset.UnsupportedCharsetException;
    import java.util.*;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @author 木西.
     *
     */
    public class HttpConnectionPoolUtil {
        private static Logger logger = LoggerFactory.getLogger(HttpConnectionPoolUtil.class);
        private static final int CONNECT_TIMEOUT = Config.getHttpConnectTimeout();// 设置连接建立的超时时间为10s
        private static final int SOCKET_TIMEOUT = Config.getHttpSocketTimeout();
        private static final int MAX_CONN = Config.getHttpMaxPoolSize(); // 最大连接数
        private static final int Max_PRE_ROUTE = Config.getHttpMaxPoolSize();
        private static final int MAX_ROUTE = Config.getHttpMaxPoolSize();
        private static CloseableHttpClient httpClient; // 发送请求的客户端单例
        private static PoolingHttpClientConnectionManager manager; // 连接池管理类
        private static ScheduledExecutorService monitorExecutor;
    
        private final static Object syncLock = new Object(); // 相当于线程锁,用于线程安全
    
        /**
         * 对http请求进行基本设置
         * 
         * @param httpRequestBase http请求
         */
        private static void setRequestConfig(HttpRequestBase httpRequestBase) {
            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
                    .setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
    
            httpRequestBase.setConfig(requestConfig);
        }
    
        public static CloseableHttpClient getHttpClient(String url) {
            String hostName = url.split("/")[2];
            System.out.println(hostName);
            int port = 80;
            if (hostName.contains(":")) {
                String[] args = hostName.split(":");
                hostName = args[0];
                port = Integer.parseInt(args[1]);
            }
    
            if (httpClient == null) {
                // 多线程下多个线程同时调用getHttpClient容易导致重复创建httpClient对象的问题,所以加上了同步锁
                synchronized (syncLock) {
                    if (httpClient == null) {
                        httpClient = createHttpClient(hostName, port);
                        // 开启监控线程,对异常和空闲线程进行关闭
                        monitorExecutor = Executors.newScheduledThreadPool(1);
                        monitorExecutor.scheduleAtFixedRate(new TimerTask() {
                            @Override
                            public void run() {
                                // 关闭异常连接
                                manager.closeExpiredConnections();
                                // 关闭5s空闲的连接
                                manager.closeIdleConnections(Config.getHttpIdelTimeout(), TimeUnit.MILLISECONDS);
                                logger.info("close expired and idle for over 5s connection");
                            }
                        }, Config.getHttpMonitorInterval(), Config.getHttpMonitorInterval(), TimeUnit.MILLISECONDS);
                    }
                }
            }
            return httpClient;
        }
    
        /**
         * 根据host和port构建httpclient实例
         * 
         * @param host 要访问的域名
         * @param port 要访问的端口
         * @return
         */
        public static CloseableHttpClient createHttpClient(String host, int port) {
            ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
            LayeredConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", plainSocketFactory).register("https", sslSocketFactory).build();
    
            manager = new PoolingHttpClientConnectionManager(registry);
            // 设置连接参数
            manager.setMaxTotal(MAX_CONN); // 最大连接数
            manager.setDefaultMaxPerRoute(Max_PRE_ROUTE); // 路由最大连接数
    
            HttpHost httpHost = new HttpHost(host, port);
            manager.setMaxPerRoute(new HttpRoute(httpHost), MAX_ROUTE);
    
            // 请求失败时,进行请求重试
            HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
                @Override
                public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
                    if (i > 3) {
                        // 重试超过3次,放弃请求
                        logger.error("retry has more than 3 time, give up request");
                        return false;
                    }
                    if (e instanceof NoHttpResponseException) {
                        // 服务器没有响应,可能是服务器断开了连接,应该重试
                        logger.error("receive no response from server, retry");
                        return true;
                    }
                    if (e instanceof SSLHandshakeException) {
                        // SSL握手异常
                        logger.error("SSL hand shake exception");
                        return false;
                    }
                    if (e instanceof InterruptedIOException) {
                        // 超时
                        logger.error("InterruptedIOException");
                        return false;
                    }
                    if (e instanceof UnknownHostException) {
                        // 服务器不可达
                        logger.error("server host unknown");
                        return false;
                    }
                    if (e instanceof ConnectTimeoutException) {
                        // 连接超时
                        logger.error("Connection Time out");
                        return false;
                    }
                    if (e instanceof SSLException) {
                        logger.error("SSLException");
                        return false;
                    }
    
                    HttpClientContext context = HttpClientContext.adapt(httpContext);
                    HttpRequest request = context.getRequest();
                    if (!(request instanceof HttpEntityEnclosingRequest)) {
                        // 如果请求不是关闭连接的请求
                        return true;
                    }
                    return false;
                }
            };
    
            CloseableHttpClient client = HttpClients.custom().setConnectionManager(manager).setRetryHandler(handler)
                    .build();
            return client;
        }
    
        /**
         * 设置post请求的参数
         */
        private static void setPostParams(HttpPost httpPost, Map<String, String> params) {
            try {
                httpPost.setEntity(new StringEntity(GsonUtils.toJson(params), ContentType.APPLICATION_JSON));
            } catch (UnsupportedCharsetException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 发送post请求
         * */
        public static String post(String url, Map<String, String> params) {
            HttpPost httpPost = new HttpPost(url);
            setRequestConfig(httpPost);
            setPostParams(httpPost, params);
            CloseableHttpResponse response = null;
            InputStream in = null;
            String resp =null;
            try {
                response = getHttpClient(url).execute(httpPost, HttpClientContext.create());
                HttpEntity entity = response.getEntity();
                resp = EntityUtils.toString(entity);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (in != null)
                        in.close();
                    if (response != null)
                        response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return resp;
        }
    
        /**
         * 关闭连接池
         */
        public static void closeConnectionPool() {
            try {
                httpClient.close();
                manager.close();
                monitorExecutor.shutdown();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    class Config {
    
        static int httpConnectTimeout = 15*1000;
    
        static int httpSocketTimeout = 15*1000;
    
        static int httpMaxPoolSize = 100;
    
        static int httpMonitorInterval = 10*1000;
    
        static int httpIdelTimeout = 5*1000;
    
        public static int getHttpIdelTimeout() {
            return httpIdelTimeout;
        }
    
        public static int getHttpSocketTimeout() {
            return httpSocketTimeout;
        }
    
        public static int getHttpMaxPoolSize() {
            return httpMaxPoolSize;
        }
    
        public static int getHttpMonitorInterval() {
            return httpMonitorInterval;
        }
    
        public static int getHttpConnectTimeout() {
            return httpConnectTimeout;
        }
    
    }
  • 相关阅读:
    JS 数组
    JS 模拟彩票
    C++ 动态内存
    计算机网络--OSI七层模型
    C++ 异常处理
    C++ 文件和流
    数据库学习教程网站
    数据结构--哈夫曼树
    数据结构--红黑树
    数据结构--伸展树
  • 原文地址:https://www.cnblogs.com/muxi0407/p/11882262.html
Copyright © 2020-2023  润新知