サーキットブレーカー

Solr のサーキットブレーカーインフラストラクチャにより、ノードの容量を超えたり、ノードがダウンしたりする可能性のあるアクションを防止できます。サーキットブレーカーの基本的な考え方は、より高品質のサービスを確保し、現在のリソース構成で処理可能なリクエストロードのみを受け入れることです。

サーキットブレーカーを使用する場面

サーキットブレーカーは、ユーザーがリクエストスループットと引き換えに Solr の安定性を向上させたい場合に使用します。サーキットブレーカーが有効になっている場合、ノードに大きな負担がかかっている状況では、HTTP エラーコード 429「リクエストが多すぎます」でリクエストが拒否される場合があります。

これは一時的な状況であるため、クライアントがこのエラーを処理し、必要に応じて再試行ロジックを構築する必要があります。

シャード化されたコレクションへのリクエストでは、サーキットブレーカーは最初のリクエストを処理するノードでのみチェックされ、ノード間のリクエストではチェックされません。そのため、ホットスポットを避けるために、Solr ノード間でクライアントリクエストをロードバランシングすることが推奨されます。

サーキットブレーカーの設定

サーキットブレーカーは、ノード全体、コレクションごと、またはその組み合わせでグローバルに設定できます。コレクションごとのサーキットブレーカーは、グローバルサーキットブレーカーの前にチェックされ、競合がある場合は、コレクションごとのサーキットブレーカーが優先されます。通常、コレクションごとのサーキットブレーカーのしきい値は、グローバルしきい値よりも低く設定されます。

サーキットブレーカーは、クエリリクエストと更新リクエストの両方についてチェックされるように登録できます。ユーザーは、各リクエストタイプに対して異なるしきい値を持つ同じタイプのサーキットブレーカーを登録できます。

グローバルサーキットブレーカー

サーキットブレーカーは、`solr.in.sh` などの環境変数またはシステムプロパティを使用してグローバルに設定できます。使用可能な変数は次のとおりです。

名前 環境変数名 システムプロパティ名

JVM ヒープ使用率

`SOLR_CIRCUITBREAKER_QUERY_MEM`、`SOLR_CIRCUITBREAKER_UPDATE_MEM`

`solr.circuitbreaker.query.mem`、`solr.circuitbreaker.update.mem`

システムCPU使用率

`SOLR_CIRCUITBREAKER_QUERY_CPU`、`SOLR_CIRCUITBREAKER_UPDATE_CPU`

`solr.circuitbreaker.query.cpu`、`solr.circuitbreaker.update.cpu`

システム負荷平均

`SOLR_CIRCUITBREAKER_QUERY_LOADAVG`、`SOLR_CIRCUITBREAKER_UPDATE_LOADAVG`

`solr.circuitbreaker.query.loadavg`、`solr.circuitbreaker.update.loadavg`

たとえば、CPU 負荷が 95% を超えたときに更新リクエストを拒否するグローバル CPU サーキットブレーカーを有効にするには、次の環境変数を設定します。`SOLR_CIRCUITBREAKER_UPDATE_CPU=95`。

コレクションごとのサーキットブレーカー

サーキットブレーカーは、以下の例に示すように、`solrconfig.xml` 内の独立した``エントリとして設定されます。デフォルトでは、検索リクエストのみが影響を受けます。

現在サポートされているサーキットブレーカー

Solr 9.4 以降、`CircuitBreakerManager` を使用したレガシー設定構文は非推奨になりましたが、引き続き動作します。このレガシープラグインが`cpuThreshold`を設定する際に使用する「CPU」サーキットブレーカーは、以下で説明する`LoadAverageCircuitBreaker`です。また、`CircuitBreakerManager`は、新しいサーキットブレーカーが使用するHTTP 429コードではなく、HTTP 503コードを返します。

JVM ヒープ使用率

このサーキットブレーカーはJVMヒープメモリの使用状況を監視し、ヒープ使用量がJVMに割り当てられた最大ヒープ(-Xmx)の構成済みパーセンテージを超えた場合、429エラーコードで着信リクエストを拒否します。このサーキットブレーカーの主な構成は、ブレーカーがトリップするしきい値パーセンテージの制御です。

JVMヒープ使用量に基づくサーキットブレーカーを有効化および構成するには、以下を追加します。

solrconfig.xml内の各コレクションごと
<circuitBreaker class="org.apache.solr.util.circuitbreaker.MemoryCircuitBreaker">
 <double name="threshold">75</double>
</circuitBreaker>
solr.in.sh内でグローバルに
SOLR_CIRCUITBREAKER_QUERY_MEM=75

thresholdは、JVMに割り当てられた最大ヒープのパーセンテージとして定義されます。

