`
san_yun
  • 浏览: 2638732 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

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中的:

    /** The default maximum number of connections allowed per host */

    public
 static
 final
 int
 DEFAULT_MAX_HOST_CONNECTIONS =
 2
;
   // Per RFC 2616 sec 8.1.4

 
    /** The default maximum number of connections allowed overall */

    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之。

分享到:
评论

相关推荐

    使用java的HttpClient实现多线程并发

    通过使用HttpClient的连接池和多线程,我们可以有效地并发执行HTTP GET请求,同时控制并发数量,避免过多的网络连接导致服务器压力过大。这种方式提高了请求效率,减少了资源消耗,并且遵循了最佳实践。

    httpclient4.5.5所有包

    - 对于高并发场景,应适当调整连接池参数,如最大连接数、超时时间等。 HttpClient 4.5.5 作为一个成熟的 HTTP 客户端库,不仅提供了丰富的功能,还具有良好的可扩展性和灵活性。开发者可以根据具体需求对其进行...

    httpclient

    HttpClient也支持异步操作,通过`HttpAsyncClient`类,可以在回调函数中处理响应,适合于高并发场景。 总的来说,HttpClient是Java中强大的HTTP客户端工具,能够满足各种复杂的HTTP请求需求。其丰富的功能和高度可...

    httpClient需要的jar包

    HttpClient是Apache基金会开发的一个Java库,它为Java程序员提供了一个强大的、灵活的、稳定的、功能丰富的客户端HTTP通信框架。...同时,及时关注Apache HttpClient的更新,以便利用新特性并修复已知问题。

    httpclient4.2.1.zip

    1. **多线程支持**:HttpClient 4.2.1支持多线程并发请求,可以高效地处理大量并发连接,提升了处理能力。 2. **连接管理**:它提供了连接池管理,允许重用已建立的TCP连接,减少网络延迟,提高整体性能。 3. **...

    org.apache.commons.httpclient

    5. **连接管理**:使用`HttpConnectionManager`管理连接池,控制并发连接数,重用连接。 6. **认证与安全**:实现基本认证、摘要认证,配置SSL/TLS连接,处理证书问题。 7. **性能优化**:使用连接池提高性能,控制...

    httpclient-4.5.3中文版文档,很实用

    1. **HTTP/1.1和HTTP/2支持**:HttpClient 4.5.3支持HTTP协议的最新版本,可以处理多路复用连接,提高了并发性能。 2. **连接管理**:HttpClient提供了`HttpConnectionManager`接口,用于管理到服务器的连接。默认...

    httpclient4.3工具类

    10. **线程安全**:为了适应多线程环境,`httpclientUtils`可能已经考虑了HttpClient实例的线程安全问题,确保在并发环境中正确使用。 在实际使用`httpclientUtils`时,开发者可以通过调用工具类提供的方法,如`...

    httpclient3.1 javadoc chm版

    HttpClient允许进行多线程并发请求,但需要注意线程安全问题。此外,合理设置连接超时、重试策略、连接池大小等参数也能显著提升性能。 九、与其他库的集成 HttpClient可以方便地与Spring框架、JUnit测试等结合使用...

    httpclient-4.5.3.zip

    - **连接管理**:通过`HttpConnectionManager`,HttpClient可以管理多个并发连接,实现高效的连接复用,降低网络延迟。 - **请求和响应处理**:HttpClient提供了`HttpRequestExecutor`和`HttpResponseHandler`接口...

    HTTPClient 的一个封装

    - **连接池管理**:通过`PoolingHttpClientConnectionManager`管理连接,提高性能和并发能力。 - **异步处理**:使用`HttpAsyncClient`进行非阻塞I/O,提高响应速度。 - **Cookie管理**:处理服务器返回的Cookie,...

    httpclient-4.5.3官方API中文文档_最新译版_2886K

    5. 异步请求:HttpClient提供异步执行请求的功能,可以实现非阻塞I/O,提高并发性能。 五、HttpClient的应用场景 HttpClient广泛应用于Web服务调用、爬虫程序、数据同步、自动化测试等领域。例如,在Web服务API调用...

    使用HttpClient必须的jar包

    7. **异步处理**:HttpClient 4.5以上版本提供了异步客户端API,可以并发处理多个请求,提高应用的并发性能。 8. **SSL/TLS支持**:HttpClient可以配置为使用HTTPS协议,需要`httpmime-x.x.x.jar`(处理MIME类型,...

    httpclient4.5 jar包

    HttpClient 4.5引入了`PoolingHttpClientConnectionManager`,它负责管理连接池,自动回收和复用连接。通过配置最大连接数、每个路由的最大连接数以及连接超时等参数,可以有效控制资源使用。 4. **异步编程支持**...

    HttpClient-4.3.6

    - **连接管理**:HttpClient提供了高级的连接管理机制,包括连接池(Connection Pooling)和智能重用,有效解决了HTTP连接的创建和关闭问题,提高了性能。 - **认证与安全**:支持多种身份验证机制,如基本认证、...

    httpclient-4.5.3 api 中文版

    1. **连接管理**:HttpClient 提供了`HttpClientConnectionManager`接口,用于管理HTTP连接。这个接口的实现,如`PoolingHttpClientConnectionManager`,允许复用HTTP连接,提高性能并减少服务器负载。你可以通过...

    httpclient-4.5jar包

    2. 连接管理器升级,提供了更智能的连接池管理,可以更好地控制并发连接数量和超时策略。 3. 支持HTTP/2和SPDY协议,增强了与现代服务器的兼容性。 4. 提供了更多的重试和恢复策略,增强了网络不稳定情况下的健壮性...

    httpClient

    在高并发场景下,HttpClient的线程安全性和连接池管理能力显得尤为重要。通过合理配置,可以在多线程环境中高效地处理请求。 7. **连接管理**: HttpClient的连接管理策略可以根据实际需求调整,例如设置最大连接...

Global site tag (gtag.js) - Google Analytics