--- title: "断路器异常 (circuit_breaking_exception) 错误排查与解决" date: 2026-03-26 lastmod: 2026-03-26 description: "circuit_breaking_exception 表示断路器被触发,是 Easysearch 的内存保护机制,防止操作消耗过多内存导致 OutOfMemoryError。" tags: ["内存管理", "断路器", "JVM", "聚合"] summary: "为什么这个错误发生 # circuit_breaking_exception 表示断路器被触发。断路器是 Easysearch 的内存保护机制,防止操作消耗过多内存导致 OutOfMemoryError。 这个错误可能由以下原因引起: 请求过大:单个请求尝试加载过多数据到内存 聚合数据过多:聚合操作产生的桶数量过多 字段数据缓存:字段数据(fielddata)缓存占用过多内存 请求级断路器:单个请求的内存使用超过限制 父级断路器:所有请求的总内存使用超过限制 JVM 堆内存不足:JVM 堆内存设置过小 高并发:并发请求过多导致总内存使用超限 深度分页:from + size 值过大 如何修复这个错误 # 1. 查看断路器状态 # # 查看所有断路器的状态 GET /_nodes/stats/breaker?pretty # 查看特定节点的断路器 GET /_nodes/<node_id>/stats/breaker 2. 增加断路器限制 # # 调整断路器限制(谨慎使用) PUT /_cluster/settings { "persistent": { "indices.breaker.total.limit": "70%", "indices.breaker.fielddata.limit": "40%", "indices.breaker.request.limit": "40%" } } 3. 减少请求大小 # # 使用分页而不是一次获取大量数据 GET /<index>/_search { "size": 100, "from": 0, "query": { "match_all": {} } } # 或使用 scroll API POST /<index>/_search?" --- ## 为什么这个错误发生 `circuit_breaking_exception` 表示断路器被触发。断路器是 Easysearch 的内存保护机制,防止操作消耗过多内存导致 OutOfMemoryError。 这个错误可能由以下原因引起: 1. **请求过大**:单个请求尝试加载过多数据到内存 2. **聚合数据过多**:聚合操作产生的桶数量过多 3. **字段数据缓存**:字段数据(fielddata)缓存占用过多内存 3. **请求级断路器**:单个请求的内存使用超过限制 4. **父级断路器**:所有请求的总内存使用超过限制 5. **JVM 堆内存不足**:JVM 堆内存设置过小 6. **高并发**:并发请求过多导致总内存使用超限 7. **深度分页**:from + size 值过大 ## 如何修复这个错误 ### 1. 查看断路器状态 ```bash # 查看所有断路器的状态 GET /_nodes/stats/breaker?pretty # 查看特定节点的断路器 GET /_nodes//stats/breaker ``` ### 2. 增加断路器限制 ```bash # 调整断路器限制(谨慎使用) PUT /_cluster/settings { "persistent": { "indices.breaker.total.limit": "70%", "indices.breaker.fielddata.limit": "40%", "indices.breaker.request.limit": "40%" } } ``` ### 3. 减少请求大小 ```bash # 使用分页而不是一次获取大量数据 GET //_search { "size": 100, "from": 0, "query": { "match_all": {} } } # 或使用 scroll API POST //_search?scroll=1m { "size": 1000, "query": { "match_all": {} } } ``` ### 4. 优化聚合查询 ```bash # 使用 composite aggregation 处理大量数据 GET //_search { "size": 0, "aggs": { "my_buckets": { "composite": { "size": 1000, "sources": [ { "field_name": { "terms": { "field": "field" } } } ] } } } } # 使用 after_key 获取下一页 ``` ### 5. 处理字段数据断路器 ```bash # 查看字段数据缓存使用 GET /_indices//fielddata?fields=field_name # 清理字段数据缓存 POST //_cache/clear?fielddata=true # 使用 doc_values 而不是 fielddata PUT //_mapping { "properties": { "field": { "type": "keyword", "doc_values": true } } } ``` ### 6. 减少聚合精度 ```bash # 使用 cardinalinality 近似聚合 GET //_search { "aggs": { "unique_count": { "cardinality": { "field": "field", "precision_threshold": 100 } } } } ``` ### 7. 分批处理大量数据 ```bash # 使用 update_by_query 分批处理 POST //_update_by_query?conflicts=proceed&scroll_size=1000 { "query": { "range": { "timestamp": { "gte": "2023-01-01" } } }, "script": { "source": "ctx._source.new_field = 'value'" } } ``` ### 8. 增加 JVM 堆内存 如果频繁触发断路器,考虑增加堆内存: ```bash # 修改 config/jvm.options -Xms16g -Xmx16g # 注意:堆内存不应超过 31GB,且应为物理内存的 50% 左右 ``` ### 9. 使用 search_after 代替深度分页 ```bash # 使用 search_after 进行深度分页 GET //_search { "size": 100, "query": { "match_all": {} }, "sort": [ {"date": "asc"}, {"_id": "asc"} ], "search_after": [1625097600000, "doc_id"] } ``` ### 10. 监控内存使用 ```bash # 查看节点内存使用 GET /_nodes/stats/jvm?human&pretty # 查看字段数据使用 GET /_cat/fielddata?v&fields=* ``` ### 预防措施 - 合理设置断路器限制(通常为堆内存的 40-70%) - 使用 doc_values 而不是 fielddata - 避免在文本字段上使用聚合或排序 - 使用 search_after 或 scroll API 代替深度分页 - 使用 composite aggregation 处理大量桶 - 定期清理不需要的缓存 - 监控断路器状态,及早发现问题 - 对大型操作进行分批处理 - 考虑使用更小的时间窗口进行数据聚合