如何解决我的 Amazon OpenSearch Service 集群上的 CPU 利用率较高的问题?

3 分钟阅读
0

我的数据节点显示我的 Amazon OpenSearch Service 集群上的 CPU 使用率很高。

简短描述

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

要解决集群 CPU 利用率较高的问题,请考虑以下方法:

  • 使用节点热点线程 API。
  • 检查写入操作或批量 API 线程池。
  • 检查搜索线程池。
  • 检查 Apache Lucene 合并线程池。
  • 检查 JVM 内存压力
  • 查看您的分片策略
  • 优化您的查询

解决方法

使用节点热点线程 API

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

以下是节点热点线程 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

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

然后,将相关节点名称传递给您的热点线程 API:

GET _nodes/<node-name>/hot_threads

有关详细信息,请参阅 Elasticsearch 网站上的热点线程 API

节点热点线程输出示例:

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

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

有关详细信息,请参阅 Elasticsearch 网站上的节点热点线程 API

检查写入操作或批量 API 线程池

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

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

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

  • 减少集群批量请求的数量。
  • 减小每个批量请求的大小,以便节点可以更有效地处理它们。
  • 如果使用 Logstash 将数据推送到您的 OpenSearch Service 集群,请减少批量大小或 Worker 数量。
  • 如果您的集群的摄取速度变慢,请扩展您的集群(水平或垂直)。要扩展您的集群,请增加节点数量和实例类型,以便 OpenSearch Service 可以处理传入的请求。

有关详细信息,请参阅 Elasticsearch 网站上的批量 API

查看搜索线程池

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

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

GET _tasks?actions=*search&detailed

任务管理 API 会获取集群上正在运行的所有活动搜索查询。有关详细信息,请参阅 Elasticsearch 网站上的任务管理 API

注意: 只有当任务管理 API 列出了搜索任务时,输出才会包含 description 字段。

示例输出:

{
    "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 调用示例:

POST _tasks/U4M_p_x2Rg6YqLujeInPOw:53506997/_cancel

任务管理 POST 调用将任务标记为“已取消”,从而释放所有依赖的 AWS 资源。如果您的集群上正在运行多个查询,请使用 POST 调用一次取消一个查询。取消每个查询,直到您的集群恢复到正常状态。在查询正文中设置超时值可防止 CPU 峰值过高,也是一种最佳做法。有关详细信息,请参阅 Elasticsearch 网站上的请求正文搜索参数。要验证活动查询的数量是否减少,请查看 Amazon CloudWatch 中的 SearchRate 指标。

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

有关详细信息,请参阅 Elasticsearch 网站上的线程池

查看 Apache Lucene 合并线程池

OpenSearch Service 使用 Apache Lucene 为集群上的文档编制索引和搜索文档。Apache Lucene 运行合并操作来减少每个分片所需的有效区段数,并移除所有已删除的文档。每当在分片中创建新区段时,都会运行此过程。

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

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

要检查 UltraWarm 迁移,请使用以下命令:

GET _ultrawarm/migration/_status?v

有关详细信息,请参阅 Elasticsearch 网站上的合并

检查 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 个

默认情况下,Amazon OpenSearch Service 的分片策略为 5:1,其中每个索引分为五个主分片。在每个索引中,每个主分片也有自己的副本。OpenSearch Service 会自动将主分片和副本分片分配给单独的数据节点,并确保在出现故障时有备份。

有关详细信息,请参阅如果我的 Amazon OpenSearch Service 集群中的分片分配不均匀,如何重新平衡?

优化您的查询

繁重聚合、通配符查询(尤其是前导通配符)和正则表达式查询可能计算成本高昂,并导致 CPU 利用率飙升。搜索慢日志和索引慢日志可以帮助您诊断昂贵且有问题的查询。

有关详细信息,请参阅使用 Amazon CloudWatch Logs 监控 OpenSearch 日志

相关信息

如何提高我的 Amazon OpenSearch Service 集群的索引性能?

如何解决 Amazon OpenSearch Service 中的搜索或写入拒绝问题?

调整 Amazon OpenSearch Service 域的大小

AWS 官方
AWS 官方已更新 1 年前