提问者:小点点

Apache HttpClient连接管理


我试图了解在实现中使用Apache HttpClient管理超文本传输协议连接的最佳方法(不是我的)。我认为它现在的实现方式是一种浪费,但由于我不太熟悉这个库,我想确认我的想法。

考虑这种情况:

  • 我在tomcat中有一个webapp,这意味着是一个多线程环境。
  • 我需要从Rest类到达一个Rest WebService。每个对我的应用程序的请求都会创建一个新的Rest类实例,以便调用我需要的服务。

选项1(目前已实现):类Rest实例化一个新的PoolingHttpClientConnectionManager并发出请求。

就我个人而言,我认为这完全是一种浪费。一次只有一个线程访问管理器的实例。所以,这种方法没有真正的好处。实际上最糟糕的是,我假设创建这个管理器可能很昂贵(?)。所以,实际上我们最终创建了多个PoolingHttpClientConnectionManager,每个线程一个(每个请求一个)。

选项2:类Rest只能将一个PoolingHttpClientConnectionManager实例化为一种单例。

然后来自tomcat的每个线程都会重用同一个连接管理器,每个线程只会创建新的httpClient。我认为这从池中获得了所有的好处,比如控制连接量和重用。但我不知道这对管理器来说是否是一个好的用途(我的猜测是它应该是Ok的,因为这个连接管理器的全部目的是在多线程环境中工作)。

选项3:类Rest可以实例化BasicHttpClientConnectionManager的一个新实例。

我尝试了这个并且工作得很好。这意味着每个线程都将有自己的单个连接管理器。即使这个管理器只有一个连接,因为我们每个线程有一个管理器,所以我们实现了并行执行。

我认为这种方法的缺点是没有限制。因此,如果我的应用程序收到太多请求,我们每次都会创建一个新的管理器,此外,我们不会重用到同一路由的连接。

我很感激你能给我关于这个问题的任何想法。我见过很多例子,但总是来自main函数和显式创建线程的简单示例。没有看到任何来自应用程序服务器(如tomcat)的示例。


共3个答案

匿名用户

强烈推荐选项2。

匿名用户

根据Apache CommonsHTTP客户端文档选项2是最明智的。

首先,它说:

从一台主机到另一台主机建立连接的过程相当复杂,涉及两个endpoint之间的多次数据包交换,这可能非常耗时。连接握手的开销可能很大,尤其是对于小型HTTP消息。如果可以重新使用打开的连接来执行多个请求,则可以实现更高的数据吞吐量。

HTTP/1.1声明,每个默认情况下,HTTP连接可以重复用于多个请求。HTTP/1.0兼容的endpoint还可以使用一种机制来显式地传达他们保持连接存活的偏好,并将其用于多个请求。HTTP代理还可以在一定时间内保持空闲连接存活,以防后续请求需要连接到同一目标主机。保持连接存活的能力通常被称为连接持久性。HttpClient完全支持连接持久性。

所以,在这一段之后,我们可以得出结论,是的,每次我们想要发出HTTP请求时实例化HTTP连接是一个非常糟糕的主意,你在问题中称之为选项1不是最好的方法。

后来在“池化连接管理器”下说:

PoolingHttpClientConnectionManager是一个更复杂的实现,它管理客户端连接池,并且能够为来自多个执行线程的连接请求提供服务。连接在每个路由的基础上进行池化。对于管理器已经在池中拥有可用持久连接的路由的请求,将通过从池中租用连接而不是创建全新的连接来提供服务。

因此,在阅读了这一段之后,我们可以得出结论,是的,由应用程序的所有线程共享单个连接池是有意义的。因此,理想情况下,您实例化一次并在需要获得HTTP连接的任何地方共享它。

最后,关于备选方案3,文件说:

BasicHttpClientConnectionManager是一个简单的连接管理器,一次只维护一个连接。即使这个类是线程安全的,它也应该只被一个执行线程使用。BasicHttpClientConnectionManager将努力为具有相同路由的后续请求重用连接。但是,如果持久连接的路由与连接请求的路由不匹配,它将关闭现有连接并为给定路由重新打开它。如果连接已经被分配,则抛出java. lang.IllegalStateException。

因此,选择3是有道理的,但就重用昂贵的资源而言,这听起来并不比选择2好。

匿名用户

实际上,我刚刚读到一个与此相关的问题,但在c#中,我不是这个问题的专家,基本上建议使用选项2。为每个连接创建一个新的连接管理器可能会导致性能不佳,因为它只为一个新连接创建一个新实例(它可能只是一个请求连接,但并没有实际使用它,它会耗尽httpclient管理器)。这个原因足以选择你的选项。这是线程链接的链接…

希望这个有帮助。