Solr 8.7で追加されたCircuit Breaker機能

はじめに

Solr 8.7 に Circuit Breaker 機能が追加されました。
いわゆるブレーカーは一定以上の電流が流れたときに回路を遮断する仕組みです。Solr においては想定を超える負荷が掛かったときにサーバが落ちる前にリクエストの受付を停める仕組みになっています。

設定方法

Solr 8.7 に付属の solrconfig.xml には Circuit Breaker 関係の設定が追加されています。説明のコメント部分を除くと以下のような内容です。

    <circuitBreakers enabled="true">
      <!--
       <memBreaker enabled="true" threshold="75"/>
      -->
      <!--
       <cpuBreaker enabled="true" threshold="75"/>
      -->
    </circuitBreakers>

circuitBreakers 要素の enabled 属性が true のときだけ Circuit Breaker 機能が有効になります。
他の部分はコメントを外して設定を有効にすれば良いのかと思ったのですが、リファレンスにはちょっと違うことが書いてあります。リファレンスによると、JVMのヒープ使用率ベースの Circuit Breaker の設定は以下の2項目です。

<str name="memEnabled">true</str>
<str name="memThreshold">75</str>

また、CPU使用率ベースの Circuit Breaker の設定は以下の通りと記載されています。

<str name="cpuEnabled">true</str>
<str name="cpuThreshold">75</str>

CircuitBreakerManager.java を確認すると以下のような読み込み処理があるので、solrconfig.xml ではなくリファレンスの記述の方が正しいようです。

      if (args != null) {
        cpuCBEnabled = Boolean.parseBoolean(args._getStr("cpuEnabled", "false"));
        memCBEnabled = Boolean.parseBoolean(args._getStr("memEnabled", "false"));
        memCBThreshold = Integer.parseInt(args._getStr("memThreshold", "100"));
        cpuCBThreshold = Integer.parseInt(args._getStr("cpuThreshold", "100"));
      }

以下は SearchHandler で circuitBreakerManager によるチェックを実行している箇所です。チェックに引っ掛かると SolrQueryResponse オブジェクト(rsp)に SERVICE_UNAVAILABLE をセットして終了していることが分かります。

    if (req.getCore().getCircuitBreakerManager().isEnabled()) {
      List trippedCircuitBreakers;

      if (timer != null) {
        RTimerTree subt = timer.sub("circuitbreaker");
        rb.setTimer(subt);

        CircuitBreakerManager circuitBreakerManager = req.getCore().getCircuitBreakerManager();
        trippedCircuitBreakers = circuitBreakerManager.checkTripped();

        rb.getTimer().stop();
      } else {
        CircuitBreakerManager circuitBreakerManager = req.getCore().getCircuitBreakerManager();
        trippedCircuitBreakers = circuitBreakerManager.checkTripped();
      }

      if (trippedCircuitBreakers != null) {
        String errorMessage = CircuitBreakerManager.toErrorMessage(trippedCircuitBreakers);
        rsp.add(STATUS, FAILURE);
        rsp.setException(new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Circuit Breakers tripped " + errorMessage));
        return;
      }
    }

おわりに

Circuit Breaker 機能は地味ながら、安定運用のためには便利な機能といえます。今後監視項目をプラグインできるようになる可能性もあり、要注目です。

コメント