高 CPU 使用率

编辑

Elasticsearch 使用线程池来管理并发操作的 CPU 资源。高 CPU 使用率通常意味着一个或多个线程池运行缓慢。

如果线程池耗尽,Elasticsearch 将拒绝与该线程池相关的请求。例如,如果search线程池耗尽,Elasticsearch 将拒绝搜索请求,直到有更多线程可用。

如果数据层(以及分配给该层的节点)经历的流量多于其他层,则可能会遇到高 CPU 使用率。这种资源利用率的不平衡也称为热点

诊断高 CPU 使用率

编辑

检查 CPU 使用率

您可以使用cat 节点 API检查每个节点的 CPU 使用率。

resp = client.cat.nodes(
    v=True,
    s="cpu:desc",
)
print(resp)
response = client.cat.nodes(
  v: true,
  s: 'cpu:desc'
)
puts response
const response = await client.cat.nodes({
  v: "true",
  s: "cpu:desc",
});
console.log(response);
GET _cat/nodes?v=true&s=cpu:desc

响应的cpu列包含当前 CPU 使用率(以百分比表示)。name列包含节点的名称。CPU 使用率升高但短暂是正常的。但是,如果 CPU 使用率在较长时间内保持升高,则应进行调查。

要跟踪随时间推移的 CPU 使用率,我们建议启用监控。

  • (推荐)启用日志和指标。启用日志和指标后,监控信息将在 Kibana 的堆栈监控页面上可见。

    您还可以启用CPU 使用率阈值警报,以便通过电子邮件收到有关潜在问题的通知。

  • 从您的部署菜单中,查看性能页面。在此页面上,您可以查看两个关键指标

    • CPU 使用率:您的部署的 CPU 使用率,以百分比表示。
    • CPU 配额:您剩余的 CPU 配额,以 CPU 时间的秒数衡量。

Elasticsearch 服务为每个部署授予CPU 配额,以便在需要时为较小的集群提供性能提升。高 CPU 使用率可能会耗尽这些配额,这可能会导致性能下降集群响应时间增加

检查热点线程

如果某个节点的 CPU 使用率很高,请使用节点热点线程 API检查在该节点上运行的资源密集型线程。

resp = client.nodes.hot_threads()
print(resp)
const response = await client.nodes.hotThreads();
console.log(response);
GET _nodes/hot_threads

此 API 以纯文本形式返回任何热点线程的细分。高 CPU 使用率通常与长时间运行的任务或任务积压相关。

降低 CPU 使用率

编辑

以下提示概述了高 CPU 使用率的最常见原因及其解决方案。

扩展集群

繁重的索引和搜索负载可能会耗尽较小的线程池。为了更好地处理繁重的负载,请向集群中添加更多节点或升级现有节点以提高容量。

分散批量请求

虽然比单个请求更有效,但大型批量索引多搜索请求仍然需要 CPU 资源。如果可能,请提交较小的请求并在它们之间留出更多时间。

取消长时间运行的搜索

长时间运行的搜索可能会阻塞search线程池中的线程。要检查这些搜索,请使用任务管理 API

resp = client.tasks.list(
    actions="*search",
    detailed=True,
)
print(resp)
response = client.tasks.list(
  actions: '*search',
  detailed: true
)
puts response
const response = await client.tasks.list({
  actions: "*search",
  detailed: "true",
});
console.log(response);
GET _tasks?actions=*search&detailed

响应的description包含搜索请求及其查询。running_time_in_nanos显示搜索已运行多长时间。

{
  "nodes" : {
    "oTUltX4IQMOUUVeiohTt8A" : {
      "name" : "my-node",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1:9300",
      "tasks" : {
        "oTUltX4IQMOUUVeiohTt8A:464" : {
          "node" : "oTUltX4IQMOUUVeiohTt8A",
          "id" : 464,
          "type" : "transport",
          "action" : "indices:data/read/search",
          "description" : "indices[my-index], search_type[QUERY_THEN_FETCH], source[{\"query\":...}]",
          "start_time_in_millis" : 4081771730000,
          "running_time_in_nanos" : 13991383,
          "cancellable" : true
        }
      }
    }
  }
}

要取消搜索并释放资源,请使用 API 的_cancel端点。

resp = client.tasks.cancel(
    task_id="oTUltX4IQMOUUVeiohTt8A:464",
)
print(resp)
response = client.tasks.cancel(
  task_id: 'oTUltX4IQMOUUVeiohTt8A:464'
)
puts response
const response = await client.tasks.cancel({
  task_id: "oTUltX4IQMOUUVeiohTt8A:464",
});
console.log(response);
POST _tasks/oTUltX4IQMOUUVeiohTt8A:464/_cancel

有关如何跟踪和避免资源密集型搜索的其他提示,请参阅避免昂贵的搜索