我在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