サーキットブレーカーの構成では、「0」は0%の使用率、「100」は100%の使用率にマップされます。

JVMに割り当てられた最大ヒープの50%未満または95%を超えるしきい値を設定することは論理的に意味がありません。したがって、このパラメーターの有効な値の範囲は[50, 95](両端を含む)です。

次の例を考えてみましょう。

JVMに5GBの最大ヒープが割り当てられており(-Xmx)、threshold75に設定されています。このシナリオでは、サーキットブレーカーがトリップするヒープ使用量は3.75GBです。

システムCPU使用率サーキットブレーカー

このサーキットブレーカーはシステムCPUの使用状況を監視し、最近のCPU使用率が構成可能なしきい値を超えた場合にトリガーされます。

これは、JMXメトリックOperatingSystemMXBean.getSystemCpuLoad()を使用して監視されます。これは、システム全体の最近のCPU使用率を測定します。このメトリックはcom.sun.managementパッケージによって提供されますが、すべてのJVMで実装されているわけではありません。メトリックが利用できない場合、サーキットブレーカーは無効になり、エラーメッセージがログに記録されます。その代替として、システム負荷平均サーキットブレーカーを使用できます。

CPU使用率に基づくサーキットブレーカーを有効化および構成するには

solrconfig.xml内の各コレクションごと
<circuitBreaker class="org.apache.solr.util.circuitbreaker.CPUCircuitBreaker">
 <double  name="threshold">75</double>
</circuitBreaker>
solr.in.sh内でグローバルに
SOLR_CIRCUITBREAKER_QUERY_CPU=75

トリガーしきい値は、CPU使用率のパーセントで定義されます。「0」は0%の使用率、「100」は100%の使用率にマップされます。上記の例では、CPU使用率が75%以上になったときにトリップします。

システム負荷平均サーキットブレーカー

このサーキットブレーカーはシステム負荷平均を監視し、最近の負荷平均が構成可能なしきい値を超えた場合にトリガーされます。

これは、JMXメトリックOperatingSystemMXBean.getSystemLoadAverage()を使用して監視されます。これは、システム全体の最近の負荷平均を測定します。「負荷平均」とは、CPUを使用しているか、またはCPUを待機しているプロセスの数であり、通常は1分間平均化されます。一部のシステムでは、IOを待機しているプロセスも負荷平均に含まれます。このメトリックを理解するには、お使いのシステムとJVMのドキュメントを確認してください。詳細については、負荷に関するWikipediaのページを参照してください。

負荷平均サーキットブレーカーを有効化および構成するには

solrconfig.xml内の各コレクションごと
<circuitBreaker class="org.apache.solr.util.circuitbreaker.LoadAverageCircuitBreaker">
 <double  name="threshold">8.0</double>
</circuitBreaker>
solr.in.sh内でグローバルに
SOLR_CIRCUITBREAKER_QUERY_LOADAVG=8.0

トリガーしきい値は、負荷平均に一致する浮動小数点数です。上記のサーキットブレーカーの例では、負荷平均が8.0以上になったときにトリップします。

システム負荷平均サーキットブレーカーの動作はオペレーティングシステムに依存し、Microsoft Windowsなどの一部のオペレーティングシステムでは動作しない場合があります。詳細については、JavaDocを参照してください。

高度な例

この例では、CPU負荷が80%を超える更新リクエストと、CPU負荷が95%を超えるクエリリクエストを防止します。サポートされているリクエストタイプはqueryupdateです。これにより、高価なバルク更新が検索に影響することを防ぎます。短縮形クラス名のサポートにも注意してください。

solrconfig.xml内の各コレクションごと
<config>
  <circuitBreaker class="solr.CPUCircuitBreaker">
   <double  name="threshold">80</double>
   <arr name="requestTypes">
     <str>update</str>
   </arr>
  </circuitBreaker>

  <circuitBreaker class="solr.CPUCircuitBreaker">
   <double  name="threshold">95</double>
   <arr name="requestTypes">
     <str>query</str>
   </arr>
  </circuitBreaker>
</config>
solr.in.sh内でグローバルに
SOLR_CIRCUITBREAKER_UPDATE_CPU=80
SOLR_CIRCUITBREAKER_QUERY_CPU=95

パフォーマンスに関する考慮事項

JVMまたはCPUサーキットブレーカーは、リクエストごとに目に見えるオーバーヘッドを追加しませんが、単一のリクエストに対してチェックされるサーキットブレーカーが多すぎると、パフォーマンスオーバーヘッドが発生する可能性があります。

さらに、ビジーノードでリクエストを再試行する際には、指数バックオフを行うことがベストプラクティスです。指数バックオフに関するWikipediaのページを参照してください。