httpclient连接池

package com.junbo.salecard.service.yunxin.impl;

import com.winnerlook.service.https.MyVerifyHostname;
import com.winnerlook.service.https.MyX509TrustManager;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
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.BufferedHttpEntity;
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.pool.PoolStats;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author zsy
 * @date 2022/1/14
 */
public class HttpClientUtils {

    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
    // 设定从连接池获取可用连接的时间
//    private static final int connectPoolTimeout = 2000;
    // 建立连接超时时间
//    private static final int connectTimeout = 5000;
    // 设置等待数据超时时间5秒钟 根据业务调整
//    private static final int socketTimeout = 5000;
    // 连接池最大连接数
//    private static final int maxTotal = 100;
    // 每个主机的并发
//    private static final int maxPerRoute = 10;
    // 目标主机的最大连接数
//    private static final int maxRoute = 50;
    private static CloseableHttpClient httpClient = null;
    private final static Object SYNC_LOCK = new Object();
    private static PoolingHttpClientConnectionManager cm = null;
    private static final ScheduledExecutorService monitorExecutor;
    private static boolean isShowUsePoolLog = true;
    private static X509TrustManager tm;

    static {
        //org.apache.commons.lang3.concurrent.BasicThreadFactory
        monitorExecutor = new ScheduledThreadPoolExecutor(1,
                new BasicThreadFactory.Builder().namingPattern("import-schedule-pool-%d").daemon(true).build());
    }

    /**
     * 获取HttpClient对象
     *
     * @param url
     * @return
     * @author
     * @date 2019年4月11日
     */
    public static CloseableHttpClient getHttpClient(final String url) throws NoSuchAlgorithmException, KeyManagementException {
        String hostname = url.split("/")[2];
        int port = 80;
        if (hostname.contains(":")) {
            final String[] arr = hostname.split(":");
            hostname = arr[0];
            port = Integer.parseInt(arr[1]);
        }
        if (HttpClientUtils.httpClient == null) {
            System.out.println("1****第一次创建httpClient");
            // 多线程下多个线程同时调用getHttpClient容易导致重复创建httpClient对象的问题,所以加上了同步锁
            synchronized (HttpClientUtils.SYNC_LOCK) {
                if (HttpClientUtils.httpClient == null) {
                    int maxTotal = 10;
                    int maxPerRoute = 10;
                    int maxRoute = 10;
                    final long timeout = 1000;
                    System.out.println("2****第一次创建httpClient -->" + maxTotal);
                    // 开启监控线程,对异常和空闲线程进行关闭
                    HttpClientUtils.monitorExecutor.scheduleAtFixedRate(new TimerTask() {
                        @Override
                        public void run() {
                            // 关闭异常连接
                            HttpClientUtils.cm.closeExpiredConnections();
                            // 关闭空闲的连接
                            HttpClientUtils.cm.closeIdleConnections(timeout, TimeUnit.MILLISECONDS);
                            final PoolStats poolStats = HttpClientUtils.cm.getTotalStats();
                            final int usePoolNum = poolStats.getAvailable() + poolStats.getLeased()
                                    + poolStats.getPending();
                            if (HttpClientUtils.isShowUsePoolLog) {
                                HttpClientUtils.logger.info("***********》关闭异常+空闲连接! 空闲连接:"
                                        + poolStats.getAvailable() + " 持久连接:" + poolStats.getLeased() + " 最大连接数:"
                                        + poolStats.getMax() + " 阻塞连接数:" + poolStats.getPending());
                            }
//                            if (usePoolNum == 0) {
//                                HttpClientUtils.isShowUsePoolLog = false;
//                            } else {
//                                HttpClientUtils.isShowUsePoolLog = true;
//                            }
                            HttpClientUtils.isShowUsePoolLog = usePoolNum != 0;
                        }
                    }, timeout, timeout, TimeUnit.MILLISECONDS);
                    HttpClientUtils.httpClient = HttpClientUtils.createHttpClient(maxTotal, maxPerRoute,
                            maxRoute, hostname, port);
                }
            }
        } else {
            System.out.println("3****获取已有的httpClient");
        }
        return HttpClientUtils.httpClient;
    }

    /**
     * 创建HttpClient对象
     *
     * @param maxTotal    最大连接数
     * @param maxPerRoute 每个主机的并发
     * @param maxRoute    目标主机的最大并发,如果只有一台,可以和maxTotal一样
     * @param hostname
     * @param port
     * @return
     * @author
     * @date 2019年4月11日
     */
    private static CloseableHttpClient createHttpClient(
            final int maxTotal,
            final int maxPerRoute,
            final int maxRoute,
            final String hostname,
            final int port) throws NoSuchAlgorithmException, KeyManagementException {
        final ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
        final LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
        final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", plainsf).register("https", sslsf).build();
        HttpClientUtils.cm = new PoolingHttpClientConnectionManager(registry);
        // 将最大连接数增加
        HttpClientUtils.cm.setMaxTotal(maxTotal);
        // 将每个路由基础的连接增加
        HttpClientUtils.cm.setDefaultMaxPerRoute(maxPerRoute);
        final HttpHost httpHost = new HttpHost(hostname, port);
        // 将目标主机的最大连接数增加
        HttpClientUtils.cm.setMaxPerRoute(new HttpRoute(httpHost), maxRoute);
        // 请求重试处理
        SSLContext sslContext = SSLContext.getInstance("TLS");
        tm = new MyX509TrustManager();
        sslContext.init(null, new TrustManager[]{tm},
                new java.security.SecureRandom());
        return HttpClients.custom()
                .setConnectionManager(HttpClientUtils.cm)
                .setSSLHostnameVerifier(new MyVerifyHostname())
                .disableAutomaticRetries()
                .setSSLContext(sslContext)
                .build();
    }

    public static String doPost(String path, String headerStr,
                         String requestBody, String encoding) throws Exception {
        String resultString;
        CloseableHttpResponse response = null;
        HttpPost httpPost = null;
        try {
            URI uri = new URI(path);
            httpPost = new HttpPost(uri);
            httpPost.setHeader("Content-type", "application/json; charset=utf-8");
            /** 报文头中设置Authorization参数*/
            httpPost.setHeader("Authorization", headerStr);
            /** 设置请求报文体*/
            httpPost.setEntity(new StringEntity(requestBody, encoding));
            response = HttpClientUtils.getHttpClient(path).execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            httpEntity = new BufferedHttpEntity(httpEntity);
            resultString = EntityUtils.toString(httpEntity);
        } finally {
            //释放连接
            if (null != response) {
                response.close();
            }
//            if (httpPost != null) {
//                httpPost.releaseConnection();
//            }
        }
        return resultString;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值