Amazon Elasticsearch Service 클러스터의 높은 CPU 사용률 문제를 해결하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2020년 12월 23일

내 데이터 노드가 내 Elasticsearch 클러스터에서 높은 CPU 사용률을 보여줍니다. 이 문제를 해결하려면 어떻게 해야 합니까?

간략한 설명

CPU 사용률을 유지 관리하여 Amazon ES에 작업을 수행할 수 있는 충분한 리소스가 있는지 확인하는 것이 좋습니다. 높은 CPU 사용률에서 일관되게 수행되는 Elasticsearch 클러스터는 클러스터 성능을 저하시킬 수 있습니다. Elasticsearch 클러스터에 과부하가 걸리면 Amazon ES가 응답을 중지하여 시간 초과 요청이 발생할 수 있습니다.

Elasticsearch 클러스터에서 높은 CPU 사용률을 해결하려면 다음 접근 방식을 고려하세요.

  • 노드 핫 스레드 API를 사용합니다. (자세한 내용은 Elasticsearch 웹 사이트의 노드 핫 스레드 API를 참조하세요.)
  • 쓰기 작업 또는 대량 API 스레드 풀을 확인합니다. (자세한 내용은 Elasticsearch 웹 사이트의 대량 API를 참조하세요.)
  • 검색 스레드 풀을 확인합니다. (자세한 내용은 Elasticsearch 웹 사이트의 스레드 풀을 참조하세요.)
  • Apache Lucene 병합 스레드 풀을 확인합니다. (자세한 내용은 Elasticsearch 웹 사이트의 병합을 참조하세요.)

해결 방법

노드 핫 스레드 API 활용

Elasticsearch 클러스터에 일정한 CPU 스파이크가 있는 경우 노드 핫 스레드 API를 사용합니다. 노드 핫 스레드 API는 작업 관리자 역할을 하며 Elasticsearch 클러스터에서 실행 중인 모든 리소스 집약적 스레드의 분석을 보여줍니다.

다음은 노드 핫 스레드 API의 출력 예입니다.

GET _nodes/hot_threads

100.0% (131ms out of 500ms) cpu usage by thread 
'elasticsearch[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.elasticsearch.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)
참고: 노드 핫 스레드 출력에는 각 노드에 대한 정보가 나열됩니다. 출력 길이는 Elasticsearch 클러스터에서 실행 중인 노드 수에 따라 다릅니다.

또한 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 'elasticsearch[<nodeName>][<thread-name>]

스레드 이름은 어느 Amazon ES 프로세스가 높은 CPU를 소비하는지 나타냅니다.

쓰기 작업 또는 대량 API 스레드 풀 확인

Amazon ES의 429 오류는 Elasticsearch 클러스터가 너무 많은 대량 인덱싱 요청을 처리하고 있음을 나타낼 수 있습니다. 클러스터에 CPU 스파이크가 지속적으로 발생하는 경우 Amazon ES는 대량 인덱싱 요청을 거부합니다.

쓰기 스레드 풀은 대량 API 작업을 포함하는 인덱싱 요청을 처리합니다. Elasticsearch 클러스터가 너무 많은 대량 인덱싱 요청을 처리하고 있는지 확인하려면 Amazon CloudWatch에서 IndexingRate 지표를 확인하세요.

Elasticsearch 클러스터가 너무 많은 대량 인덱싱 요청을 처리하는 경우 다음 접근 방식을 고려하세요.

  • Elasticsearch 클러스터에서 대량 요청 수를 줄입니다.
  • 노드가 더 효율적으로 처리할 수 있도록 각 대량 요청 크기를 줄입니다.
  • Logstash를 사용하여 Elasticsearch 클러스터에 데이터를 푸시하는 경우 일괄 처리 크기 또는 작업자 수를 줄입니다.
  • Elasticsearch 클러스터의 수집 속도가 느려지면 클러스터를 수평 또는 수직으로 확장합니다. 클러스터를 확장하려면 Amazon ES가 들어오는 요청을 적절히 처리할 수 있도록 노드 수와 인스턴스 유형을 늘립니다.

