断路器错误

编辑

Elasticsearch 使用断路器来防止节点耗尽 JVM 堆内存。如果 Elasticsearch 估计某个操作会超过断路器的限制,它会停止该操作并返回错误。

默认情况下,父断路器会在 JVM 内存使用率达到 95% 时触发。为了防止错误,我们建议在内存使用率持续超过 85% 时采取措施减少内存压力。

诊断断路器错误

编辑

错误信息

如果请求触发了断路器,Elasticsearch 会返回一个带有 429 HTTP 状态码的错误。

{
  'error': {
    'type': 'circuit_breaking_exception',
    'reason': '[parent] Data too large, data for [<http_request>] would be [123848638/118.1mb], which is larger than the limit of [123273216/117.5mb], real usage: [120182112/114.6mb], new bytes reserved: [3666526/3.4mb]',
    'bytes_wanted': 123848638,
    'bytes_limit': 123273216,
    'durability': 'TRANSIENT'
  },
  'status': 429
}

Elasticsearch 还会将断路器错误写入elasticsearch.log。这在自动化流程(例如分配)触发断路器时非常有用。

Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [<transport_request>] would be [num/numGB], which is larger than the limit of [num/numGB], usages [request=0/0b, fielddata=num/numKB, in_flight_requests=num/numGB, accounting=num/numGB]

检查 JVM 内存使用情况

如果您已启用 Stack Monitoring,则可以在 Kibana 中查看 JVM 内存使用情况。在主菜单中,点击Stack Monitoring。在 Stack Monitoring 的概述页面上,点击节点JVM 堆列显示每个节点的当前内存使用情况。

您还可以使用cat nodes API获取每个节点的当前heap.percent

resp = client.cat.nodes(
    v=True,
    h="name,node*,heap*",
)
print(resp)
response = client.cat.nodes(
  v: true,
  h: 'name,node*,heap*'
)
puts response
const response = await client.cat.nodes({
  v: "true",
  h: "name,node*,heap*",
});
console.log(response);
GET _cat/nodes?v=true&h=name,node*,heap*

要获取每个断路器的 JVM 内存使用情况,请使用节点统计 API

resp = client.nodes.stats(
    metric="breaker",
)
print(resp)
response = client.nodes.stats(
  metric: 'breaker'
)
puts response
const response = await client.nodes.stats({
  metric: "breaker",
});
console.log(response);
GET _nodes/stats/breaker

防止断路器错误

编辑

减少 JVM 内存压力

高 JVM 内存压力通常会导致断路器错误。请参阅高 JVM 内存压力

避免在 text 字段上使用 fielddata

对于高基数的 text 字段,fielddata 可能会使用大量的 JVM 内存。为了避免这种情况,Elasticsearch 默认情况下会禁用 text 字段上的 fielddata。如果您已启用 fielddata 并触发了fielddata 断路器,请考虑禁用它并改用 keyword 字段。请参阅fielddata 映射参数

清除 fielddata 缓存

如果您已触发 fielddata 断路器并且无法禁用 fielddata,请使用清除缓存 API清除 fielddata 缓存。这可能会中断任何使用 fielddata 的正在进行的搜索。

resp = client.indices.clear_cache(
    fielddata=True,
)
print(resp)
response = client.indices.clear_cache(
  fielddata: true
)
puts response
const response = await client.indices.clearCache({
  fielddata: "true",
});
console.log(response);
POST _cache/clear?fielddata=true