如何排查 Amazon OpenSearch Service 集群上 CPU 使用率较高的问题?

上次更新日期:2021 年 8 月 5 日

我的数据节点显示 Amazon OpenSearch Service(Amazon Elasticsearch Service 的后继者) 集群的 CPU 使用率较高。如何排查此问题?

简短描述

最佳做法是保持现有的 CPU 利用率,确保 OpenSearch Service 有足够的资源来执行其任务。集群始终以较高的 CPU 利用率运行可能会降低集群性能。当您的集群超载时,OpenSearch Service 将会停止响应,从而导致请求超时。

要排查集群 CPU 使用率较高的问题,请考虑以下方法:

  • 使用 Nodes hot threads(节点热点线程)API。(有关更多信息,请参阅 Elasticsearch 网站上的 Nodes hot threads API。)
  • 查看 write 操作或 bulk API 线程池。(有关更多信息,请参阅 Elasticsearch 网站上的 Bulk API。)
  • 查看 search 线程池。(有关更多信息,请参阅 Elasticsearch 网站上的线程池。)
  • 查看 Apache Lucene merge 线程池。(有关更多信息,请参阅 Elasticsearch 网站上的 Merge。)

解决方法

使用 Nodes hot threads(节点热点线程)API

如果 OpenSearch Service 集群中的 CPU 持续处于峰值,请使用 nodes hot threads(节点热点线程)API。nodes hot threads(节点热点线程)API 充当任务管理器,向您显示集群上运行的所有资源密集型线程的细分情况。

以下是 nodes hot threads(节点热点线程)API 的示例输出:

GET _nodes/hot_threads

100.0% (131ms out of 500ms) cpu usage by thread 
'opensearch[xxx][search][T#62]' 10/10 snapshots sharing following 10 
elements sun.misc.Unsafe.park(Native Method) 
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
java.util.concurrent.LinkedTransferQueue.awaitMatch(LinkedTransferQueue.java:737)
 
java.util.concurrent.LinkedTransferQueue.xfer(LinkedTransferQueue.java:647)
 
java.util.concurrent.LinkedTransferQueue.take(LinkedTransferQueue.java:1269)
 
org.opensearch.common.util.concurrent.SizeBlockingQueue.take(SizeBlockingQueue.java:162)
 
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
注意: nodes hot threads 输出列示了每个节点的信息。输出的长度取决于 OpenSearch Service 集群中运行的节点数。

此外,可以使用 cat nodes(cat 节点)API 查看资源利用率的当前细分情况。您可以使用以下命令缩小 CPU 利用率最高的节点子集:

GET _cat/nodes?v&s=cpu:desc

输出中的最后一列显示了节点名称。有关更多信息,请参阅 Elasticsearch 网站上的 cat nodes API

然后,将相关节点名称传递给 hot threads API:

GET _nodes/<node-name>/hot_threads

有关更多信息,请参阅 Elasticsearch 网站上的 hot threads API

nodes hot threads 输出如下所示:

<percentage> of cpu usage by thread 'opensearch[<nodeName>][<thread-name>]

线程名称表示哪些 OpenSearch Service 进程正在占用较高的 CPU。

查看 write 操作或 bulk API 线程池

OpenSearch Service 中的 429 error(429 错误)可能表明您的集群正在处理的批量索引请求过多。当您的集群中的 CPU 持续处于峰值时,OpenSearch Service 将拒绝批量索引请求。

write(写入)线程池处理索引请求,其中包括批量 API 操作。要确认您的集群是否正在处理过多的批量索引请求,请查看 Amazon CloudWatch 中的 IndexingRate 指标。

如果您的集群正在处理的批量索引请求过多,可以考虑以下方法:

  • 减少集群批量请求的数量。
  • 减小每个批量请求的大小,以便节点可以更有效地处理它们。
  • 如果使用 Logstash 将数据推送到 OpenSearch Service 集群中,则缩小批量大小或减少工作线程的数量。
  • 如果集群的提取速度降低,请(水平或垂直)扩展集群。要扩展集群,请增加节点数量和实例类型,以便 OpenSearch Service 能够正确处理传入的请求。

查看 search 线程池

占用较高 CPU 的 search 线程池表明搜索查询正在使您的 OpenSearch Service 集群不堪重负。单个长时间运行的查询可能会使您的集群不堪重负。集群正在执行的查询数量增加也会影响 search 线程池。

要查看是否是单个查询正在增加您的 CPU 使用率,请使用任务管理 API。例如:

GET _tasks?actions=*search&detailed

task management(任务管理)API 将获取集群上运行的所有活动搜索查询。有关更多信息,请参阅 Elasticsearch 网站上的 Task management(任务管理)API。

以下是示例输出:

{
  "nodes": {
    "U4M_p_x2Rg6YqLujeInPOw": {
      "name": "U4M_p_x",
      "roles": [
        "data",
        "ingest"
      ],
      "tasks": {
        "U4M_p_x2Rg6YqLujeInPOw:53506997": {
          "node": "U4M_p_x2Rg6YqLujeInPOw",
          "id": 53506997,
          "type": "transport",
          "action": "indices:data/read/search",
          "description": """indices[*], types[], search_type[QUERY_THEN_FETCH], source[{"size":10000,"query":{"match_all":{"boost":1.0}}}]""",
          "start_time_in_millis": 1541423217801,
          "running_time_in_nanos": 1549433628,
          "cancellable": true,
          "headers": {}
        }
      }
    }
  }
}

检查 description(描述)字段,确定正在运行的特定查询。running_time_in_nanos 字段指出查询运行的时长。要降低 CPU 使用率,请取消正在占用较高 CPU 的搜索查询。task management API 还支持 _cancel 调用。

注意:请务必记录输出的任务 ID,以便用于取消特定任务。在此示例中,任务 ID 为“U4M_p_x2Rg6YqLujeInPOw:53506997”。

以下是 task management POST 调用的示例:

POST _tasks/U4M_p_x2Rg6YqLujeInPOw:53506997/_cancel

Task Management POST 调用会将任务标记为“已取消”,从而释放所有相关 AWS 资源。如果集群上运行了多个查询,请使用 POST 调用一次取消一个查询。取消每个查询,直至集群恢复正常状态。最佳做法是在查询正文中设置适当的超时值,以防止较高的 CPU 峰值。(有关更多信息,请参阅 Elasticsearch 网站上的请求正文搜索参数。) 要验证活动查询的数量是否减少,请查看 Amazon CloudWatch 中的 SearchRate 指标。

注意:同时取消 OpenSearch Service 集群中的所有活动搜索查询可能会导致客户端应用程序端出错。

查看 Apache Lucene merge 线程池

OpenSearch Service 使用 Apache Lucene 对集群上的文档进行索引和搜索。Apache Lucene 运行 merge(合并)操作,以减少每个分区所需的有效区段数,并移除所有已删除的文档。只要在分区中创建新区段就会运行此过程。

如果您观察到 Apache Lucene merge(合并)线程操作影响了 CPU 使用率,请增加 OpenSearch Service 集群索引的 refresh_interval 设置值。refresh_interval 设置的增加会减慢集群的区段创建速度。

注意将索引迁移到 UltraWarm 存储的集群可以提高 CPU 利用率。UltraWarm 迁移通常涉及 force merge(强制合并) API 操作,该操作可能会占用大量 CPU。

要查看是否有任何 UltraWarm 迁移,请使用以下命令:

GET _ultrawarm/migration/_status?v