Redisドライバーのタイムアウトの事象


解説

空きスレッドが利用できない時に大量のトラフィックがアプリケーションに到達すると、Redisドライバーの設計上、タイムアウト例外がスローされます。 Redisドライバーは、Redisサーバーからの応答を受信し、データがコールバックによって完全に解析されるまで、リクエスト スレッドをブロックします。しかし、受信したデータをタイムリー(デフォルトでは1秒)に解析するためのコールバックを呼び出すのに必要な空きスレッドがない為、タイムアウト例外が発生します。

技術的背景

スレッド プールは、特定の条件下で、入ってくる負荷を処理するための新しいワーカー スレッドを作成できます。スレッドの追加は、CPUリソースに余裕がある場合にのみ有効であり、 CPU使用率が80%未満の場合、スレッド プールが新しいスレッドを挿入します。

CPUパフォーマンス カウンターには直前の1秒間のシステム状態が示されるため、新しく作成されたスレッドによって生じた負荷は1秒後にしか反映されません。このため、CPUの過負荷が生じないように、スレッドの作成数は1秒あたり2スレッド以下に制限されています。

留意点: CLRスレッド プール サイズの管理方法は実装の詳細であり、テクノロジー ベンダーによって随時変更される可能性があります。

現在の実装については、「Azure Cache for Redis に関する FAQ」で記述されています。

シナリオ

スレッド プールの空きスレッドが着信するリクエストの数より少ない場合、すべてのスレッドがASP.NETによって着信リクエストの処理に使用され、さらにいくつかのスレッドが作成されます。残りのスレッドはワーク キューに入ります。

しかし、解析結果の待機中にすべてのワーカー スレッドがブロックされるため、Redis応答を解析するための空きワーカー スレッドが残りません。

その結果、応答の解析の優先度が高いことを確認するロジックがないことにより、優先順位の逆転が発生します。

タイムアウトが発生してブロックが解除され、例外がスローされてASP.NETのスレッドが解放されると、循環待機デッドロック状態が解決されます。

解放されたスレッドは、その時点のワーク キューの状況に応じて、保留中のコールバック処理に割り当てられる場合があります。

参考資料

解決策

本事象を解決するには、以下を実施してください。

  1. 本記事の「Redis設定の調整」節に記載されている内容に従って、Redisプロバイダーの設定を調整します。
  2. KB1003041の記事に記載されている指示に従って、スレッドの枯渇とスロットリングを防止するために.NET ThreadPoolパラメータの値を調整します。
  3. Sitecore XP 9.1.0および9.1.1に関しては特に、影響を受けている製品バージョンと互換性のある、以下のhotfixをダウンロードしてインストールします。

    このHotfixは、特定のSitecoreバージョン向けに作成されたものであり、他のSitecoreバージョンや、(互換性が確認できるまでは)他のHotfixと組み合わせてインストールすることはできません。すでに他のHotfixが貴社インスタンスにインストールされている場合は、Sitecoreサポートに互換性のチェックをリクエストしてください。
    ZIPファイルの内容を解凍し、インストール手順書や関連ファイルをご確認ください。貴社CMインスタンスにこのHotfixをインストールした後、貴社の標準の開発方法で、他のインスタンスと同期してください。

Redis設定の調整

Redisタイムアウトの事象を解決するために、以下のRedisプロバイダーの設定を調整します:

次の値を、設定の例としてweb.configファイルのRedisプロバイダー構成セクションに追加できます。

なお、最終的な設定値は、負荷テストの結果に応じて、ソリューションごとに調整する必要があります。

Redisプロバイダーの設定の詳細は、Redis プロバイダー設定リファレンスを参照してください。