如何解决我的 Amazon OpenSearch Service 集群上的 CPU 利用率较高的问题?
我的数据节点显示我的 Amazon OpenSearch Service 集群上的 CPU 使用率很高。
简短描述
最佳做法是保持您的 CPU 利用率,确保 OpenSearch Service 有足够的资源来执行其任务。集群始终以较高 CPU 利用率运行可能会降低集群性能。当您的集群超载时,OpenSearch 服务会停止响应,从而导致请求超时。
要解决集群上的 CPU 使用率过高的问题,请执行以下操作:
- 使用自动运行手册。
- 使用节点热点线程 API。
- 检查写入操作或批量 API 线程池。
- 检查搜索线程池。
- 检查 Apache Lucene 合并线程池。
- 检查 JVM 内存压力。
- 查看您的分片策略。
- 优化您的查询。
解决方法
使用自动运行手册
使用 AWSSupport-TroubleshootOpenSearchHighCPU AWS Systems Manager Automation 运行手册对 OpenSearch 服务中的 CPU 使用率较高问题进行故障排除。
**注意:**在使用运行手册之前,请查看 AWSSupport-TroubleshootOpenSearchHighCPU 中的 Required AWS Identity and Access Management (IAM) permissions(所需的 AWS Identity and Access Management (IAM) 权限)和 Instructions(说明)部分。
输出显示以下信息:
- 热点线程。
- 当前正在运行的任务。
- 域中每个节点的线程池统计信息。
- 有关域中节点的信息,按其 CPU 使用率排序。
- 对每个数据节点及其磁盘空间进行分片分配。
- 运行状况和有关 OpenSearch Service 域运行状况的信息。
使用运行手册的输出来确定 CPU 利用率高的原因。
使用节点热点线程 API
如果您的 OpenSearch Service 集群持续出现 CPU 峰值,请使用节点热点线程 API。有关详细信息,请参阅 Elastic 网站上的节点热点线程 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)
**注意:**节点热点线程输出列出了每个节点的信息。输出的长度取决于您的 OpenSearch Service 集群中正在运行的节点数。
您还可以使用 cat 节点 API 查看当前的资源利用率细分情况。要缩小 CPU 利用率最高的节点子集,请运行以下命令:
GET _cat/nodes?v&s=cpu:desc
输出中的最后一列显示了您的节点名称。有关详细信息,请参阅 Elastic 网站上的 cat 节点 API。
将相关节点名称传递给您的热点线程 API:
GET _nodes/<node-name>/hot_threads
有关详细信息,请参阅 Elastic 网站上的热点线程 API。
输出示例:
<percentage> of cpu usage by thread 'opensearch[<nodeName>][<thread-name>]'
线程名称指示 CPU 占用较高的 OpenSearch Service 进程。
检查写入操作或批量 API 线程池
OpenSearch Service 中的 429 错误可能表明您的集群正在处理的批量索引请求过多。当您的集群中持续出现 CPU 峰值时,OpenSearch Service 会拒绝批量索引请求。
write(写入)线程池处理索引请求,其中包括 Bulk(批量)API 操作。要检查您的集群是否正在处理的批量索引请求过多,请查看 Amazon CloudWatch 中的 IndexingRate 指标。
如果您的集群正在处理的批量索引请求过多,请执行以下操作:
- 减少集群批量请求的数量。
- 减小每个批量请求的大小,以便节点可以更有效地处理它们。
- 如果使用 Logstash 将数据推送到您的 OpenSearch Service 集群,请减少批量大小或 Worker 数量。
- 如果您的集群的摄取速度变慢,请水平或垂直扩展您的集群。要纵向扩展您的集群,请增加节点数量和实例类型,以便 OpenSearch Service 可以处理传入的请求。
有关详细信息,请参阅 Elastic 网站上的批量 API。
查看搜索线程池
占用较高 CPU 的搜索线程池表明搜索查询使您的 OpenSearch Service 集群不堪重负。一个长时间运行的查询可能会使您的集群不堪重负。您的集群执行的查询次数增加也会影响您的搜索线程池。
要查看单个查询是否在增加 CPU 使用率,请使用任务管理 API:
GET _tasks?actions=*search&detailed
任务管理 API 会获取集群上正在运行的所有活动搜索查询。有关详细信息,请参阅 Elastic 网站上的任务管理 API。
注意:如果任务管理 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 的搜索查询。任务管理 API 还支持 _cancel 调用。
**注意:**要取消任务,请记录输出中的任务 ID。在以下示例中,任务 ID 为 U4M_p_x2Rg6YqLujeInPOw:53506997。
示例调用:
POST _tasks/U4M_p_x2Rg6YqLujeInPOw:53506997/_cancel
任务管理 POST 调用将任务标记为“已取消”,并释放所有依赖的 AWS 资源。如果您的集群上正在运行多个查询,请使用 POST 调用取消每个查询,直到您的集群恢复正常状态。
要防止 CPU 峰值过高,在查询正文中设置超时值也是一种最佳做法。有关详细信息,请参阅 Elastic 网站上的参数。要验证活动查询的数量是否减少,请查看 CloudWatch 中的 SearchRate 指标。有关详细信息,请参阅 Elastic 网站上的线程池。
**注意:**在 OpenSearch Service 集群中同时取消所有活动搜索查询时,客户端应用程序端可能会出错。
查看 Apache Lucene 合并线程池
OpenSearch Service 使用 Apache Lucene 来索引和搜索集群上的文档。当您创建新的分片区段时,Apache Lucene 会运行合并操作以减少每个分区的有效区段数并移除已删除的文档。
如果 Apache Lucene 合并线程操作影响了 CPU 使用率,请增加 OpenSearch Service 集群索引的 refresh_interval 设置。refresh_interval 设置增加会减慢集群区段创建速度。有关详细信息,请参阅 Elastic 网站上的 index.refresh_interval。
注意:将索引迁移到 UltraWarm 存储的集群可以提高您的 CPU 利用率。UltraWarm 迁移通常涉及强制合并 API 操作,该操作可能会占用大量 CPU。有关详细信息,请参阅 Elastic 网站上的强制合并 API。
要检查 UltraWarm 迁移,请运行以下命令:
GET _ultrawarm/migration/_status?v
有关详细信息,请参阅 Elastic 网站上的合并。
检查 JVM 内存压力
查看群集节点中 Java 堆的 JVM 内存压力百分比。如果 JVM 内存压力达到 75%,则 Amazon OpenSearch Service 会启动并发标记清除 (CMS) 垃圾收集器。如果 JVM 内存压力达到 100%,则 OpenSearch Service JVM 退出,并最终在 OutOfMemory (OOM) 时重启。
在以下示例日志中,JVM 处于建议范围内,但集群受到长时间运行的垃圾回收的影响:
[2022-06-28T10:08:12,066][WARN ][o.o.m.j.JvmGcMonitorService] [515f8f06f23327e6df3aad7b2863bb1f] [gc][6447732] overhead, spent [9.3s] collecting in the last [10.2s]
有关详细信息,请参阅如何解决 Amazon OpenSearch Service 集群上的高 JVM 内存压力问题?
查看您的分片策略
根据集群大小,您的集群性能可能会由于分片过多而降低。最佳做法是每 GiB 的 Java 堆最多只有 25 个分片。
默认情况下,OpenSearch Service 的分片策略为 5:1,其中每个索引分为五个主分片。在每个索引中,每个主分片也有自己的副本。OpenSearch Service 会自动将主分片和副本分片分配给单独的数据节点,并确保在出现故障时有备份。
有关详细信息,请参阅如果我的 Amazon OpenSearch Service 集群中的分片分配不均匀,如何重新平衡?
优化您的查询
大量聚合、通配符查询(例如前导通配符)和正则表达式查询可能会导致 CPU 利用率飙升。要诊断这些查询,请搜索慢速日志并编制索引。有关详细信息,请参阅使用 Amazon CloudWatch Logs 监控 OpenSearch 日志。
相关信息
如何提高我的 Amazon OpenSearch Service 集群的索引性能?