Java 多线程应用程序中的Apache HttpClient和HttpConnection

Java 多线程应用程序中的Apache HttpClient和HttpConnection,java,multithreading,apache-httpclient-4.x,apache-httpcomponents,Java,Multithreading,Apache Httpclient 4.x,Apache Httpcomponents,在我的多线程应用程序中,我向一些http服务器发送一些http请求,我会说10个服务器,每个服务器300个不同的请求,大约每小时一次,没什么大不了的 我的问题是:我应该为所有传出连接保留一个HttpClient吗?每个唯一的目标服务器可能有一个?或者每次“迭代”一次(每小时开始时大约需要10分钟) 我目前正在为每个请求使用一个poollighttpclientconnectionmanager和HttpClientBuilder.setConnectionManager(connectionMa

在我的多线程应用程序中,我向一些http服务器发送一些http请求,我会说10个服务器,每个服务器300个不同的请求,大约每小时一次,没什么大不了的

我的问题是:我应该为所有传出连接保留一个HttpClient吗?每个唯一的目标服务器可能有一个?或者每次“迭代”一次(每小时开始时大约需要10分钟)

我目前正在为每个请求使用一个
poollighttpclientconnectionmanager
HttpClientBuilder.setConnectionManager(connectionManager.build()


我有一种真正浪费资源的感觉,而且我还看到每个服务器都有许多处于
已建立状态的连接,尽管我使用的是池连接管理器。(对每台服务器的请求都是一个接一个地发送的,并且不是并发的)

我想说,如果它没有损坏,就不要修复它。我的意思是,只要最简单的配置能够满足您的需求,就可以使用它,并且不引入任何复杂性,只是为了满足未来的可伸缩性需求。额外的部件意味着额外的复杂性,也意味着更多的bug。一旦您看到当前配置不再支持增加的负载,请进行评估并添加资源。我希望这有助于

在客户端请求的HTTP 1.0头中,您需要

Connection: keep-alive
但是,这只是一个请求,您要连接的服务器可能会断开连接

HTTP 1.1默认提供此功能,但默认超时时间非常短。也许有一些可能的配置。在任何情况下,如果您收到的响应标题中带有
Connection:close
,则必须关闭连接

有关更多详细信息,请参阅,特别是第8节“持久连接”

因此,正确的做法似乎是确保HTTP 1.1处理(1.1默认情况下连接保持打开),而不是对HttpClient执行任何“特殊”操作,默认情况下,客户端将保持尽可能长的持久连接


我的建议是(如果在客户端连接端添加例程/线程/控制器),将与特定服务器/端口的所有相关连接在同一范围内排序(所有连接都在同一线程上或按相同顺序排序),这可能会降低您运行连接关闭逻辑的可能性;但是,您不能真正强制连接保持打开状态(原因很明显)。

我同意@Michael Gantman没有修复它

我想说,修复或不修复取决于您的负载配置文件

保持还是不保持连接?

例如,如果您一次向10台服务器发送300个请求,然后一个小时内不做任何事情,那么在资源方面,在整个小时内保持任何TCP/IP连接打开(因为使用HTTP/1.1)是没有意义的

但是如果你每隔5秒和一个服务器交谈,你可以考虑保持连接打开。此外,如果您想通过反复减少连接建立来最小化延迟,则可以考虑保持连接打开。 为此,您必须使用HTTP/1.1。你可以找到很多例子,例如

要保留多少连接?

同样,这取决于您的负载配置文件。你说你有10台服务器。如果您串行发送一台服务器的数据,那么使用http/1.1为每台服务器建立一个http连接就完全足够了。但是,如果您想更快地执行某些操作(例如,并行上载两个图像),则可以在同一服务器上打开多个连接。(当然,这意味着您的应用程序实际上是多线程的。)

结论

如果它不是一个时间关键型应用程序,最简单的方法就是不要将任何数据集中在一起,只要在有数据要发送时点击服务器即可。您可以重新开始优化,争取10毫秒的改进,但代价是严重的意外复杂性

我目前正在为每个请求使用一个池httpclientconnectionmanager和HttpClientBuilder.setConnectionManager(connectionManager.build()

为每个请求构建一个新的HttpClient是一个巨大的浪费。每个配置(每个客户端可以有不同的连接管理器、最大并发请求等)或应用程序的每个独立模块(为了避免在其他独立模块之间创建依赖关系),都应该使用HttpClient

另外,不要忘记
.build()
返回一个
CloseableHttpClient
,这意味着您应该在使用完httpClient.close()后调用它,否则可能会泄漏资源


更新以响应@Nati的评论:

什么是“浪费”?HttpClient是一个沉重的对象吗

正如您所看到的,它包含大量代码,在每个请求上执行都是毫无意义的。这会消耗CPU并产生大量垃圾,从而降低整个应用程序的性能。你做的分配越少越好!换句话说,为每个请求创建新的客户机没有任何好处,只有缺点

在应用程序的整个生命周期中将其作为一个bean保留有意义吗

我知道,除非它很少使用

HttpConnection和HttpClient之间的关系


每个http客户端可以执行多个http请求。每个请求都在客户端的上下文中执行(它的配置-即代理、并发、保持活动状态等)。必须关闭对请求的每个响应(reset()、close()、不记得确切名称),以便释放连接,以便将其重新用于另一个请求。

Yes,
过早优化是万恶之源。
克努斯说。但这不是一种优化。我需要最佳实践和对我正在使用的重要框架的深入理解