我們運行一個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。
我不會說他們在send()中被「封鎖」,只是他們將大部分的處理時間花費在那裏。套接字緩衝區是否可能已滿?無論如何,考慮內核中的錯誤將是我最後的選擇。 –
套接字緩衝區是最確定的,但它通常通過EAGAIN機制處理b/c UNIX套接字是非阻塞的。我同意內核bug部分。 –
如果在不成功的發送之間沒有延遲(例如睡眠),這是您將得到的結果。 –