我在Scala应用程序中使用Apache Http Client。Apache HttpClient PoolingHttpClientConnectionManager泄漏连接?
该应用程序具有高吞吐量和高并行性。
我不确定,但我想我可能是在泄漏连接。似乎只要使用客户端的代码段变得繁忙,应用程序就会变得无法响应。我的怀疑是我正在泄漏套接字或其他导致应用程序其他方面停止工作的东西。它可能也不会泄漏连接,因为它们不会足够快地关闭连接。
对于更多的上下文,偶尔某些操作会导致此代码每分钟并行执行数百次。发生这种情况时,应用程序的Rest API(Spray)将无响应。应用程序的其他领域也以高并行性运行,并且这些应用程序响应性永远不会造成问题。
减少这部分代码的并行性似乎可以缓解问题,但不是一个可行的长期解决方案。
我忘了配置什么,或者配置不正确?
我使用的代码是这样的:
class SomeClass {
val connectionManager = new PoolingHttpClientConnectionManager()
connectionManager.setDefaultMaxPerRoute(50)
connectionManager.setMaxTotal(500)
val httpClient = HttpClients.custom().setConnectionManager(connectionManager).build()
def postData() {
val post = new HttpPost("http://SomeUrl") // Typically this URL is fixed. It doesn't vary much if at all.
post.setEntity(new StringEntity("Some Data"))
try {
val response = httpClient.execute(post)
try {
// Check the response
} finally {
response.close()
}
} finally {
post.releaseConnection()
}
}
}
编辑
我可以看到我建立了大量处于TIME_WAIT状态的连接。我已经尝试将DefaultMaxPerRoute和MaxTotal调整为各种值,但没有明显的效果。这似乎是我错过了一些东西,因此连接没有被重新使用,但我找不到任何文件表明我缺少的东西。这些连接重新使用至关重要。
EDIT 2
随着进一步的调查,使用lsof的-p,我可以看到,如果我设置MaxPerRoute至10,实际上被列为 “ESTABLISHED” 10个连接。我可以看到端口号不会改变。这似乎暗示我实际上正在重新使用这些连接。
什么不解释是为什么我仍然泄漏在此代码中的连接?在TIME_WAIT状态下显示的重用连接和泄漏连接(与netstat -a一起发现)共享相同的基本URL。所以他们绝对是相关的。是否有可能我正在重新使用连接,但不知何故不正确地关闭响应?
EDIT 3
位于所述TIME_WAIT “泄漏” 的来源。这是在一个不相关的代码部分。所以这与HttpClient没有任何关系。然而,在修复该代码后,所有的TIME_WAIT都消失了,但是当多次访问HttpClient代码时,应用程序仍然没有响应。仍在调查那部分。
要分析为什么您的喷雾应用程序变得无响应(如果您认为这可能是一个问题),您可能需要收集一些堆栈痕迹以查看Akka /喷雾线程在哪里花费时间。在控制台上使用'jps'和'jstack'来做到这一点。随意在喷雾邮件列表上发布关于它的信息。 – jrudolph