在一次服务器异常的排查过程当中(服务器异常排查的过程我会另起文章),我们决定使用HttpClient4.X替代HttpClient3.X或者HttpConnection。
为什么使用HttpClient4?主要是HttpConnection没有连接池的概念,多少次请求就会建立多少个IO,在访问量巨大的情况下服务器的IO可能会耗尽。
HttpClient3也有连接池的东西在里头,使用MultiThreadedHttpConnectionManager,大致过程如下:
- MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
- HttpClient client = new HttpClient(connectionManager);...// 在某个线程中。
- GetMethod get = new GetMethod("http://jakarta.apache.org/");
- try {
- client.executeMethod(get);// print response to stdout
- System.out.println(get.getResponseBodyAsStream());
- } finally {
- // be sure the connection is released back to the connection
- managerget.releaseConnection();
- }
可以看出来,它的方式与jdbc连接池的使用方式相近,我觉得比较不爽的就是需要手动调用releaseConnection去释放连接。对每一个HttpClient.executeMethod须有一个method.releaseConnection()与之匹配。
HttpClient4在这点上做了改进,使用我们常用的InputStream.close()来确认连接关闭(4.1版本之前使用entity.consumeContent()来确认内容已经被消耗关闭连接)。具体方式如下:
- ...HttpClient client = null;InputStream in = null;
- try{
- client = HttpConnectionManager.getHttpClient();
- HttpGet get = new HttpGet();
- get.setURI(new URI(urlPath));
- HttpResponse response = client.execute(get);
- HttpEntity entity =response.getEntity();
- if( entity != null ){
- in = entity.getContent();
- ....
- }catch (Exception e){
- ....
- }finally{
- if (in != null){
- try{in.close ();}catch (IOException e){
- e.printStackTrace ();
- }
- }
- }
2012-03-06更新:
有网友提出调用in.close()是否会关闭底层socket,事情是这样的:
- 回复kangkang203:感谢你提出的这个问题。
- 首 先我文中提出的方法in.close()它会触发一个连接的释放这个连接将重新被连接管理器收回,官网的原文是这么说 的:“Closing the input stream will trigger connection release...the underlying connection gets released back to the connection manager”。 但是底层的socket是否会被关闭是不一定的,我看了部分源码(EofSensorInputStream)发现,大多数情况socket并不会关闭, 而是否关闭socket貌似是由一个Watcher去决定的。所以in.close的调用不会引起socket的关闭。
- 另外,由于http本身我们把它当做“短连接”,所以在一次请求交互完成后仍然打开socket的意义不是很大,毕竟它不像长连接那样在一个连接建立之后会有很多次数据交互。我们试用连接管理器的更多意义在于它对连接的管理。
好说完了连接池的使用流程,现在来说一说连接池在使用时最重要的几个参数。我用4.1的版本实现了一个简单的HttpConnectionManager,代码如下:
- public class HttpConnectionManager {
- private static HttpParams httpParams;
- private static ClientConnectionManager connectionManager;
- /**
- * 最大连接数
- */
- public final static int MAX_TOTAL_CONNECTIONS = 800;
- /**
- * 获取连接的最大等待时间
- */
- public final static int WAIT_TIMEOUT = 60000;
- /**
- * 每个路由最大连接数
- */
- public final static int MAX_ROUTE_CONNECTIONS = 400;
- /**
- * 连接超时时间
- */
- public final static int CONNECT_TIMEOUT = 10000;
- /**
- * 读取超时时间
- */
- public final static int READ_TIMEOUT = 10000;
- static {
- httpParams = new BasicHttpParams();
- // 设置最大连接数
- ConnManagerParams.setMaxTotalConnections(httpParams, MAX_TOTAL_CONNECTIONS);
- // 设置获取连接的最大等待时间
- ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT);
- // 设置每个路由最大连接数
- ConnPerRouteBean connPerRoute = new ConnPerRouteBean(MAX_ROUTE_CONNECTIONS);
- ConnManagerParams.setMaxConnectionsPerRoute(httpParams,connPerRoute);
- // 设置连接超时时间
- HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);
- // 设置读取超时时间
- HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT);
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
- connectionManager = new ThreadSafeClientConnManager(httpParams, registry);
- }
- public static HttpClient getHttpClient() {
- return new DefaultHttpClient(connectionManager, httpParams);
- }
- }
最大连接数、获取连接的最大等待时间、读取超时时间 这些配置应该比较容易理解,一般的连接池都会有这些配置,比较特别的是 每个路由(route)最大连接数 。
什么是一个route?
这里route的概念可以理解为 运行环境机器 到 目标机器的一条线路。举例来说,我们使用HttpClient的实现来分别请求 www.baidu.com 的资源和 www.bing.com 的资源那么他就会产生两个route。
这里为什么要特别提到route最大连接数这个参数呢,因为这个参数的默认值为2,如果 不设置这个参数值默认情况下对于同一个目标机器的最大并发连接只有2个!这意味着如果你正在执行一个针对某一台目标机器的抓取任务的时候,哪怕你设置连接 池的最大连接数为200,但是实际上还是只有2个连接在工作,其他剩余的198个连接都在等待,都是为别的目标机器服务的。
怎么样蛋疼吧,我是已经有过血的教训了,在切换到HttpClient4.1的起初没有注意到这个配置,最后使得服务承受的压力反而不如从前了,所以在这里特别提醒大家注意。
HttpClient4.X 教程下载:
关于版本的补充:
网友w2449008821提醒之后我才发现在HttpClient4.1+的版本ConnManagerParams已经被Deprecated了。
我在写这篇日志的时候时候的httpclient 版本是4.0.3,从4.0版本之后ConnManagerParams被Deprecated,没想到一个小版本升级会有这么大变化。
官网教程举例了新的连接池设置:
- SchemeRegistry schemeRegistry = new SchemeRegistry();
- schemeRegistry.register(
- new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
- schemeRegistry.register(
- new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
- ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry);
- // Increase max total connection to 200
- cm.setMaxTotalConnections(200);
- // Increase default max connection per route to 20
- cm.setDefaultMaxPerRoute(20);
- // Increase max connections for localhost:80 to 50
- HttpHost localhost = new HttpHost("locahost", 80);
- cm.setMaxForRoute(new HttpRoute(localhost), 50);
- HttpClient httpClient = new DefaultHttpClient(cm);
ConnManagerParams的功能被挪到了 ThreadSafeClientConnManager 和 HttpConnectionParams两个类:
static ConnPerRoute |
getMaxConnectionsPerRoute(HttpParams params) Deprecated. use ThreadSafeClientConnManager.getMaxForRoute(org.apache.http.conn.routing.HttpRoute)
|
static int |
getMaxTotalConnections(HttpParams params) Deprecated. use ThreadSafeClientConnManager.getMaxTotal()
|
static long |
getTimeout(HttpParams params) Deprecated. use HttpConnectionParams.getConnectionTimeout(HttpParams)
|
static void |
setMaxConnectionsPerRoute(HttpParams params, ConnPerRoute connPerRoute) Deprecated. use ThreadSafeClientConnManager.setMaxForRoute(org.apache.http.conn.routing.HttpRoute, int)
|
static void |
setMaxTotalConnections(HttpParams params, int maxTotalConnections) Deprecated. use ThreadSafeClientConnManager.setMaxTotal(int)
|
static void |
setTimeout(HttpParams params, long timeout) Deprecated. use HttpConnectionParams.setConnectionTimeout(HttpParams, int)
|
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e638
http://blog.csdn.net/shootyou/article/details/6415248
相关推荐
在用C3P0数据连接池的时候,一旦并发上来就坑不住了,因为C3P0存在BUG,c3p0在从连接池中获取和返回连接的时候,采用了异步的处理方式,使用一个线程池来异步的 把返回关闭了(没有真正关闭)的连接放入连接池中。...
public Pagi()//定义构造器,初始化每页显示的主题数和数据库的连接。 { intPageSize=4; //每页显示的记录数目 db = new DB(); } //Countsql:总记录的Query字符串。[形式为select count(*) from tablename] //...
#3191 修复 json-rpc 客户端因对端服务重启,导致连接池中的连接全部失效,新的请求进来时,首次使用皆会报错的问题。 新增 #3170 为 hyperf/watcher 组件新增了更加友好的驱动器 FindNewerDriver,支持 Mac Linux...
数据访问调整参数 为了获得较好的应用程序性能,可以通过 WebSphere Application Server 管理控制台调整一些数据访问资源。...请调整数据源和连接池的这些属性,以优化应用程序与数据存储器之间的事务的性能。
第七章 案例1通过委托实现异步调用 案例2使用定时器执行方法 ...HTTP协议下载文件 案例2如何利用流下载文件 案例3获取当前主机名和IP 案例4自制浏览器 案例5利用TCP协议实现通讯 案例7多线程...
在这个 CCNA 综合技能练习中,XYZ 公司结合使用 eBGP 和 PPP 实现 WAN 连接。其他技术包括 NAT、DHCP、静态和默认路由、适用于 IPv4 的 EIGRP、VLAN 间路由和 VLAN 配置。安全配置包括 SSH、端口安全、交换机安全和 ...
使用数据库连接池druid dubbo使用 1.1.11 集成Spring Cache,FastJson Spring Cache增加redis缓存实现 Mybatis使用二级缓存,增加redis实现 增加reactJs 增加Mybatis插件pageHelper,Mapper 1.1.12 使用draft富文本编辑...
1.0.5 从web项目迁移成maven项目 1.0.6 增加菜单框架ext实现,类路径调整 1.0.7 增加http工具类,demo例子 1.0.8 socket工具类,权限组件,菜单组件,jdbc分页支持多种数据库,ant路径...使用数据库连接池druid dubbo使用
Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。 Druid已经在阿里巴巴部署了超过600个应用,经过多年多生产环境大规模...
使用数据库连接池druid dubbo使用 1.1.11 集成Spring Cache,FastJson Spring Cache增加redis缓存实现 Mybatis使用二级缓存,增加redis实现 增加reactJs 增加Mybatis插件pageHelper,Mapper 1.1.12 使用draft富文本编辑...
快速稳定(连接池) 显式优于隐式。 缓冲区大小、连接池大小。 指定查询参数,查询函数中没有参数 不能配置多个后端,而是一个经过良好测试的后端 谷歌应用引擎支持 Cloudant 支持 非目标: 完整的 api 覆盖(在...
## 平台简介 可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手...16. 连接池监视:监视当期系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
数据库连接池使用方法 服务文件在/server/mysql/DbServer.php 简单地封装文件在/application/library/mysql/dbclient.php 配置在conf/application.ini中 ;数据库连接池配置 DbServer.async=true //配置是同步...
使用数据库连接池druid dubbo使用 1.1.11 集成Spring Cache,FastJson Spring Cache增加redis缓存实现 Mybatis使用二级缓存,增加redis实现 增加reactJs 增加Mybatis插件pageHelper,Mapper doc内有相关文档
cxxtools 是一种会经常使用的C++类库,主要的功能有:参数解析、BASE64编码解码、iconv接口、MD5编码、线程处理、Socket处理、动态异常安全的缓冲、dlopen\dlsym的封装、连接池模版、HTTP编程中的参数封装等。
连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 在线体验 admin/admin123 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。 演示地址:...
[timesUsed="连接最多能使用次数"] [frequency="连接池刷新周期"] [pause="几次连接不上数据库时暂停连接"] [trace="是否输出连接池日志"] [More="更多参数"] [weName="数据模块显示名"] [taskFrequency="暂未启用...
本书从最基础的JSP开发开始,循序渐进地介绍了JSP 开发技术,并涵盖了许多高级主题,如需要在企业级Web应用中使用的特性—Enterprise JavaBeans、JDBC 2.0、数据库连接池和自定义标签库。本书既适合初学者阅读,也...
功能支持清洁便捷的API 易于设置标题,Cookie,参数,过帐表格会话控制保持活动和连接池HTTP(S)代理支持重定向控制超时控制支持使用css选择器,regexp,json从响应主体中提取结果内容解码还有更多...安装go get ...