空きスレッドが利用できない時に大量のトラフィックがアプリケーションに到達すると、Redisドライバーの設計上、タイムアウト例外がスローされます。 Redisドライバーは、Redisサーバーからの応答を受信し、データがコールバックによって完全に解析されるまで、リクエスト スレッドをブロックします。しかし、受信したデータをタイムリー(デフォルトでは1秒)に解析するためのコールバックを呼び出すのに必要な空きスレッドがない為、タイムアウト例外が発生します。
技術的背景
スレッド プールは、特定の条件下で、入ってくる負荷を処理するための新しいワーカー スレッドを作成できます。スレッドの追加は、CPUリソースに余裕がある場合にのみ有効であり、 CPU使用率が80%未満の場合、スレッド プールが新しいスレッドを挿入します。
CPUパフォーマンス カウンターには直前の1秒間のシステム状態が示されるため、新しく作成されたスレッドによって生じた負荷は1秒後にしか反映されません。このため、CPUの過負荷が生じないように、スレッドの作成数は1秒あたり2スレッド以下に制限されています。
留意点: CLRスレッド プール サイズの管理方法は実装の詳細であり、テクノロジー ベンダーによって随時変更される可能性があります。
現在の実装については、「Azure Cache for Redis に関する FAQ」で記述されています。
シナリオ
スレッド プールの空きスレッドが着信するリクエストの数より少ない場合、すべてのスレッドがASP.NETによって着信リクエストの処理に使用され、さらにいくつかのスレッドが作成されます。残りのスレッドはワーク キューに入ります。
しかし、解析結果の待機中にすべてのワーカー スレッドがブロックされるため、Redis応答を解析するための空きワーカー スレッドが残りません。
その結果、応答の解析の優先度が高いことを確認するロジックがないことにより、優先順位の逆転が発生します。
タイムアウトが発生してブロックが解除され、例外がスローされてASP.NETのスレッドが解放されると、循環待機デッドロック状態が解決されます。
解放されたスレッドは、その時点のワーク キューの状況に応じて、保留中のコールバック処理に割り当てられる場合があります。
参考資料
本事象を解決するには、以下を実施してください。
Redisタイムアウトの事象を解決するために、以下のRedisプロバイダーの設定を調整します:
次の値を、設定の例としてweb.configファイルのRedisプロバイダー構成セクションに追加できます。
なお、最終的な設定値は、負荷テストの結果に応じて、ソリューションごとに調整する必要があります。
Redisプロバイダーの設定の詳細は、Redis プロバイダー設定リファレンスを参照してください。