2017-06-15 40 views
0

我們運行一個Linux應用程序,它分派了大量(超過1000個)子進程。這些子進程通過UNIX數據報套接字與主進程進行通信(所有子進程之間共享一個進程)。 UNIX數據報套接字除了用於記錄的其他通信之外也被使用。整個系統運行良好,直到應用程序必須對一個巨大的外部錯誤做出反應 - 比如說應用程序數據庫崩潰。我們觀察到,在這種情況下,子進程開始產生大量錯誤日誌事件,這可能是正確的,因爲每個子進程都會受到該崩潰的影響。幾分鐘後,80-100%CPU 系統(非用戶!)消耗的負載增加到8000以上。只有當應用程序被殺或更常見時才能恢復狀態,由於響應緩慢並且必須重新啓動,該狀態變爲不可用。在Linux UNIX套接字上實時鎖定,該怎麼辦?

對核心轉儲的調查顯示子進程在UNIX套接字上的系統調用send()中被阻塞,與主進程對話。 UNIX套接字被配置爲非阻塞,並且該應用實現了EAGAIN的正確處理。更深入的分析表明內核中存在活鎖狀態。顯然,進程正在競爭訪問與UNIX套接字相關的一些資源。

問題:你曾經遇到過這種或類似的行爲嗎?我們錯過任何關於UNIX套接字並行性的事情嗎?

版本:
- CentOS Linux版本7.3.1611(核心)。
- 內核Linux 3.10.0-514.16.1.el7.x86_64 x86_64。

+0

我不會說他們在send()中被「封鎖」,只是他們將大部分的處理時間花費在那裏。套接字緩衝區是否可能已滿?無論如何,考慮內核中的錯誤將是我最後的選擇。 –

+0

套接字緩衝區是最確定的,但它通常通過EAGAIN機制處理b/c UNIX套接字是非阻塞的。我同意內核bug部分。 –

+1

如果在不成功的發送之間沒有延遲(例如睡眠),這是您將得到的結果。 –

回答

0

在這方面,內核方面顯然有改進的餘地,而且很可能是一個相當低的掛果。我不會推測。使用火焰圖很容易看出問題的可能性。

但是,在這種情況下,排序的考慮因素是紅鯡魚。爲了說明起見,我們假設內核以0開銷推送所有這些錯誤消息。您已經生成了千兆字節的重複性錯誤消息,但沒有添加任何值。

相反,當有重大事件只要登錄其一次,然後重新登錄,它被清除(如注意與數據庫的連接去世,注意當它得到了回升,但不要每次登錄查詢它已經死了)。或者,您可以定期或使用ratelimit進行記錄。無論哪種方式,只是垃圾郵件是不對的。

孩子的數量(1000多個?)看起來非常過分,並且對這個項目的設計的有效性提出了一個問號。你能詳細說明那裏發生了什麼?

+0

讓我們從頭開始:我完全同意,具有大量子進程的設計至少是奢侈的。決策的最初目的來自安全性:每個孩子處理通過唯一密鑰集加密的對等連接,並且意圖是在系統/過程級別保持分離。性能方面也相當令人印象深刻,它可輕鬆處理+ 10k併發連接,每秒處理250個事務,佔用CPU的1-5%,系統負載小於0.1。但我不是爲了辯護這一點,下一代可能會轉而採用「每CPU核心處理器」模式。 –

+0

重大事件和'管理'日誌記錄:是的,這是一個很好的觀察。但是,這並沒有解決根本問題。還有其他方式可以觸發廣泛的日誌記錄,從而調用應用程序的停滯。 –

+0

Re「千兆字節的重複性錯誤消息不增加任何值」 - 這個應用程序生成了一個巨大的審計日誌,它被輸入到一個功能強大的日誌分析器中。從這個角度來看,這些錯誤在海洋中下降。類似的情況(當不拖延應用程序時)會在監控圖表中產生一個「漂亮」峯值,以便操作員快速響應。但是,我不再爲此辯護 - 這是一個明顯的改進空間,可能是單一但更嚴重的日誌消息。 –