검색 스레드 풀 확인

높은 CPU를 사용하는 검색 스레드 풀은 검색 쿼리가 Elasticsearch 클러스터를 압도하고 있음을 나타냅니다. 클러스터는 단일 장기 실행 쿼리로 인해 압도될 수 있습니다. Elasticsearch 클러스터에서 수행되는 쿼리가 늘어나면 검색 스레드 풀에도 영향을 줄 수 있습니다.

단일 쿼리로 CPU 사용량이 증가하는지 확인하려면 작업 관리 API를 사용합니다. 예를 들어, 다음과 같습니다.

GET _tasks?actions=*search&detailed

작업 관리 API는 Elasticsearch 클러스터에서 실행 중인 모든 활성 검색 쿼리를 가져옵니다. 자세한 내용은 Elasticsearch 웹 사이트의 작업 관리 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": {}
        }
      }
    }
  }
}

설명 필드를 확인하여 실행 중인 특정 쿼리를 식별합니다. running_time_in_nanos 필드는 쿼리가 실행된 시간을 나타냅니다. CPU 사용률을 줄이려면 높은 CPU를 소비하는 검색 쿼리를 취소합니다. 작업 관리 API는 _cancel 호출도 지원합니다.

참고: 특정 작업을 취소하려면 출력에서 작업 ID를 기록해야 합니다. 이 예에서 작업 ID는 “U4M_p_x2Rg6YqLujeInPOw:53506997"입니다.

다음은 작업 관리 POST 호출의 예입니다.

POST _tasks/_cancel/U4M_p_x2Rg6YqLujeInPOw:53506997

작업 관리 POST 호출은 작업을 “취소됨”으로 표시하여 종속 AWS 리소스를 모두 해제합니다. Elasticsearch 클러스터에서 실행되는 쿼리가 여러 개인 경우 POST 호출을 사용하여 한 번에 하나씩 쿼리를 취소합니다. Elasticsearch 클러스터가 정상 상태로 돌아갈 때까지 각 쿼리를 취소합니다. 또한 높은 CPU 스파이크를 방지하기 위해 쿼리 본문에 적절한 시간 초과 값을 설정하는 것이 좋습니다. 자세한 내용은 Elasticsearch 웹 사이트의 요청 본문 검색 파라미터를 참조하세요. 활성 쿼리 수가 감소했는지 확인하려면 Amazon CloudWatch에서 SearchRate 지표를 확인하세요.

참고: Elasticsearch 클러스터에서 모든 활성 검색 쿼리를 동시에 취소하면 클라이언트 애플리케이션 측에서 오류가 발생할 수 있습니다.

Apache Lucene 병합 스레드 풀 확인

Amazon ES는 Apache Lucene을 사용하여 Elasticsearch 클러스터에서 문서를 인덱싱하고 검색합니다. Apache Lucene은 병합 작업을 실행하여 각 샤드에 필요한 유효 세그먼트 수를 줄이고 삭제된 문서를 제거합니다. 이 프로세스는 샤드에 새 세그먼트가 생성될 때마다 실행됩니다.

CPU 사용률에 영향을 미치는 Apache Lucene 병합 스레드 작업이 관찰되면 Elasticsearch 클러스터 인덱스의 refresh_interval 설정을 늘립니다. refresh_interval 설정을 늘리면 클러스터의 세그먼트 생성 속도가 느려집니다.

참고: 인덱스를 UltraWarm 스토리지로 마이그레이션하는 Elasticsearch 클러스터는 CPU 사용률을 높일 수 있습니다. UltraWarm 마이그레이션에는 일반적으로 CPU를 많이 사용하는 강제 병합 API 작업이 포함됩니다.

UltraWarm 마이그레이션을 확인하려면 다음 명령을 사용합니다.

GET _ultrawarm/migration/_status?v