HttpClient使用高并发请求连接池
连接池技术作为创建和管理连接的缓冲池技术,目前已广泛用于诸如数据库连接等长连接的维护和管理中,能够有效减少系统的响应时间,节省服务器资源开销。其优势主要有两个:其一是减少创建连接的资源开销,其二是资源的访问控制。连接池管理的对象是长连接,对于HTTP连接是否适用,我们需要首先回顾一下长连接和短连接。
所谓长连接是指客户端与服务器端一旦建立连接以后,可以进行多次数据传输而不需要重新建立连接,而短连接则每次数据传输都需要客户端和服务器端建立一次连接。长连接的优势在于省去了每次数据传输连接建立的时间开销,能够大幅度提高数据传输的速度,对于P2P应用十分适合,但是对于诸如Web网站之类的B2C应用,并发请求量大,每一个用户又不需频繁操作的场景下,维护大量的长连接对服务器无疑是一个巨大的考验。而此时,短连接可能更加适用。但是短连接每次数据传输都需要建立连接,我们知道HTTP协议的传输层协议是TCP协议,TCP连接的建立和释放分别需要进行3次握手和4次挥手,频繁的建立连接即增加了时间开销,同时频繁的创建和销毁Socket同样是对服务器端资源的浪费。所以对于需要频繁发送HTTP请求的应用,需要在客户端使用HTTP长连接。
HTTP连接是无状态的,这样很容易给我们造成HTTP连接是短连接的错觉,实际上HTTP1.1默认即是持久连接,HTTP1.0也可以通过在请求头中设置Connection:keep-alive使得连接为长连接。既然HTTP协议支持长连接,我们就有理由相信HTTP连接同样需要连接池技术来管理和维护连接的建立和销毁。HTTP Client4.0的ThreadSafeClientConnManager实现了HTTP连接的池化管理,其管理连接的基本单位是Route(路由),每个路由上都会维护一定数量的HTTP连接。这里的Route的概念可以理解为客户端机器到目标机器的一条线路,例如使用HttpClient的实现来分别请求 www.163.com 的资源和 www.sina.com 的资源就会产生两个route。缺省条件下对于每个Route,HttpClient仅维护2个连接,总数不超过20个连接,显然对于大多数应用来讲,都是不够用的,可以通过设置HTTP参数进行调整。
两个主机建立连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并且也很耗时间。Http连接需要的三次握手开销很大,这一开销对于比较小的http消息来说更大。但是如果我们直接使用已经建立好的http连接,这样花费就比较小,吞吐率更大。 传统的HttpURLConnection并不支持连接池,如果要实现连接池的机制,还需要自己来管理连接对象。对于网络请求这种底层相对复杂的操作,个人以为如果有可用的其他方案,也没有必要自己去管理连接对象。除了HttpURLConnection,大家肯定还知道HttpClient。一般情况下,普通使用HttpClient已经能满足我们的需求,不过有时候,在我们需要高并发大量的请求网络的时候,还是用“连接池”这样的概念能提升吞吐量。
代码:
RequestConfig.Builder builder = RequestConfig.custom();
// 单位毫秒 默认3分钟
builder.setConnectTimeout(10000);
builder.setSocketTimeout(10000);
PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager();
clientConnectionManager.setMaxTotal(500);
clientConnectionManager.setDefaultMaxPerRoute(300);
HttpClientBuilder clientBuilder = HttpClients.custom()
.setConnectionManager(clientConnectionManager)
.setDefaultRequestConfig(builder.build());
CloseableHttpClient httpClient = clientBuilder.build();
String urlStr = "http://www.baidu.com";
HttpGet httpGet = new HttpGet(urlStr);
CloseableHttpResponse response = httpClient.execute(httpGet);
HttpEntity http = response.getEntity();
String result = EntityUtils.toString(http, "utf-8");
EntityUtils.consume(http);
每个路由默认保持300个连接,最大不错过500个连接;如果某个路由被访问的非常频繁,可以占用较多的连接;
————————————————
版权声明:本文为CSDN博主「Firm陈」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42408447/article/details/121033946