Elasticsearch 含多种熔断器用来避免因为操作引起来的OutOfMemoryError(内存溢出错误). 每个熔断器指定可以使用多少内存的限制。 另外,还有一个父级别的熔断器,指定可以在所有断路器上使用的总内存量。
parent circuit breaker(父熔断器)
父熔断器可以通过如下配置:
indices.breaker.total.limit: 70%
indices.breaker.total.use_real_memory: true
- 父级断路器是否应考虑实际内存使用情况(true)或仅考虑子级断路器保留的数量(false)。默认为true。
- 整个父级断点器的启动限制,如果
indices.breaker.total.use_real_memory: false
默认为JVM堆的70% of the JVM heap., 否则为95% of the JVM heap.
Field data circuit breaker( 列数据熔断器)
列数据断路器,Elasticsearch系统会估计有多少数据被加载到内存中。 它可以避免因为列字段加载(缓存)增长过多带来的异常。 默认情况下,该限制配置为最大JVM堆的60%。
可以配置以下参数:
index.breaker.fielddata.limit
fieldData断点器的限制,默认为JVM堆的60(7.*版本: 40%)
indices.breaker.fielddata.overhead
所有列数据乘以一个常量得到最终的值。 默认为1.03
Request circuit breaker(请求熔断器)
请求断路器允许Elasticsearch防止每个请求数据结构(例如,用于在请求期间计算聚合的内存)超过一定量的内存。
indices.breaker.request.limit
request熔断器的限制,默认为JVM堆的60%
indices.breaker.request.overhead
所有请求乘以一个常量得到最终的值。 默认为1
In flight requests circuit breaker(请求中的熔断器)
请求中的熔断器,允许Elasticsearch限制在传输或HTTP级别上的所有当前活动的传入请求的内存使用超过节点上的一定量的内存。 内存使用是基于请求本身的内容长度。
network.breaker.inflight_requests.limit
(inflight_requests)请求中熔断器,默认为100%的JVM堆。 这意味着受限于父母断路器配置的极限。
network.breaker.inflight_requests.overhead
所有(inflight_requests)请求中估算的常数乘以确定最终估计。 默认为1(7.*版本:2)
Accounting requests circuit breaker
找不到中文翻译,这个熔断器允许Elasticsearch限制内存中保存的内容的使用量,这些内容在请求完成时未释放,
包括像Lucene段内存这样的东西。
indices.breaker.accounting.limit
accounting断路器的限制,默认为JVM堆的100%这意味着它受到父断路器配置的限制的约束。
indices.breaker.accounting.overhead
所有 accounting 估计相乘的常数,以确定最终估计。默认为1
Script compilation circuit breaker(脚本编译熔断器)
与以前的基于内存的断路器略有不同,脚本编译断路器在一段时间内限制了内联脚本编译的数量。
script.max_compilations_rate
限制允许编译的特定时间间隔内的唯一动态脚本数。默认为75 / 5m,即每5分钟75个。
事故起因:
开发同学在排查 nginx 日志中 uuid 为 undefined 的请求,时间选择了一年。而我们一天的数据早已经超过1亿多,整个请求把把5.5G 的数据加载到内存中直接把 es 撑炸了。
kibana 返回:
Data too large, data for [xxx] would be larger than limit
解决方案:
- 把 index cache 释放掉
curl -XPOST 'index1_alias,index2/_cache/clear'
- 可以把Request circuit breaker limit 调小些
curl -XPUT /_cluster/settings \
-H 'Content-type: application/json'
-d '{
"persistent" : {
"indices.breaker.request.limit" : "45%"
}
}
'