HttpClient 连接池的简单实现
来源:互联网 发布:noogenesis数据bi平台 编辑:程序博客网 时间:2024/05/19 19:59
最近在做Druid大数据实时分析系统,以Http的方式向Druid集群写入数据,采用HttpClient向集群提交数据,由于数据量较大,采用多线程的方式开启了10个线程后,发现单个的HttpClient会出现连接超时,效率不高,所以想用到连接池的方式提高效率下面是一个简单的HttpClient连接池的实现:
package com.ssm.httpclient.utils;import java.io.IOException;import java.util.concurrent.TimeUnit;import org.apache.http.client.config.RequestConfig;import org.apache.http.config.Registry;import org.apache.http.config.RegistryBuilder;import org.apache.http.config.SocketConfig;import org.apache.http.conn.DnsResolver;import org.apache.http.conn.HttpConnectionFactory;import org.apache.http.conn.ManagedHttpClientConnection;import org.apache.http.conn.routing.HttpRoute;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.impl.DefaultConnectionReuseStrategy;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.apache.http.impl.conn.SystemDefaultDnsResolver;import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class HttpClientUtils { private static final Logger LOG = LoggerFactory.getLogger(HttpClientUtils.class); static PoolingHttpClientConnectionManager manager = null; static CloseableHttpClient httpClient = null; public static synchronized CloseableHttpClient getHttpClient(){ if(httpClient == null){ //注册访问协议相关的Socket工厂 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", SSLConnectionSocketFactory.getSystemSocketFactory()) .build(); //HttpConnection 工厂:配置写请求/解析响应处理器 HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connectionFactory = new ManagedHttpClientConnectionFactory(DefaultHttpRequestWriterFactory.INSTANCE, DefaultHttpResponseParserFactory.INSTANCE); //DNS 解析器 DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE; //创建池化连接管理器 manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry,connectionFactory,dnsResolver); //默认为Socket配置 SocketConfig defaultSocketConfig = SocketConfig.custom().setTcpNoDelay(true).build(); manager.setDefaultSocketConfig(defaultSocketConfig); manager.setMaxTotal(300); //设置整个连接池的最大连接数 //每个路由的默认最大连接,每个路由实际最大连接数由DefaultMaxPerRoute控制,而MaxTotal是整个池子的最大数 //设置过小无法支持大并发(ConnectionPoolTimeoutException) Timeout waiting for connection from pool manager.setDefaultMaxPerRoute(200);//每个路由的最大连接数 //在从连接池获取连接时,连接不活跃多长时间后需要进行一次验证,默认为2s manager.setValidateAfterInactivity(5*1000); //默认请求配置 RequestConfig defaultRequestConfig = RequestConfig.custom() .setConnectTimeout(2*1000) //设置连接超时时间,2s .setSocketTimeout(5*1000) //设置等待数据超时时间,5s .setConnectionRequestTimeout(2000) //设置从连接池获取连接的等待超时时间 .build(); //创建HttpClient httpClient = HttpClients.custom() .setConnectionManager(manager) .setConnectionManagerShared(false) //连接池不是共享模式 .evictIdleConnections(60, TimeUnit.SECONDS) //定期回收空闲连接 .evictExpiredConnections()// 定期回收过期连接 .setConnectionTimeToLive(60, TimeUnit.SECONDS) //连接存活时间,如果不设置,则根据长连接信息决定 .setDefaultRequestConfig(defaultRequestConfig) //设置默认请求配置 .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE) //连接重用策略,即是否能keepAlive .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE) //长连接配置,即获取长连接生产多长时间 .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)) //设置重试次数,默认是3次,当前是禁用掉(根据需要开启) .build(); //JVM 停止或重启时,关闭连接池释放掉连接(跟数据库连接池类似) Runtime.getRuntime().addShutdownHook(new Thread(){ @Override public void run() { try{ if(httpClient !=null){ httpClient.close(); } }catch(IOException e){ LOG.error("error when close httpClient:{}",e); } } }); } return httpClient; }}
基于HttpClientUtils的测试
package com.ssm.httpclient.utils;import java.io.IOException;import java.nio.charset.Charset;import java.util.List;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.ThreadFactory;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.client.methods.HttpGet;import org.apache.http.util.EntityUtils;import com.google.common.collect.Lists;import com.google.common.util.concurrent.ThreadFactoryBuilder;public class HttpClientExample { public static void main(String[] args) { final ThreadFactory threadFactory = new ThreadFactoryBuilder() .setNameFormat("Orders-%d").build(); ExecutorService executorService = Executors.newFixedThreadPool(10,threadFactory); List<Future<?>> list = Lists.newArrayList(); Long startTime = System.currentTimeMillis(); Future<?> future; for(int i=0;i<100;i++){ future = executorService.submit((new HttpGetTest())); list.add(future); } for(Future<?> future2:list){ try { future2.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } System.out.println("total cost times: "+(System.currentTimeMillis()-startTime)); executorService.shutdown(); }}class HttpGetTest implements Runnable { public void run() { HttpResponse response = null; try { HttpGet get = new HttpGet("https://baike.baidu.com/item/httpclient/5766483?fr=aladdin"); response = HttpClientUtils.getHttpClient().execute(get); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { EntityUtils.consume(response.getEntity()); } else { String result = EntityUtils.toString(response.getEntity(),Charset.forName("utf-8")); System.out.println(result); } } catch (Exception e) { if (response != null) { try { EntityUtils.consume(response.getEntity()); } catch (IOException e1) { e1.printStackTrace(); } } } }}
total cost times: 3248
一百个线程请求花了3s 多,性能还是可以
阅读全文
0 0
- HttpClient 连接池的简单实现
- 实现一个简单的HttpClient连接池(转自博客园)
- HttpClient的连接池
- 连接管理工具httpclient的简单使用
- 使用HttpClient的PoolingHttpClientConnectionManager实现Http请求连接池
- httpclient连接池的使用
- httpclient连接池的使用
- httpClient 4.5.2 实现连接池
- httpClient 4.5.2 实现连接池
- 基于httpclient的一个简单刷票器实现
- HttpClient实现简单的网络爬虫功能
- Scala结合HttpClient实现简单的爬虫
- Http请求连接池 - HttpClient 的 PoolingHttpClientConnectionManager
- 配置使用连接池的httpClient
- HttpClient连接池的三篇文章
- 简单JDBC连接池的实现
- java 连接池的简单实现
- JDBC实现简单的连接池代码
- 2n皇后问题
- 视频编码之I帧 、P帧、B帧
- 宿舍里的故事之五子棋
- Mac 下启动tomcat
- 廉价16bit音频DAC芯片TM8211(PT8211、TDA1311)
- HttpClient 连接池的简单实现
- FastCGI 协议分析与C语言实现实例
- SSL_1010 方格取数
- elementUI table的滑动条
- 关于libjpeg或libjpeg-turbo使用中的一个注意事项
- mybatis和mysql中查询前六个月订单中每个月的总订单数
- shell脚本-计算1到100的和
- 整理一下Unity界面的知识
- 小草软路由-多网卡普通路由模式设置