断路器防的是什么
断路器是堆内存的熔断机制:它估算某次请求(聚合、请求阶段、字段数据载入等)将要占用的内存,一旦超过预设水位就直接拒绝请求,返回 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,节点上其他用途(缓存、分片元数据)也会被一起挤压。