私たちは、多数の(1000以上の)子プロセスをフォークするLinuxアプリケーションを動作させます。これらの子プロセスは、UNIXデータグラムソケット(すべての子プロセスで共有される)を介してマスタープロセスと通信します。 UNIXデータグラムソケットは、ログ用の他の通信の他にも使用されます。アプリケーションが大規模な外部エラーに反応するまでシステム全体が正常に動作します - アプリケーションデータベースのクラッシュを考えましょう。このような状況では、子プロセスは大量のエラーログイベントを生成し始めます。これは、各子がそのクラッシュの影響を受けるため正しいと思われます。数分後、負荷は8000を超えて80-100%のCPUで増加します。システム(消費者ではありません)消費。状態が回復するのは、アプリが強制終了された場合、または一般的に、応答が遅いためにボックスを使用できなくなり、再起動する必要がある場合のみです。Linux UNIXソケットでのライブロック、どうすればよいですか?
コアダンプの調査では、子プロセスがUNIXソケット上のsend()
syscallでブロックされ、プロセスをマスターすることが示されています。 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ソケットは非ブロックです。私はカーネルのバグの部分に同意します。 –
失敗したセンド間に遅延(スリープなど)がない場合、これが結果になります。 –