httpclient的并发连接问题
昨天的搜索系统又出状况了,几个库同时重建索引变得死慢。经过一个上午的复现分析,确定问题出现httpclient的使用上(我使用的是3.1这个被广泛使用的遗留版本)。搜索系统在重建索引时,是并发多个线程(默认是8个)不停的从PHP客户端取数据(当然,从另一个角度来说,搜索系统是客户端,PHP端是服务端),取回后放到一个队列里由单独的一个或多个线程更新索引。在测试环境复现发现,对于一个请求,PHP端打印耗时是1-2秒,但搜索端打印在4-6秒。这种耗时差别也就两种可能性,一个是PHP端返回到搜索端接受完耗时太长,另一个就是搜索端在真正发给PHP端数据前等待了很久。因为有了之前的jetty7的困顿,起初我怀疑是传输数据的问题。因为请求数据的代码部分我只是简单的使用了httpclient,所以只能从httpclient着手分析。我想到把PHP端和搜索端的请求起始和结束时间都打出来对照一下,不过在这样做之前我把搜索端的并发请求线程数调到了1,看下单线程情况下效果如何,结果惊奇地发现PHP端和搜索端的耗时相近。所以,可以确定,是httpclient的并发连接处理上可能存在问题。不消说,翻开httpclient API中和配置相关的接口,结果找到HttpConnectionManagerParams类中下面两个函数:
public void setDefaultMaxConnectionsPerHost(int maxHostConnections); public void setMaxTotalConnections(int maxTotalConnections);
httpclient在处理请求连接方面使用了连接池,它内部实际上有两种连接池,一种是全局的ConnectionPool,一种是每主机(per-host)HostConnectionPool。参数maxHostConnections就HostConnectionPool中表示每主机可保持连接的连接数,maxTotalConnections是ConnectionPool中可最多保持的连接数。每主机的配置类是HostConfiguration,HttpClient有个int executeMethod(final HostConfiguration hostConfiguration, final HttpMethod method)方法可以指定使用哪个HostConfiguration,不过多数情况都是不显示指定HostConfiguration,这样httpclient就用了默认的HostConfiguration=null,也就是说所有的请求可以认为指自同一个主机。如果不设置这两个参数,httpclient自然会用默认的配置,也就是MultiThreadedHttpConnectionManager中的:
public static final int DEFAULT_MAX_HOST_CONNECTIONS = 2; // Per RFC 2616 sec 8.1.4 ? public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20;
默认的maxHostConnections大小只有2,也就是说,在我并发8个线程请求数据时,实际上会有6个线程处于等待被调度,这也就解释上面的现象了。再看看上面的注释,我从http://www.faqs.org/rfcs/rfc2616.html找到从了RFC 2616 sec 8.1.4 Practical Considerations段落的最后一段:
Clients that use persistent connections SHOULD limit the number of simultaneous connections that they maintain to a given server. A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy. A proxy SHOULD use up to 2*N connections to another server or proxy, where N is the number of simultaneously active users. These guidelines are intended to improve HTTP response times and avoid congestion.
看这叙述,也就表明人家httpclient设置maxHostConnections为2是有根有据的。不过,这种设置显然适合的是浏览器这种客户端,但我相信,多数使用httpclient并不希望有这种默认的限制。而它默认的只有20的maxTotalConnections也太有些吝啬了。我后来浏览solr的客户端server类CommonsHttpSolrServer的代码发现了下面的段落,solr要比我更了解httpclient:
_httpClient = (client == null) ? new HttpClient(new MultiThreadedHttpConnectionManager()) : client; if (client == null) { // set some better defaults if we created a new connection manager and client // increase the default connections this.setDefaultMaxConnectionsPerHost( 32 ); // 2 this.setMaxTotalConnections( 128 ); // 20 }
对于httpclient,特别指出的是它的MultiThreadedHttpConnectionManager,看名字好像是多线程并发请求似的,其实不是,但它也确实用到了多线程,那是在发现连接不够用时起个等待线程wait信号,这个名称的含义应该是多线程情况线程安全的HttpConnectionManager。
使用httpclient还有两点经验,一个是创建的MultiThreadedHttpConnectionManager 实例最好是全局的,否则会有多个连接池,而HttpClient是线程安全的,可以多个实例。另一个是,在处理请求的最后,也就是finnaly里中,要调用method.releaseConnection();回收连接,否则连接池就可能会爆了。
补充:写完之后倒在床上,我又想起了几个问题,这里补充上:
1、系统原先重建索引隐约记得速度还是可以的,为什么现在变慢得如此明显?这有两方面的原因,一个是原来系统取数据是用的单线程(我后来发现单取数据取数据速度跟不上更新索引的速度所以改成多线程),另一个是,当时重建没有一下子同时开启数个库。所以,即便是同样的代码,环境变了,效果也可能变了。当这种改变悄然发生了,程序员却没有捕捉到,才会第一直觉感到问题的诡异。
2、对于长时间不能获得连接的情况,httpclient是否有warn日志报出来?因为我使用了httpclient的getResponseBodyAsStream方法,而它会打出warn日志,所以我是关掉了httpclient的warn级别的。所以,我又检查了httpclient的代码,可惜没看到相关warning log,这点httpclient可以改进下。不过httpclient现在都是4时代了,而我使用的还是3.1的,而3.x已经被停止更新了,所以再采用httpclient可以考虑4版本的,尽管现在能见到的代码几乎都是用的3.x系列的。
3、httpclient的文档是否有特别提到连接数配置的情况?我翻看了一下,确实在关于threading一页中有提到。不过,我等使用它时显然没有完整阅毕它的文档。或许,httpclient给出个明显的最佳实践到能引起使用者的注意,否则误用的情况还是会时有发生。不信,google之。
httpclient的并发连接问题的更多相关文章
- C#多线程环境下调用 HttpWebRequest 并发连接限制
C#多线程环境下调用 HttpWebRequest 并发连接限制 .net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如 win ...
- 【原创】高性能网络编程(二):上一个10年,著名的C10K并发连接问题
1.前言 对于高性能即时通讯技术(或者说互联网编程)比较关注的开发者,对C10K问题(即单机1万个并发连接问题)应该都有所了解."C10K"概念最早由Dan Kegel发布于其个人 ...
- 多线程调用HttpWebRequest并发连接限制
.net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如 windows xp , windows 7 下默认是2,在服务器操作 ...
- 大并发连接的oracle在Linux下内存不足的问题的分析
大并发连接的oracle在Linux下内存不足的问题的分析 2010-01-28 20:06:21 分类: Oracle 最近一台装有Rhel5.3的40G内存的机器上有一个oracle数据库,数据库 ...
- (五)通过Python的select监控多个描述符实现并发连接
概述 本文通过使用select改写之前的服务器程序通过监控多个套接字描述符来实现并发连接并加入了一些机制让程序更加健壮,不过我们所有的实验都是建立在单词发送数据不会超过1024字节,如果超过你需要做特 ...
- Nginx 限制并发连接和并发请求数配置
Nginx限制并发连接和并发请求数配置 by:授客 QQ:1033553122 测试环境 nginx-1.10.0 配置介绍 查看是否内置模块 # pwd /mnt/nginx-1.10.0 ...
- 【转】C#多线程环境下调用 HttpWebRequest 并发连接限制
.net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如 windows xp , windows 7 下默认是2,在服务器操作 ...
- C10K并发连接_转
转载:http://blog.csdn.net/wangtaomtk/article/details/51811011 1 C10K问题 大家都知道互联网的基础就是网络通信,早期的互联网可以说是一个小 ...
- 多线程环境下调用 HttpWebRequest 并发连接限制
.net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如 windows xp , windows 7 下默认是2,在服务器操作 ...
随机推荐
- WebSlides - 轻松制作漂亮的 HTML 幻灯片(演讲稿)
WebSlides 是一个开源的 HTML 幻灯片项目,能够帮助熟悉前端语言的开发者快速制作出效果精美的幻灯片.页面中的每个 <section> 都是一个独立的幻灯片,只需要很少的 CSS ...
- Spring: 读取 .properties 文件地址,json转java对象,el使用java类方法相关 (十三)
1. 在Java中获取 .properties 文件的路径 (src/main/resources 下) ProjectName |---src/main/java |---src/main/reso ...
- 第10月第5天 v8
1. brew install v8 http://www.cnblogs.com/tinyjian/archive/2017/01/17/6294352.html http://blog.csdn. ...
- 第5月第10天 node.js的request模块
1.node.js的request模块 http://www.cnblogs.com/meteoric_cry/archive/2012/08/18/2645530.html
- (A - 整数划分 HYSBZ - 1263)(数组模拟大数乘法)
题目链接:https://cn.vjudge.net/problem/HYSBZ-1263 题目大意:中文题目 具体思路:先进了能的拆成3,如果当前剩下的是4,就先不减去3,直接乘4,如果还剩2的话, ...
- Git常见错误处理
如果输入$ Git remote add origin git@github.com:djqiang(github帐号名)/gitdemo(项目名).git 提示出错信息:fatal: remo ...
- Dream------Hbase--0.94版本和0.98/1.X版本api变动
Dream------Hbase--0.94版本和0.98/1.X版本api变动 网上好多说getQualifier.getValue.getRow被..Array代替了,其实并不是的. 1. Int ...
- mount过程分析之六——挂载关系(图解)【转】
转自:https://blog.csdn.net/zr_lang/article/details/40343899 引言 写到这里我们已经从mount文件系统调用的入口开始,分析到内核的mount,通 ...
- %08lx
u-boot中代码如下: debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr); 对应设备上的打印消息如下: N ...
- centos7 部署 open-falcon 0.2.0
=============================================== 2019/4/29_第3次修改 ccb_warlock 更新 ...