为什么这个错误发生 #
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?scroll=1m
{
"size": 1000,
"query": {
"match_all": {}
}
}
4. 优化聚合查询 #
# 使用 composite aggregation 处理大量数据
GET /<index>/_search
{
"size": 0,
"aggs": {
"my_buckets": {
"composite": {
"size": 1000,
"sources": [
{ "field_name": { "terms": { "field": "field" } } }
]
}
}
}
}
# 使用 after_key 获取下一页
5. 处理字段数据断路器 #
# 查看字段数据缓存使用
GET /_indices/<index>/fielddata?fields=field_name
# 清理字段数据缓存
POST /<index>/_cache/clear?fielddata=true
# 使用 doc_values 而不是 fielddata
PUT /<index>/_mapping
{
"properties": {
"field": {
"type": "keyword",
"doc_values": true
}
}
}
6. 减少聚合精度 #
# 使用 cardinalinality 近似聚合
GET /<index>/_search
{
"aggs": {
"unique_count": {
"cardinality": {
"field": "field",
"precision_threshold": 100
}
}
}
}
7. 分批处理大量数据 #
# 使用 update_by_query 分批处理
POST /<index>/_update_by_query?conflicts=proceed&scroll_size=1000
{
"query": {
"range": {
"timestamp": {
"gte": "2023-01-01"
}
}
},
"script": {
"source": "ctx._source.new_field = 'value'"
}
}
8. 增加 JVM 堆内存 #
如果频繁触发断路器,考虑增加堆内存:
# 修改 config/jvm.options
-Xms16g
-Xmx16g
# 注意:堆内存不应超过 31GB,且应为物理内存的 50% 左右
9. 使用 search_after 代替深度分页 #
# 使用 search_after 进行深度分页
GET /<index>/_search
{
"size": 100,
"query": { "match_all": {} },
"sort": [
{"date": "asc"},
{"_id": "asc"}
],
"search_after": [1625097600000, "doc_id"]
}
10. 监控内存使用 #
# 查看节点内存使用
GET /_nodes/stats/jvm?human&pretty
# 查看字段数据使用
GET /_cat/fielddata?v&fields=*
预防措施 #
- 合理设置断路器限制(通常为堆内存的 40-70%)
- 使用 doc_values 而不是 fielddata
- 避免在文本字段上使用聚合或排序
- 使用 search_after 或 scroll API 代替深度分页
- 使用 composite aggregation 处理大量桶
- 定期清理不需要的缓存
- 监控断路器状态,及早发现问题
- 对大型操作进行分批处理
- 考虑使用更小的时间窗口进行数据聚合





