サーバーの CPU 負荷が高い場合、またはスレッド プールがビジー状態の場合の WCF Reliable Sessions の障害
サーバーの CPU 負荷が高い (80 ~ 100% の範囲) 場合、または使用可能な即時 IO スレッドプール スレッドがない場合に、インフラストラクチャ キープアライブ メッセージの発行または受け入れを妨げる WCF Reliable Sessions に設計上の欠陥があるようです。メッセージを処理します。この症状は、信頼できるセッションの非アクティブ タイムアウトが原因で明らかにランダムなチャネルが異常終了することとして現れます。ただし、キープアライブ タイマーが実行できないにもかかわらず、アボート タイマーが起動しているように見えるため、アボート ロジックはより高い優先度で、または別のメカニズムを介して実行されているようです。
参照元を掘り下げると、ChannelReliableSession は InterruptableTimer クラスを使用して inactivityTimer を処理しているようです。応答として、ReliableOutputSessionChannel によって設定された PollingCallback を起動し、ACKRequestedMessage を作成してリモート エンドポイントに送信します。InactivityTimer は、WCF 内部の IOThreadTimer/IOThreadScheduler を使用して、それ自体をスケジュールします。これは、タイマーを処理するために使用可能な (ビジーでない) IO ThreadPool スレッドに依存します。CPU 負荷が高い場合、スレッド プールは新しいスレッドを生成しないようです。その結果、複数のスレッドが実行されている場合 (私の 4 コア マシンでは 8 スレッドのように見えます。15 秒の inactivityTimeout で 7 は中止されて失敗します)、キープアライブを送信するスレッドは使用できません。ただし、クライアントの信頼できるセッションの非アクティブ タイムアウトをサーバーよりも長くなるように変更すると、これらの条件下でもサーバーはメッセージをより短い時間で期待しているため、一方的にチャネルを中止します。そのため、中止ロジックがより高い優先度で実行されているか、実行中のスレッドの 1 つに例外がスローされているようです (どれかは不明)。CPU の使用率が高いためにサーバーでの中止が遅れ、クライアントの長いタイムアウトが最終的にヒットすることを期待していましたが、そうではありませんでした。CPU 負荷が低い場合、これとまったく同じシナリオが、返されるまでに 30 ~ 90 秒かかる同時呼び出しでも完全に正常に機能します。
InstanceMode が何であるか、最大同時接続、セッション、またはインスタンスが何であるか、他のタイムアウト値が何であるかは関係ありません (recieveTimeout 以外は inactivityTimeout より大きくなければなりません)。これは完全に WCF 実装の設計上の欠陥です。偽のアボートが生成されないように、分離された優先度の高いスレッドまたはリアルタイム スレッドを使用してキープアライブ メッセージを処理する必要があります。
短いバージョンは次のとおりです。CPU負荷が低いままである限り、15秒の信頼できるセッション非アクティブタイムアウトで完了するのに60秒かかる1000の同時リクエストを問題なく発行できます。CPU負荷が高くなるとすぐに、呼び出しはランダムにこれには、CPU 時間をまったく消費していない呼び出しや、使用されるのを待っているアイドリング状態のデュプレックス セッションが含まれます。受信呼び出しも CPU 負荷に追加されると、他の要求が受信キューに留まっている間、中断が保証された要求で実行時間が浪費されるため、サービスは死のスパイラルに入ります。サービスは、すべての要求が停止され、進行中のすべてのスレッドが終了し、CPU 負荷が低下するまで、正常な状態に戻ることはできません。この動作は、逆説的に Reliable Sessions を最も信頼性の低い通信メカニズムの 1 つにしているように見えます。
これと同じ動作がクライアントにも当てはまります。その場合、WCF クライアントはボックス上の他のプロセスに翻弄される可能性がありますが、CPU 負荷が高い場合、すべての操作が inactivityTimeout 未満で完了しない限り、信頼できるセッションをランダムに中止します。ただし、新しい呼び出しを発行しない場合すぐに、WCF は引き続きキープアライブの送信に失敗し、チャネルに障害が発生する可能性があります。