Java ApacheHttpClient连接管理

Java ApacheHttpClient连接管理,java,apache-httpclient-4.x,Java,Apache Httpclient 4.x,我试图理解在实现中使用ApacheHttpClient管理http连接的最佳方法(不是我的)。我认为现在实现它的方式是一种浪费,但由于我对这个库不太熟悉,我想确认一下我的想法 考虑以下情况: 我在tomcat中有一个webapp,意思是多线程环境 我需要从Rest类访问Rest Web服务。每次对我的应用程序的请求都会创建一个新的Rest类实例,以便调用我需要的服务 选项1(当前已实现):类Rest实例化一个新的PoollightTPClientConnectionManager并发出请求。

我试图理解在实现中使用ApacheHttpClient管理http连接的最佳方法(不是我的)。我认为现在实现它的方式是一种浪费,但由于我对这个库不太熟悉,我想确认一下我的想法

考虑以下情况:

  • 我在tomcat中有一个webapp,意思是多线程环境
  • 我需要从Rest类访问Rest Web服务。每次对我的应用程序的请求都会创建一个新的Rest类实例,以便调用我需要的服务
选项1(当前已实现):类Rest实例化一个新的PoollightTPClientConnectionManager并发出请求。

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

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

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

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

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

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

如果你能给我一些关于这件事的想法,我将不胜感激。
我看过很多例子,但都是来自主函数和显式创建线程的简单例子。在tomcat这样的应用服务器上没有看到任何示例。

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


希望能有所帮助。

强烈建议选择2

根据选择2,这是最明智的选择

首先,它说:

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

HTTP/1.1声明HTTP连接可以被多次重复使用 默认情况下的请求数。符合HTTP/1.0的端点也可以使用 明确传达他们的偏好以保持一致的机制 连接处于活动状态,并将其用于多个请求。HTTP代理可以 在发生故障时,还要将空闲连接保持活动一段时间 后续请求需要连接到同一目标主机。 保持连接活跃的能力通常被称为 连接持久性。HttpClient完全支持连接 坚持

因此,在这一段之后,我们可以得出这样的结论:是的,每当我们想要发出HTTP请求时,实例化HTTP连接是一个非常糟糕的想法,而您在问题中所称的选项1并不是最好的方法

稍后在“池连接管理器”下会显示:

PoolighttpClientConnectionManager是一个更复杂的实现 管理客户端连接池并能够为 来自多个执行线程的连接请求。连接是 按每条路线汇集。对路由的请求,其中 管理器在池中已具有可用的永久连接,将 通过从池中租用连接而不是创建 全新的连接

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

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

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


因此,选项3是有道理的,但从重用昂贵资源的角度来看,这听上去并不比选项2好。

选项2。您希望尽可能广泛地共享连接。多个池只是浪费连接,一个