首页/数据/NoSQL 速查/断路器 circuit breaker 与内存保护
Elasticsearch89 条

断路器 circuit breaker 与内存保护

断路器防止聚合、请求或 fielddata 占用过多堆内存:父断路器默认限制在堆的 70%,触发时返回 429 与 circuit_breaking_exception。

NoSQL 速查数据更新于 2026-10-13

断路器防的是什么

断路器是堆内存的熔断机制:它估算某次请求(聚合、请求阶段、字段数据载入等)将要占用的内存,一旦超过预设水位就直接拒绝请求,返回 429 与 circuit_breaking_exception,而不是让节点一路涨到 OOM。父断路器默认限制在堆的 70%,字段数据与请求阶段各自还有独立的子限制。

触发说明什么

断路器是保护而不是根因:频繁触发说明查询模式(大聚合、深分页、脚本)或堆容量与当前负载不匹配。调大上限只是把风险往后推,真正有效的做法是减少聚合桶数、把深分页换成游标方式、把对 text 字段的排序聚合改用 keyword 字段。

基本信息

父断路器indices.breaker.total.limit,默认约堆的 70%
子限制indices.breaker.fielddata.limit、indices.breaker.request.limit
触发表现请求返回 429,消息含 data too large 或 circuit_breaking
设置范围集群级动态设置,可用 persistent 或 transient 下发
观察入口GET /_nodes/stats/breaker

示例

示例
PUT /_cluster/settings
{ "persistent": { "indices.breaker.total.limit": "70%" } }

# 查看各节点断路器水位与估算值
GET /_nodes/stats/breaker?filter_path=nodes.*.breakers.parent,nodes.*.breakers.fielddata

# 同时看线程池,确认是否伴随请求积压
GET /_cat/thread_pool?v&h=node_name,name,active,queue,rejected

# 排查是否由 text 字段触发字段数据载入
GET /my-index/_mapping?filter_path=**.fielddata

典型使用场景

  • 大聚合返回 429 时确认是断路器拒绝而不是分片失败
  • 容量评估:观察估算值的日常峰值,判断堆是否够用
  • 排查字段数据触发:多来自对 text 字段排序或聚合
  • 压测验收:确认常规流量下不会频繁触发熔断
  • 参数调整:确有更大的聚合内存需求时按节点实际堆设置水位

设置与观察项

设置或分段含义调整风险
total.limit所有断路器合计上限挤压其他内存用途,逼近 OOM
fielddata.limit字段数据缓存上限掩盖映射设计问题
request.limit单个请求阶段的估算上限请求能过了,节点却更吃力
breaker 分段parent、fielddata、request 分别查看分段阈值各自独立生效
断路器基于估算值判断,存在误差:可能提前拒绝,也可能没拦住;因此它只是兜底保护,堆容量与查询设计仍要留出余量。
调大上限只是把风险后移,过量内存分配最终会压垮 GC 甚至 OOM,节点上其他用途(缓存、分片元数据)也会被一起挤压。

易错点

  • 频繁触发断路器说明查询模式或堆容量不匹配,一味调大阈值会把问题推迟到 OOM
  • 字段数据触发多来自对 text 字段排序聚合,根治方式是改用 keyword 字段
  • 断路器估算存在误差,压测时要结合真实堆曲线与 GC 表现判断,而不是只看是否报错
  • 只有个别节点触发时,多半是分片分布不均让该节点承载了更多聚合请求,先调整分配再谈扩容

数据来源与参考

  • Elasticsearch Guide: Circuit breaker settings
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