Apache HttpClient 连接管理
Apache HttpClient Connection Management
我正在尝试了解在实现(不是我的)中使用 Apache HttpClient 管理 http 连接的最佳方法。我认为它现在的实现方式是一种浪费,但由于我对这个库不太熟悉,所以我想确认一下我的想法。
考虑这种情况:
- 我有一个webapp在一个tomcat,意思是多线程环境。
- 我需要从 class Rest 访问 Rest WebService。对我的应用程序的每个请求都会创建一个新的 Rest class 实例,以便调用我需要的服务。
选项 1(当前已实现):class Rest 实例化一个新的 PoolingHttpClientConnectionManager 并发出请求。
就我个人而言,我认为这完全是浪费。一次只有一个线程访问管理器的实例。因此,这种方法并没有真正的好处。这实际上是最糟糕的,因为我假设这个管理器的创建成本可能很高(?)。因此,实际上我们最终创建了多个 PoolingHttpClientConnectionManager,每个线程一个(每个请求一个)。
选项 2:class Rest 只能将一个 PoolingHttpClientConnectionManager 实例化为一种单例。
然后 tomcat 中的每个线程将重用相同的连接管理器,并且每个线程只会创建新的 httpClient。
我认为这从池中获得了所有好处,比如控制连接数量和重用。但我不知道这对管理器是否有用(我的猜测是它应该没问题,因为这个连接管理器的全部目的是在多线程环境中工作)。
选项 3:class Rest 可以实例化一个新的 BasicHttpClientConnectionManager 实例。
我试过了,效果很好。这意味着每个线程都有自己的单一连接管理器。尽管这个管理器只有一个连接,但因为我们每个线程都有一个管理器,所以我们实现了并行执行。
我认为这种方法的缺点是没有限制。因此,如果我的应用程序收到太多请求,我们每次都会创建一个新的管理器,此外,我们不会重复使用同一路由的连接。
如果你能就此事给我任何想法,我将不胜感激。
我见过很多例子,但总是来自主函数的简单例子,并显式创建线程。没有看到来自应用程序服务器的任何示例,例如 tomcat.
实际上我刚刚读到一个与此相关的问题,但在 c# 中我不是这方面的专业人士,基本上推荐选项 2。
为每个连接创建一个新的连接管理器可能会导致性能下降,因为它只为一个新连接创建一个新实例(它可能只是一个请求连接但实际上并没有使用它,它会耗尽 httpclient 管理器)。这个理由足以让你选择。
这是线程
的 link
希望对您有所帮助。
强烈推荐选项 2。
根据 Apache Commons HTTP Client Documentation 选项 2 是最明智的。
首先,它说:
The process of establishing a connection from one host to another is
quite complex and involves multiple packet exchanges between two
endpoints, which can be quite time consuming. The overhead of
connection handshaking can be significant, especially for small HTTP
messages. One can achieve a much higher data throughput if open
connections can be re-used to execute multiple requests.
HTTP/1.1 states that HTTP connections can be re-used for multiple
requests per default. HTTP/1.0 compliant endpoints can also use a
mechanism to explicitly communicate their preference to keep
connection alive and use it for multiple requests. HTTP agents can
also keep idle connections alive for a certain period time in case a
connection to the same target host is needed for subsequent requests.
The ability to keep connections alive is usually refered to as
connection persistence. HttpClient fully supports connection
persistence.
因此,在该段之后,我们可以得出结论,是的,每次我们想要发出 HTTP 请求时都实例化 HTTP 连接是一个非常糟糕的主意,而您在问题中所说的选项 1 并不是最好的方法去吧。
然后在 "Pooling connection manager" 下显示:
PoolingHttpClientConnectionManager is a more complex implementation
that manages a pool of client connections and is able to service
connection requests from multiple execution threads. Connections are
pooled on a per route basis. A request for a route for which the
manager already has a persistent connection available in the pool will
be serviced by leasing a connection from the pool rather than creating
a brand new connection.
因此,在阅读本段之后我们可以得出结论,是的,让应用程序的所有线程共享一个连接池是有意义的。因此,理想情况下,您将它实例化一次,然后在需要获取 HTTP 连接的任何地方共享它。
最后,关于选项 3,文档说:
BasicHttpClientConnectionManager
is a simple connection manager that
maintains only one connection at a time. Even though this class is
thread-safe it ought to be used by one execution thread only.
BasicHttpClientConnectionManager
will make an effort to reuse the
connection for subsequent requests with the same route. It will,
however, close the existing connection and re-open it for the given
route, if the route of the persistent connection does not match that
of the connection request. If the connection has been already been
allocated, then java.lang.IllegalStateException is thrown.
因此,选项 3 是有道理的,但就重用昂贵的资源而言,这显然并不比选项 2 好。
我正在尝试了解在实现(不是我的)中使用 Apache HttpClient 管理 http 连接的最佳方法。我认为它现在的实现方式是一种浪费,但由于我对这个库不太熟悉,所以我想确认一下我的想法。
考虑这种情况:
- 我有一个webapp在一个tomcat,意思是多线程环境。
- 我需要从 class Rest 访问 Rest WebService。对我的应用程序的每个请求都会创建一个新的 Rest class 实例,以便调用我需要的服务。
选项 1(当前已实现):class Rest 实例化一个新的 PoolingHttpClientConnectionManager 并发出请求。
就我个人而言,我认为这完全是浪费。一次只有一个线程访问管理器的实例。因此,这种方法并没有真正的好处。这实际上是最糟糕的,因为我假设这个管理器的创建成本可能很高(?)。因此,实际上我们最终创建了多个 PoolingHttpClientConnectionManager,每个线程一个(每个请求一个)。
选项 2:class Rest 只能将一个 PoolingHttpClientConnectionManager 实例化为一种单例。
然后 tomcat 中的每个线程将重用相同的连接管理器,并且每个线程只会创建新的 httpClient。 我认为这从池中获得了所有好处,比如控制连接数量和重用。但我不知道这对管理器是否有用(我的猜测是它应该没问题,因为这个连接管理器的全部目的是在多线程环境中工作)。
选项 3:class Rest 可以实例化一个新的 BasicHttpClientConnectionManager 实例。
我试过了,效果很好。这意味着每个线程都有自己的单一连接管理器。尽管这个管理器只有一个连接,但因为我们每个线程都有一个管理器,所以我们实现了并行执行。
我认为这种方法的缺点是没有限制。因此,如果我的应用程序收到太多请求,我们每次都会创建一个新的管理器,此外,我们不会重复使用同一路由的连接。
如果你能就此事给我任何想法,我将不胜感激。 我见过很多例子,但总是来自主函数的简单例子,并显式创建线程。没有看到来自应用程序服务器的任何示例,例如 tomcat.
实际上我刚刚读到一个与此相关的问题,但在 c# 中我不是这方面的专业人士,基本上推荐选项 2。
为每个连接创建一个新的连接管理器可能会导致性能下降,因为它只为一个新连接创建一个新实例(它可能只是一个请求连接但实际上并没有使用它,它会耗尽 httpclient 管理器)。这个理由足以让你选择。
这是线程
希望对您有所帮助。
强烈推荐选项 2。
根据 Apache Commons HTTP Client Documentation 选项 2 是最明智的。
首先,它说:
The process of establishing a connection from one host to another is quite complex and involves multiple packet exchanges between two endpoints, which can be quite time consuming. The overhead of connection handshaking can be significant, especially for small HTTP messages. One can achieve a much higher data throughput if open connections can be re-used to execute multiple requests.
HTTP/1.1 states that HTTP connections can be re-used for multiple requests per default. HTTP/1.0 compliant endpoints can also use a mechanism to explicitly communicate their preference to keep connection alive and use it for multiple requests. HTTP agents can also keep idle connections alive for a certain period time in case a connection to the same target host is needed for subsequent requests. The ability to keep connections alive is usually refered to as connection persistence. HttpClient fully supports connection persistence.
因此,在该段之后,我们可以得出结论,是的,每次我们想要发出 HTTP 请求时都实例化 HTTP 连接是一个非常糟糕的主意,而您在问题中所说的选项 1 并不是最好的方法去吧。
然后在 "Pooling connection manager" 下显示:
PoolingHttpClientConnectionManager is a more complex implementation that manages a pool of client connections and is able to service connection requests from multiple execution threads. Connections are pooled on a per route basis. A request for a route for which the manager already has a persistent connection available in the pool will be serviced by leasing a connection from the pool rather than creating a brand new connection.
因此,在阅读本段之后我们可以得出结论,是的,让应用程序的所有线程共享一个连接池是有意义的。因此,理想情况下,您将它实例化一次,然后在需要获取 HTTP 连接的任何地方共享它。
最后,关于选项 3,文档说:
BasicHttpClientConnectionManager
is a simple connection manager that maintains only one connection at a time. Even though this class is thread-safe it ought to be used by one execution thread only.BasicHttpClientConnectionManager
will make an effort to reuse the connection for subsequent requests with the same route. It will, however, close the existing connection and re-open it for the given route, if the route of the persistent connection does not match that of the connection request. If the connection has been already been allocated, then java.lang.IllegalStateException is thrown.
因此,选项 3 是有道理的,但就重用昂贵的资源而言,这显然并不比选项 2 好。