HttpClient连接池配置与使用

 二维码 130
发表时间:2019-07-30 14:56

在游戏项目开发中,经常会向其它的服务发送一些Http请求,获取一些数据或验证。比如充值,SDK验证等。如果每次都重新创建一个新的HttpClient对象的话,当并发上来时,容易出现异常或连接失败,超时。这里可以使用HttpClient的连接池配置,减少HttpClient创建的数量,减少资源开销。

package com.mygame.common.utils;


import java.io.IOException;

import java.security.KeyManagementException;

import java.security.KeyStoreException;

import java.security.NoSuchAlgorithmException;

import org.apache.http.Header;

import org.apache.http.HttpStatus;

import org.apache.http.client.config.RequestConfig;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.config.Registry;

import org.apache.http.config.RegistryBuilder;

import org.apache.http.conn.socket.ConnectionSocketFactory;

import org.apache.http.conn.socket.PlainConnectionSocketFactory;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import org.apache.http.conn.ssl.TrustSelfSignedStrategy;

import org.apache.http.entity.StringEntity;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import org.apache.http.ssl.SSLContextBuilder;

import org.apache.http.util.EntityUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;


publicclass GameHttpClient {

    privatestatic Logger logger = LoggerFactory.getLogger(GameHttpClient.class);

    // 池化管理

    privatestatic PoolingHttpClientConnectionManager poolConnManager = null;


    privatestatic CloseableHttpClient httpClient;// 它是线程安全的,所有的线程都可以使用它一起发送http请求

    static {

        try {

            System.out.println("初始化HttpClientTest~~~开始");

            SSLContextBuilder builder = new SSLContextBuilder();

            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());

            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());

            // 配置同时支持 HTTP 和 HTPPS

            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslsf).build();

            // 初始化连接管理器

            poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

            poolConnManager.setMaxTotal(640);// 同时最多连接数

            // 设置最大路由

            poolConnManager.setDefaultMaxPerRoute(320);

            // 此处解释下MaxtTotal和DefaultMaxPerRoute的区别:

            // 1、MaxtTotal是整个池子的大小;

            // 2、DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分;比如:

            // MaxtTotal=400 DefaultMaxPerRoute=200

            // 而我只连接到http://www.abc.com时,到这个主机的并发最多只有200;而不是400;

            // 而我连接到http://www.bac.com 和

            // http://www.ccd.com时,到每个主机的并发最多只有200;即加起来是400(但不能超过400);所以起作用的设置是DefaultMaxPerRoute

            // 初始化httpClient

            httpClient = getConnection();


            System.out.println("初始化HttpClientTest~~~结束");

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (KeyStoreException e) {

            e.printStackTrace();

        } catch (KeyManagementException e) {

            e.printStackTrace();

        }

    }


    publicstatic CloseableHttpClient getConnection() {

        RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(5000).build();

        CloseableHttpClient httpClient = HttpClients.custom()

                // 设置连接池管理

                .setConnectionManager(poolConnManager)

                .setDefaultRequestConfig(config)

                // 设置重试次数

                .setRetryHandler(new DefaultHttpRequestRetryHandler(2, false)).build();

        returnhttpClient;

    }

   

    publicstatic String httpGet(String url) {

        HttpGet httpGet = new HttpGet(url);

        CloseableHttpResponse response = null;

       

        try {

            response = httpClient.execute(httpGet);

            String result = EntityUtils.toString(response.getEntity());

            intcode = response.getStatusLine().getStatusCode();

            if (code == HttpStatus.SC_OK) {

                returnresult;

            } else {

                logger.error("请求{}返回错误码:{},{}", url, code,result);

                returnnull;

            }

        } catch (IOException e) {

            logger.error("http请求异常,{}",url,e);

        } finally {

            try {

                if (response != null)

                    response.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

        returnnull;

    }

    publicstatic String post(String uri, Object params, Header... heads) {

        HttpPost httpPost = new HttpPost(uri);

        CloseableHttpResponse response = null;

        try {

            StringEntity paramEntity = new StringEntity(JSON.toJSONString(params));

            paramEntity.setContentEncoding("UTF-8");

            paramEntity.setContentType("application/json");

            httpPost.setEntity(paramEntity);

            if (heads != null) {

                httpPost.setHeaders(heads);

            }

             response = httpClient.execute(httpPost);

            intcode = response.getStatusLine().getStatusCode();

            String result = EntityUtils.toString(response.getEntity());

            if (code == HttpStatus.SC_OK) {

                returnresult;

            } else {

                logger.error("请求{}返回错误码:{},请求参数:{},{}", uri, code, params,result);

                returnnull;

            }

        } catch (IOException e) {

            logger.error("收集服务配置http请求异常", e);

        } finally {

            try {

               if(response != null) {

                   response.close();

               }

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

        returnnull;

    }


}

1.jpg


QQ交流群:66728073,197321069