最近使用httpclient总结的几条注意事项
Posted 不识君的荒漠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近使用httpclient总结的几条注意事项相关的知识,希望对你有一定的参考价值。
httpclient版本
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
连接管理
1. 默认使用连接池的连接管理器
httpclient默认使用的PoolingHttpClientConnectionManager这个类作为连接管理器,当然还提供了另外一个连接管理的类:BasicHttpClientConnectionManager。
PoolingHttpClientConnectionManager与BasicHttpClientConnectionManager的区别是,前者池化连接,也就是说,缓存一些长连接,在并发过高的情况下连接池的性能可是很明显的,毕竟高并发的时候,连接建立的过程也是比较耗时的,使用连接池,如果服务器响应很快的情况下,TPS可以有一个倍数的提升。后者是只缓存一个连接,如果下次请求与缓存的连接的路由信息不一致,则关闭缓存连接,重新建立一条新连接。
以前没怎么用过httpclient,刚开始使用的时候,我本来以为httpclient默认并未使用连接池,后来,我使用100个线程压测服务器的某个接口的时候,查看TCP连接信息,发现在一直都是只有2个连接建立状态,我使用的服务器,设置了100个工作线程,正常情况下应该是会出现成百上千甚至上万个TCP连接信息,有100个连接建立的状态,然后debug源码查找原因的时候,才发现它默认使用的就是连接池管理器,非常nice。
建议:使用连接池就行,一般不用更换为BasicHttpClientConnectionManager,但是需要对这个连接池管理器的相关配置做下调整,看下文。
2. 连接池配置
有几个默认配置如下:
最大连接数:20
每个路由最大连接数:2
获取连接的等待时间:-1(一直等下去,直到拿到可用连接)
最大连接数指的是一个客户端可以与服务器建立的最大连接数,每个路由最大连接数是指1个主机进程允许建立的最大连接数,一个路由信息的标志大概这个样子:http://127.0.0.1:8080。获取连接的等待时间是当请求过来时,已经没有可用连接,需要等待正在使用的连接释放之后,才有可用连接获取到的等待时间,默认是无限等下去,可以设置一个时间,单位毫秒。当前超过这个时间的时候,抛出异常直接返回。
p.s. 关于连接管理这部分有兴趣可以看下源码,实现并不复杂。
连接数默认的配置值还是比较小的,在实际场景中应当根据需要设置的大点。如下示例:
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(2000);// 最大连接数
connectionManager.setDefaultMaxPerRoute(100);//默认连接数
p.s. 也可以设置不同路由的最大连接数设置不同的值,并不一定是全局统一的值。
3. 获取连接的等待时间设置生效问题
我本来是这样设置的:
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// ... 连接池管理器自定义配置
RequestConfig requestConfig = RequestConfig
.custom()
//...其它配置
.setConnectionRequestTimeout(1000)
.build();
CloseableHttpClient httpClient = HttpClients
.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
因为我看到RequestConfig类提供的有设置获取连接的等待时间的接口,测试的时候,发现不生效,后来debug源码的时候,才发现根本不会读取这个配置。
想要这个配置生效,可以在构建HttpRequestBase或者它的子类如HttpGet时,设置RequestConfig,它下面的实现是从这里获取连接等待超时的值设置(我也是dubug的几遍源码,没有找到其它突破口,最终从源码中推测出这种设置,如有其它好的方案,欢迎告知),如下示例:
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// ... 连接池管理器自定义配置
RequestConfig requestConfig = RequestConfig
.custom()
//...其它配置
.setConnectionRequestTimeout(1000)
.build();
CloseableHttpClient httpClient = HttpClients
.custom()
.setConnectionManager(connectionManager)
/*.setDefaultRequestConfig(requestConfig)*/
.build();
HttpGet httpGet = new HttpGet();
httpGet.setConfig(requestConfig);
httpClient.execute(httpGet);
p.s. 我上面的代码都是个示例,并不能直接来用,能说明意思就行,真正的实现还是稍为复杂点的,包括https协议的处理以及一些其它相关配置。
以上是关于最近使用httpclient总结的几条注意事项的主要内容,如果未能解决你的问题,请参考以下文章