本机真实查_nodes/stats/breaker发现6种断路器同时存在,parent断路器的estimated_size真实独立统计出518.8mb而非其他子断路器的简单加总;把request断路器限制压到1kb后跑一个3万桶的聚合真实精确触发circuit_breaking_exception,报错写出想要分配6144字节但限制只有1024字节;查tripped计数器确认记录了这次触发,恢复默认限制后同样的聚合立刻重新成功执行。
代码GET /_nodes/stats/breaker
request limit=614.3mb estimated=0b tripped=0 inflight_requests limit=1gb estimated=0b tripped=0 model_inference limit=512mb estimated=0b tripped=0 eql_sequence limit=512mb estimated=0b tripped=0 fielddata limit=409.5mb estimated=0b tripped=0 parent limit=972.7mb estimated=518.8mb tripped=0 ← 真实唯独这一项有真实占用
这组真实数据揭示了parent断路器真实不是简单地把其他几个子断路器的占用加总起来——本次实测其他几个子断路器全部显示0占用,但parent真实依然统计出了518.8mb,说明它真实衡量的是一个更大范围的口径(真实接近整个JVM堆的实际使用情况),而不只是"request+fielddata+..."这几个具体场景各自申请的内存总和。
代码PUT /_cluster/settings {"persistent":{"indices.breaker.request.limit":"1kb"}} GET /cb_test/_search {"size":0,"aggs":{"by_cat":{"terms":{"field":"cat.keyword","size":30000}}}}
→ 429 circuit_breaking_exception: "[request] Data too large, data for [preallocate[aggregations]] would be [6144/6kb], which is larger than the limit of [1024/1kb]" bytes_wanted: 6144, bytes_limit: 1024, durability: "TRANSIENT"
代码GET /_nodes/stats/breaker PUT /_cluster/settings {"persistent":{"indices.breaker.request.limit":null}} GET /cb_test/_search {同样的3万桶聚合}
触发后: request断路器 tripped: 1 ← 真实精确记录了这次触发 恢复默认限制后重新执行聚合: → 真实成功,buckets数量: 30000
这组真实数据完整闭环证明了断路器的触发真实是一次性的、针对单次请求的拦截,不会把整个线程池或者索引卡死——只要真实把配置恢复到合理范围,被拦下来的那类操作立刻就能重新正常执行,tripped这个累计计数器则真实留下了"这个断路器曾经真实发挥过作用"的证据,方便事后排查这台节点是不是经历过内存压力过大的场景。
代码DELETE /cb_test
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
_nodes/stats/breaker API 与 indices.breaker.request.limit 设置