ElasticsearchのCircuitBreaker

最近Elasticsearch 5.2.2を使っているときにOutOfMemoryが発生したことがあって、そのときにログを見ると下記のようにCircuitBreakerも発動してた。

Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [request] Data too large, data for [<reused_arrays>] would be larger than limit of [19206989414/17.8gb]
        at org.elasticsearch.common.breaker.ChildMemoryCircuitBreaker.circuitBreak(ChildMemoryCircuitBreaker.java:97) ~[elasticsearch-5.2.2.jar:5.2.2]
        at org.elasticsearch.common.breaker.ChildMemoryCircuitBreaker.limit(ChildMemoryCircuitBreaker.java:170) ~[elasticsearch-5.2.2.jar:5.2.2]
        at org.elasticsearch.common.breaker.ChildMemoryCircuitBreaker.addEstimateBytesAndMaybeBreak(ChildMemoryCircuitBreaker.java:123) ~[elasticsearch-5.2.2.jar:5.2.2]
        at org.elasticsearch.common.util.BigArrays.adjustBreaker(BigArrays.java:405) ~[elasticsearch-5.2.2.jar:5.2.2]

CircuitBreakerが発動するならOutOfMemoryがおきないで欲しいものだけど完璧じゃないんだろうし、タイミングにもよるのかも。

ソース的にはこの辺
https://github.com/elastic/elasticsearch/tree/master/core/src/main/java/org/elasticsearch/common/breaker

indices.breaker.request.limitのdefaultが60%なのでうちの環境だと30GBのメモリを使っているので18GBを超えるとCircuitBreakerが発動する模様。
https://www.elastic.co/guide/en/elasticsearch/reference/current/circuit-breaker.html

社内のElasticsearchマスターに相談したら閾値をもっと下げて良いんじゃね?という話になったので、下記のようにガツッと下げて運用中。

indices.breaker.total.limit: 20%
indices.breaker.request.limit: 10%
indices.breaker.fielddata.limit: 10%

X-Pack Monitoringだと残念ながらCircuitBreaker周りのメトリクスは取れなくて、elasticsearch_exporterだと一部(メモリ使用量)取れる。ただしCircuitBreaker発動回数が取れなかったので、pull requestしといた。
https://github.com/justwatchcom/elasticsearch_exporter/pull/37

こちらからは以上です。