SolrのCirtcuit Breakerは具体的に何を見ているのか

はじめに

前回紹介した Circuit Breaker には MemoryCircuitBreaker と CPUCircuitBreaker の2種類があります。それぞれメモリとCPUの使い過ぎに対応しているのだなと何となくは想像が付きますが、具体的にはシステムの何を参照しているのかを調べてみました。

MemoryCircuitBreaker

リファレンスによると、JVMのヒープ使用率が設定値を超えると503を返すと書かれています。MemoryCircuitBreaker の実装をみると、取得しているのは ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() でした。これは現在のヒープ使用量をByteで返すものです。

一方、設定ではヒープの使用率を記述するので、比較するには使用率か使用量かのどちらかに変換して合わせる必要があります。
ソースを確認すると、MemoryCircuitBreaker のコンストラクタで memThreashold を読み込んだときに、ヒープの最大値 * memThreshold / 100 で閾値となるメモリ使用量を計算しておき、MemoryMXBean から取得したメモリ使用量がその値を超えたらリクエストを拒否するという実装になっていました。

CPUCircuitBreaker

CPUCircuitBreaker で監視しているのは ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverate() なので OS から取得するロードアベレージです。設定するのはCPU使用率なので、こちらも何らかの変換をしているのかと思いきや、何とソースコードではCPU使用率の閾値(%)とロードアベレージ(0以上の数値、CPUの数にもよるが通常はせいぜい10未満)を直接比較していました。

これだと使用率のつもりで75などと設定しても全く引っ掛からないのはずで不思議に思って調べてみたところ、どうやらバグのようで JIRA に Issue が作られていました。

CPU circuit breaker needs to use CPU utilization, not Unix load average

タイトルそのまんまですね。
ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverate() の代わりに ManagementFactory.getOperatingSystemMXBean().getSystemCPULoad() (0.0-0.1の間のCPU使用率)を使うことが提案されており、近いうちに修正されることと思います。


コメント