排查 Elasticsearch 请求被拒绝的问题

Elasticsearch 拒绝请求时,会停止该操作,并返回 HTTP 429 状态码,表示 TOO_MANY_REQUESTS。HTTP 响应正文会说明拒绝原因。可以重试 HTTP 429 错误,但一般应使用指数退避,避免进一步加重性能问题。

检查被拒绝的任务

请求被拒绝往往是资源耗尽造成的,以下介绍最常见的原因。

查看线程池

使用 cat thread pool API 检查每个线程池被拒绝的任务数量:


				GET /_cat/thread_pool?v=true&h=id,name,queue,active,rejected,completed
		

如果 rejected 相对于 completed 的比例很高,尤其是在 search 和 write 线程池中,说明 Elasticsearch 经常拒绝请求。

下面是典型的队列容量错误。API 响应正文返回 es_rejected_execution_exception:


{
    "shard" : 0,
    "node" : "XXXX",
    "reason" : {
       "reason" : "rejected execution of org.elasticsearch.common.util.concurrent.TimedRunnable@26c03d4a on QueueResizingEsThreadPoolExecutor[name = XXXXX/search, queue capacity = 1000, min queue capacity = 1000, max queue capacity = 1000, frame size = 2000, targeted response rate = 1s, task execution EWMA = 968.1ms, adjustment amount = 50, org.elasticsearch.common.util.concurrent.QueueResizingEsThreadPoolExecutor@70be0765[Running, pool size = 25, active threads = 25, queued tasks = 1000, completed tasks = 616499351]]",
       "type" : "es_rejected_execution_exception"
    },
    "index" : "my-index-000001"
}
		

错误日志则返回 EsRejectedExecutionException:


Caused by: org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution of org.elasticsearch.common.util.concurrent.TimedRunnable@1a25fe82 on QueueResizingEsThreadPoolExecutor[name = XXXXX/search, queue capacity = 1000, min queue capacity = 1000, max queue capacity = 1000, frame size = 2000, targeted response rate = 1s, task execution EWMA = 10.7ms, adjustment amount = 50, org.elasticsearch.common.util.concurrent.QueueResizingEsThreadPoolExecutor@6312a0bb[Running, pool size = 25, active threads = 25, queued tasks = 1000, completed tasks = 616499351]]
		

如果线程池拒绝错误持续发生,请排查线程池导致的任务队列积压。完整演示见线程池拒绝问题视频。

检查熔断器

使用节点统计 API 检查熔断器触发次数:


				GET /_nodes/stats/breaker
		

这些统计自节点启动以来累计。更多信息见熔断器错误相关文档,也可观看熔断器错误排查视频。

分析索引压力

Elasticsearch 会预留部分 JVM 内存用于索引。如果堆使用量超过 indexing_pressure.memory.limit,就可能产生错误。通过节点统计 API 查看索引压力拒绝次数:


				GET _nodes/stats?human&filter_path=nodes.*.indexing_pressure
		

这些统计也是自节点启动以来累计。

以下示例展示索引压力导致的拒绝。API 响应正文返回 es_rejected_execution_exception:


{
  "error" : {
    "root_cause" : [
      {
        "type" : "es_rejected_execution_exception",
        "reason" : "rejected execution of primary operation [coordinating_and_primary_bytes=XXXXX, replica_bytes=XXXXX, all_bytes=XXXXX, coordinating_operation_bytes=XXXXX, max_coordinating_and_primary_bytes=XXXXX]"
      }
    ],
    "type" : "es_rejected_execution_exception",
    "reason" : "rejected execution of coordinating operation [coordinating_and_primary_bytes=XXXXX, replica_bytes=XXXXX, all_bytes=XXXXX, coordinating_operation_bytes=XXXXX, max_coordinating_and_primary_bytes=XXXXX]"
  },
  "status" : 429
}
		

错误日志返回 EsRejectedExecutionException:


Caused by: org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution of primary operation [coordinating_and_primary_bytes=XXXXX, replica_bytes=XXXXX, all_bytes=XXXXX, coordinating_operation_bytes=XXXXX, max_coordinating_and_primary_bytes=XXXXX]
		

按照文档读写模型,错误中的 rejected execution of <category> operation 会指出以下类别之一:combined_coordinating_and_primary、coordinating、primary 或 replica。

这些错误通常与以下情况有关:

  • 积压任务的数量。
  • 批量索引的批次设置过大。
  • 搜索响应体过大。
  • 使用 semantic_text 字段类型。对大批量文档建立索引时,如果继续处理可能导致内存不足(OOM),系统可能会拒绝请求。

排查演示见索引压力拒绝视频。

避免请求被拒绝

使用 AutoOps 检测并解决问题

AutoOps 是监控工具,能够实时检测 Elasticsearch 集群问题,并建议如何解决及改善性能。

解决 CPU 与内存使用率过高的问题

如果 Elasticsearch 经常拒绝请求和其他任务,集群很可能存在高 CPU 使用率或高 JVM 内存压力。可以参阅相应的高 CPU 使用率与高 JVM 内存压力排查文档。

解决 semantic_text 摄取问题

批量索引具有 semantic_text 字段的文档时,推理处理可能消耗过多内存,从而导致请求被拒绝。这些拒绝会在集群日志中表现为 InferenceException。

处理步骤:

  1. 减小索引请求中的文档批次。
  2. 如果缩小批次仍无法解决,考虑增加机器资源。

最后手段是调整集群设置 indexing_pressure.memory.coordinating.limit。默认值为堆内存的 10%。提高该限制,允许协调操作在被拒绝之前使用更多内存。

警告:只有其他方案都已尝试后,才应考虑调整这一值。设置过高可能让集群发生内存不足错误。修改后必须重启集群才会生效。


原文:Rejected requests。作者/维护方:Elastic 文档维护者。本文为中文翻译,代码及命令保留原文。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容