多线程应用程序中的 Apache HttpClient 和 HttpConnection
Apache HttpClient and HttpConnection in a multithreaded applicatio
在我的多线程应用程序中,我向一些 http 服务器发送一些 http 请求,我会说 10 个服务器,每个服务器 300 个不同的请求,大约每小时一次,没什么大不了的。
我的问题是:我应该为所有传出连接保留一个 HttpClient 吗?也许每个唯一的目标服务器一个?或者每"iteration"一个(每小时开始大约需要10分钟)?
我目前对每个请求使用一个 PoolingHttpClientConnectionManager
和 HttpClientBuilder.setConnectionManager(connectionManager).build()
。
我有一种真正的资源浪费的感觉,我也看到每个服务器的许多连接处于 ESTABLISHED
状态,尽管我使用的是池连接管理器。 (每个服务器的请求是一个一个发送的,不是并发的)
我会说如果它没坏就不要修理它。我的意思是只要最简单的配置满足您的需求就可以使用它,并且不要为了满足未来的可扩展性需求而引入任何复杂性。额外的部分意味着额外的复杂性,也意味着更多的错误。一旦您看到当前配置不再承受增加的负载,请进行估算并添加资源。希望对您有所帮助
在您的客户端请求的 HTTP 1.0 header 中,您需要
Connection: keep-alive
但是,这只是一个请求,您正在连接的服务器可能会断开连接。
HTTP 1.1 默认提供此功能,但默认 time-out 非常短。也许那里可能有一些配置。无论如何,如果您在 header 中收到带有 Connection: close
的响应,您必须关闭连接。
更多详细信息,请参阅 rfc2616,尤其是第 8 节 "Persistent connections"
因此,似乎正确的做法是确保 HTTP 1.1 处理(默认情况下连接在 1.1 中保持打开状态)并且不对 HttpClient 执行任何操作 "special"。 According to the second and third sections of the HttpClient homepage,默认情况下,客户端将保持尽可能长的持久连接。
我的建议是(如果在客户端连接端添加例程/线程/控制器)在同一范围内对特定服务器/端口的所有相关连接进行排序(全部在同一线程上或在相同的顺序),这可能会降低您 运行 进入连接关闭逻辑的可能性;但是,您不能真正强制连接保持打开状态(原因很明显)。
我同意@Michael Gantman 不修复它的观点。
我会说修复与否取决于您的负载配置文件。
保持还是不保持联系?
例如,如果您一次向 10 个服务器发出 300 个请求,然后您在一个小时内没有做任何事情,那么 资源明智 它不会在整个小时内保持任何 TCP/IP 连接打开(因为使用 HTTP/1.1)是有意义的。
但是,如果您每 5 秒与服务器通信一次,您可能会考虑保持连接打开。此外,如果您想通过消除重复建立连接来最大程度地减少延迟,您可以考虑保持连接打开。
为此,您必须使用 HTTP/1.1。你可以找到很多例子,例如
要保留多少个连接?
同样,取决于您的负载配置文件。你说你有 10 台服务器。如果您连续为一台服务器发送数据,那么每个服务器一个 http/1.1 的 http 连接就足够了。然而,如果你想做一些更快速的事情(例如并行上传两张图片),那么你可以对同一台服务器打开多个连接。 (当然,这意味着您的应用程序是真正的多线程。)
结论
如果它不是时间关键型应用程序,最简单的方法是不要汇集任何东西,只要在有数据要发送时才访问服务器。您可以开始对此进行过度优化,并以严重的意外复杂性为代价争取 10 毫秒的改进。
I'm currently using a single PoolingHttpClientConnectionManager, and HttpClientBuilder.setConnectionManager(connectionManager).build() for every request.
为每个请求构建一个新的 HttpClient 是一种巨大的浪费。您应该为每个配置(每个客户端可以有不同的连接管理器、最大并发请求数等)或应用程序的每个独立模块使用一个 HttpClient(以免在其他独立模块之间创建依赖关系)。
另外不要忘记 .build()
returns 一个 CloseableHttpClient
这意味着你应该在使用完后调用 httpClient.close()
否则你可能会泄漏资源。
更新以回应@Nati 的评论:
what will be "wasted" ? is HttpClient a heavy object ?
Here you can see the source code for the creation of an http client. 如您所见,它有很多代码,对每个请求都执行毫无意义。这种不必要的消耗 CPU 并产生大量垃圾,从而降低了整个应用程序的性能。你做的分配越少越好!换句话说,为每个请求创建新客户端没有好处——只有缺点。
does it make any sense of keeping it as a bean for the entire lifespan of the application
恕我直言,除非很少(非常)很少使用它。
relation between the HttpConnection and HttpClient
每个http客户端可以执行多个http请求。每个请求都在客户端的上下文中执行(它的配置——即代理、并发、保持活动等)每个对请求的响应都必须关闭(reset()、close(),不记得确切的名称) 以释放连接,以便它可以重新用于另一个请求。
在我的多线程应用程序中,我向一些 http 服务器发送一些 http 请求,我会说 10 个服务器,每个服务器 300 个不同的请求,大约每小时一次,没什么大不了的。
我的问题是:我应该为所有传出连接保留一个 HttpClient 吗?也许每个唯一的目标服务器一个?或者每"iteration"一个(每小时开始大约需要10分钟)?
我目前对每个请求使用一个 PoolingHttpClientConnectionManager
和 HttpClientBuilder.setConnectionManager(connectionManager).build()
。
我有一种真正的资源浪费的感觉,我也看到每个服务器的许多连接处于 ESTABLISHED
状态,尽管我使用的是池连接管理器。 (每个服务器的请求是一个一个发送的,不是并发的)
我会说如果它没坏就不要修理它。我的意思是只要最简单的配置满足您的需求就可以使用它,并且不要为了满足未来的可扩展性需求而引入任何复杂性。额外的部分意味着额外的复杂性,也意味着更多的错误。一旦您看到当前配置不再承受增加的负载,请进行估算并添加资源。希望对您有所帮助
在您的客户端请求的 HTTP 1.0 header 中,您需要
Connection: keep-alive
但是,这只是一个请求,您正在连接的服务器可能会断开连接。
HTTP 1.1 默认提供此功能,但默认 time-out 非常短。也许那里可能有一些配置。无论如何,如果您在 header 中收到带有 Connection: close
的响应,您必须关闭连接。
更多详细信息,请参阅 rfc2616,尤其是第 8 节 "Persistent connections"
因此,似乎正确的做法是确保 HTTP 1.1 处理(默认情况下连接在 1.1 中保持打开状态)并且不对 HttpClient 执行任何操作 "special"。 According to the second and third sections of the HttpClient homepage,默认情况下,客户端将保持尽可能长的持久连接。
我的建议是(如果在客户端连接端添加例程/线程/控制器)在同一范围内对特定服务器/端口的所有相关连接进行排序(全部在同一线程上或在相同的顺序),这可能会降低您 运行 进入连接关闭逻辑的可能性;但是,您不能真正强制连接保持打开状态(原因很明显)。
我同意@Michael Gantman 不修复它的观点。
我会说修复与否取决于您的负载配置文件。
保持还是不保持联系?
例如,如果您一次向 10 个服务器发出 300 个请求,然后您在一个小时内没有做任何事情,那么 资源明智 它不会在整个小时内保持任何 TCP/IP 连接打开(因为使用 HTTP/1.1)是有意义的。
但是,如果您每 5 秒与服务器通信一次,您可能会考虑保持连接打开。此外,如果您想通过消除重复建立连接来最大程度地减少延迟,您可以考虑保持连接打开。
为此,您必须使用 HTTP/1.1。你可以找到很多例子,例如
要保留多少个连接?
同样,取决于您的负载配置文件。你说你有 10 台服务器。如果您连续为一台服务器发送数据,那么每个服务器一个 http/1.1 的 http 连接就足够了。然而,如果你想做一些更快速的事情(例如并行上传两张图片),那么你可以对同一台服务器打开多个连接。 (当然,这意味着您的应用程序是真正的多线程。)
结论
如果它不是时间关键型应用程序,最简单的方法是不要汇集任何东西,只要在有数据要发送时才访问服务器。您可以开始对此进行过度优化,并以严重的意外复杂性为代价争取 10 毫秒的改进。
I'm currently using a single PoolingHttpClientConnectionManager, and HttpClientBuilder.setConnectionManager(connectionManager).build() for every request.
为每个请求构建一个新的 HttpClient 是一种巨大的浪费。您应该为每个配置(每个客户端可以有不同的连接管理器、最大并发请求数等)或应用程序的每个独立模块使用一个 HttpClient(以免在其他独立模块之间创建依赖关系)。
另外不要忘记 .build()
returns 一个 CloseableHttpClient
这意味着你应该在使用完后调用 httpClient.close()
否则你可能会泄漏资源。
更新以回应@Nati 的评论:
what will be "wasted" ? is HttpClient a heavy object ?
Here you can see the source code for the creation of an http client. 如您所见,它有很多代码,对每个请求都执行毫无意义。这种不必要的消耗 CPU 并产生大量垃圾,从而降低了整个应用程序的性能。你做的分配越少越好!换句话说,为每个请求创建新客户端没有好处——只有缺点。
does it make any sense of keeping it as a bean for the entire lifespan of the application
恕我直言,除非很少(非常)很少使用它。
relation between the HttpConnection and HttpClient
每个http客户端可以执行多个http请求。每个请求都在客户端的上下文中执行(它的配置——即代理、并发、保持活动等)每个对请求的响应都必须关闭(reset()、close(),不记得确切的名称) 以释放连接,以便它可以重新用于另一个请求。