2017-04-09 74 views
5

我在一起在Docker羣中運行6個容器。 Kafka + Zookeeper,MongoDB,A,B,C和界面。接口是公共的主要接入點 - 只有此容器發佈端口 - 5683.接口容器在啓動過程中連接到A,B和C.我正在使用docker-compose文件+ docker stack deploy,每個服務都有一個用作接口主機的名稱。一切都開始成功,工作正常。經過一段時間(20分鐘,1小時,..)我無法提出接口請求。接口收到我的請求,但應用程序與服務A,B,C或全部服務失去連接。如果我重新啓動界面,它可以重新連接到服務A,B,C。泊塢窗服務在一段時間後停止通信

我首先想到讓我暴露在每個服務(接口,A,B,C)2個新港口,並與分析器和調試器將它們連接它的應用的問題。應用程序運行正常,沒有泄漏,沒有阻塞的線程,正常工作和等待連接。調試器告訴我,當我向接口和接口請求嘗試請求服務A時,拋出了由同級異常重置的連接。

在調試過程中,我發現有趣的東西。當服務啓動並且調試器在一段時間後斷開連接時,我將調試器連接到接口。 +我無法重新連接,直到向容器 - >應用程序發出請求。問題 - 握手失敗。

,我發現了另一個有趣的事情是,我無法要求既不接口。所以我用wireshark來看看發生了什麼,並且:SYN - ACK很好。然後應用程序發佈一些數據和接口以FIN,ACK進行響應。我認爲這也發生在接口試圖請求服務A並且它終止連接時。接口的代碼庫,A,B和C對於netty服務器是一樣的。

最後,我不認爲這是一個應用程序問題。爲什麼?我試圖將容器部署爲不作爲服務。我分別運行每個容器,發佈每個端口的服務端點和設置爲localhost。 (不覆蓋網絡)。它正在工作。容器運行沒有問題。 +在開始時我並沒有說過,當java應用程序(接口,A,B,C)作爲獨立應用程序運行時沒有問題,而不是在docker中運行。

你能幫我解決這個問題嗎?爲什麼碼頭在覆蓋網絡的情況下關閉套接字?

我正在使用最新的碼頭。我也用得比較老。

+0

「接口」,「A」,「B」和「C」是你自己的Java應用程序嗎?我很困惑什麼是「接口」。另外,你是否在沒有Docker Swarm的Docker Compose中嘗試過這種方法?我的猜測是,該應用程序與Docker Swarm路由器奇怪地工作,所以也許嘗試沒有Docker Swarm可能是一個好主意。 –

+0

是的,A,B,C和接口是我的Java應用程序,具有相同的基本代碼。共享的基本代碼除其他外包含netty。接口只是服務的名稱,可以很容易地解釋這個問題 - 只有這個接口是公共接口,並且作爲其他服務的網關,不會發布端口。 +它負責認證和授權,但這是業務邏輯。 –

+0

正如我寫的,我試圖分別運行每個容器,每個容器都公佈了它公開的端口,並且我使用localhost作爲ip,因此interface不是連接到dns主機名,而是連接到localhost。這工作沒有任何問題。 –

回答

4

最後,我能夠解決這個問題。

發生了什麼,還有一次。接口打開與A,B,C的永久TCP連接。當您嘗試將這些服務A,B,C作爲獨立的Java應用程序運行時,一切都正常。當我們將它們碼頭化並在羣集中運行時,它只能工作幾分鐘。奇怪的是,當你向客戶端發出一個請求時,Interface和另一個服務之間的連接中斷了。

經過很多很多不成功的測試和調試每個容器我想單獨運行每個泊塢窗的容器中,映射端口和端點我指定本地主機。 (每個容器暴露的端口和接口連接到本地主機)有趣的事情發生,它正在工作。當你像這樣運行容器時,使用不同的容器網絡驅動程序。橋一個。如果您在羣集中運行它,則會使用覆蓋網絡驅動程序。

所以它必須是一些與泊塢窗的網絡,而不是與應用程序本身。接下來的步驟是幾分鐘後從每個容器運行tcpdump,此時應停止工作。它很有意思。

  • 客戶端 - >接口(OK,請求接受)
  • 接口 - >(前向請求,因爲它屬於A)
    • 接口 - > A [POST]
    • A - >接口[RESET]

A被正在重置幾分鐘而不通信之後打開TCP通信。爲什麼?

Docker使用IP虛擬服務器,IPVS維護自己的連接表。 IPVS表中CLOSE_WAIT連接的默認超時值爲60秒。因此,當服務器在60秒後發送某些內容時,IPVS連接不再可用,並且該數據包對於新的TCP會話看起來無效並且獲得RST。在客戶端,連接永遠保持在FIN_WAIT2狀態,因爲應用程序仍然打開套接字;內核的fin_wait定時器僅爲孤立的TCP套接字啓用。

這是我讀到的,它是如何理解的。我不確定我對問題的解釋是否正確,但基於這些假設,我在界面和A,B,C服務之間實現了乒乓,以防在沒有通信的情況下60秒。而且,它正在工作。

+0

非常有用的研究!謝謝。但我在這裏有一個更深的問題。我的一個容器是MongoDB,它隨機重置連接,我顯然無法在這裏實現乒乓球.. –

+0

我也在使用MongoDB,並且我對它沒有任何問題。我會嘗試不同的客戶端庫。 –

+0

這是Mongo團隊的官方客戶端庫,我設法瞭解一些重現條件。 如果我的容器通過覆蓋網絡通信,它工作正常。如果有人試圖通過發佈的端口進行通信(通過入口網絡),則存在風險。 這與客戶端庫無關,因爲我嘗試建立兩個官方容器:一個是數據庫,另一個是運行'mongodump'(相同的映像,只是不同的啓動命令),它的工作方式相同。 當我使用發佈的端口時它會隨機重置連接,並且每當我使用內部網絡地址時它都可以正常工作。 –