高いCPU使用率

Elasticsearchは、同時操作のためにCPUリソースを管理するためにスレッドプールを使用します。高いCPU使用率は通常、1つ以上のスレッドプールが不足していることを意味します。

スレッドプールが枯渇すると、Elasticsearchはそのスレッドプールに関連するリクエストを拒否します。たとえば、searchスレッドプールが枯渇している場合、Elasticsearchは、より多くのスレッドが利用可能になるまで検索リクエストを拒否します。

データティアが他のティアよりも多くのトラフィックを受けている場合、そのティアに割り当てられたノードも高いCPU使用率を経験する可能性があります。このリソース利用の不均衡は、ホットスポッティングとしても知られています。

高いCPU使用率の診断

CPU使用率を確認する

cat nodes APIを使用して、ノードごとのCPU使用率を確認できます:

Python

  1. resp = client.cat.nodes(
  2. v=True,
  3. s="cpu:desc",
  4. )
  5. print(resp)

Ruby

  1. response = client.cat.nodes(
  2. v: true,
  3. s: 'cpu:desc'
  4. )
  5. puts response

Js

  1. const response = await client.cat.nodes({
  2. v: "true",
  3. s: "cpu:desc",
  4. });
  5. console.log(response);

コンソール

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

レスポンスのcpu列には、現在のCPU使用率がパーセンテージで表示されます。name列には、ノードの名前が表示されます。高いが一時的なCPU使用率は正常です。ただし、CPU使用率が長時間高い場合は、調査する必要があります。

CPU使用率を時間の経過とともに追跡するには、監視を有効にすることをお勧めします:

  • (推奨)ログとメトリクスを有効にします。ログとメトリクスが有効になっている場合、監視情報はKibanaのスタックモニタリングページに表示されます。
    CPU使用率のしきい値アラートを有効にして、潜在的な問題についてメールで通知を受けることもできます。
  • デプロイメントメニューから、パフォーマンスページを表示します。このページでは、2つの重要なメトリクスを表示できます:
    • CPU使用率:デプロイメントのCPU使用率をパーセンテージで表します。
    • CPUクレジット:残りのCPUクレジットをCPU時間の秒数で測定します。

Elasticsearchサービスは、必要に応じて小規模クラスターにパフォーマンスブーストを提供するために、デプロイメントごとにCPUクレジットを付与します。高いCPU使用率はこれらのクレジットを消耗させ、パフォーマンスの低下クラスターの応答時間の増加を引き起こす可能性があります。

ホットスレッドを確認する

ノードに高いCPU使用率がある場合は、nodes hot threads APIを使用して、ノード上で実行されているリソース集約型スレッドを確認します。

Python

  1. resp = client.nodes.hot_threads()
  2. print(resp)

Js

  1. const response = await client.nodes.hotThreads();
  2. console.log(response);

コンソール

  1. GET _nodes/hot_threads

このAPIは、プレーンテキストでホットスレッドの内訳を返します。高いCPU使用率は、長時間実行されているタスクまたはタスクのバックログと頻繁に相関します。

CPU使用率を減らす

以下のヒントは、高いCPU使用率の最も一般的な原因とその解決策を概説しています。

クラスターをスケールする

重いインデックス作成や検索負荷は、小さなスレッドプールを枯渇させる可能性があります。重い作業負荷をより良く処理するために、クラスターにノードを追加するか、既存のノードをアップグレードして容量を増やします。

バルクリクエストを分散させる

個別のリクエストよりも効率的ですが、大規模なバルクインデックス作成multi-searchリクエストは、依然としてCPUリソースを必要とします。可能であれば、より小さなリクエストを送信し、それらの間により多くの時間を取ります。

長時間実行されている検索をキャンセルする

長時間実行されている検索は、searchスレッドプールのスレッドをブロックする可能性があります。これらの検索を確認するには、タスク管理APIを使用します。

Python

  1. resp = client.tasks.list(
  2. actions="*search",
  3. detailed=True,
  4. )
  5. print(resp)

Ruby

  1. response = client.tasks.list(
  2. actions: '*search',
  3. detailed: true
  4. )
  5. puts response

Js

  1. const response = await client.tasks.list({
  2. actions: "*search",
  3. detailed: "true",
  4. });
  5. console.log(response);

コンソール

  1. GET _tasks?actions=*search&detailed

レスポンスのdescriptionには、検索リクエストとそのクエリが含まれています。running_time_in_nanosは、検索がどれくらいの時間実行されているかを示します。

コンソール-結果

  1. {
  2. "nodes" : {
  3. "oTUltX4IQMOUUVeiohTt8A" : {
  4. "name" : "my-node",
  5. "transport_address" : "127.0.0.1:9300",
  6. "host" : "127.0.0.1",
  7. "ip" : "127.0.0.1:9300",
  8. "tasks" : {
  9. "oTUltX4IQMOUUVeiohTt8A:464" : {
  10. "node" : "oTUltX4IQMOUUVeiohTt8A",
  11. "id" : 464,
  12. "type" : "transport",
  13. "action" : "indices:data/read/search",
  14. "description" : "indices[my-index], search_type[QUERY_THEN_FETCH], source[{\"query\":...}]",
  15. "start_time_in_millis" : 4081771730000,
  16. "running_time_in_nanos" : 13991383,
  17. "cancellable" : true
  18. }
  19. }
  20. }
  21. }
  22. }

検索をキャンセルしてリソースを解放するには、APIの_cancelエンドポイントを使用します。

Python

  1. resp = client.tasks.cancel(
  2. task_id="oTUltX4IQMOUUVeiohTt8A:464",
  3. )
  4. print(resp)

Ruby

  1. response = client.tasks.cancel(
  2. task_id: 'oTUltX4IQMOUUVeiohTt8A:464'
  3. )
  4. puts response

Js

  1. const response = await client.tasks.cancel({
  2. task_id: "oTUltX4IQMOUUVeiohTt8A:464",
  3. });
  4. console.log(response);

コンソール

  1. POST _tasks/oTUltX4IQMOUUVeiohTt8A:464/_cancel

リソース集約型の検索を追跡し回避する方法についての追加のヒントは、高コストの検索を避けるを参照してください。