관리 메뉴

피터의 개발이야기

[Elasticsearch] Elasticsearch rejected exception 분석 본문

DevOps/Elasticsearch

[Elasticsearch] Elasticsearch rejected exception 분석

기록하는 백앤드개발자 2022. 11. 16. 00:34
반응형

ㅁ 개요

 ㅇ Elasticsearch(이후 ES) Data 노드에서 볼륨 유휴시간이 갑자기 떨어지고, ES 내부 로그에서 rejected exception을 확인하였다.

 ㅇ rejected exception을 분석하고 ES의 thread pool의 개념을 정리하였다.

 ㅇ 참조 사이트는 여기

 

 

ㅁ ES Data-1의 볼륨 유휴시간 지표

 ㅇ CloudWatch에 Volume 지표를 모니터링 중에 ES Data-1의 유휴시간에 특이사항을 발견하였다.

 

 ㅇ 키바나에서 클러스터 상태를 확인하니 yellow 상태였다.

 ㅇ 기존에 ES가 Volume에 병목이 종종 발생하는 터라 ES Pod 내부의 로그를 확인하였다.

 

 

ㅁ ES 에러로그

{"type": "server", "timestamp": "2022-08-29T01:01:57,596+0000", "level": "ERROR", "component": "o.e.a.b.TransportBulkAction", "cluster.name": "es-cluster", "node.name": "elasticsearch-data-1", "cluster.uuid": "OC2nqF8xSNO-dUhsxk4xsw", "node.id": "LI0Fg97HTpSOFvY6GCGgxQ",
"message": "failed to execute pipeline for a bulk request" ,
"stacktrace": ["org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution of org.elasticsearch.ingest.IngestService$4@205c8c21 on EsThreadPoolExecutor[name = elasticsearch-data-1/write, queue capacity = 2000, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@4c451412[Running, pool size = 2, active threads = 2, queued tasks = 2264, completed tasks = 161066153]]",
"at org.elasticsearch.common.util.concurrent.EsAbortPolicy.rejectedExecution(EsAbortPolicy.java:48) ~[elasticsearch-7.2.0.jar:7.2.0]",
"at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825) ~[?:?]",
"at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355) ~[?:?]",

 ㅇ 로그의 키워드는 "rejected execution" 이다.

 ㅇ 이후 상세 내용을 분석하면 Thread Pool과 관련이 있음을 알 수 있었다.

    * name = elasticsearch-data-1/write,

    * queue capacity = 2000,

    * org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@4c451412

      [Running, pool size = 2, active threads = 2, queued tasks = 2264, completed tasks = 161066153]]

 ㅇ 관련 검색을 하는 과정에서 ES에서는 Thread Pool이라는 것이 존재하였다.

 

 

ㅁ ES Thread Pool

  Elasticsearch는 Thead Pool 클러스터의 각 노드에서 요청을 관리하고 리소스 사용을 최적화 한다. 노드는 스레드 메모리 사용량을 관리하기 위해 여러 스레드 풀을 보유한다. 이러한 풀 중 다수에는 보류 중인 요청을 버려지는 것 대신 보류할 수 있는 파이프라인 대기열을 가지고 있다. 그래서 순간적으로 많은 요청에 대해서 순차적으로 분산하여 처리가 가능하다. 위의 에러는 2개의 스레드 풀에  2000개의 요청을 수용할 수 있는데 그 이상으로 2264개의 요청이 인입되어 발생한 에러인 것이다.

 

 

ㅁ ES Thread Pool의 유형 

ㅇ fixed

Thread Pool은 서비스할 Thread가 없는 보류 중인 요청에 대한 큐(선택적으로 제한함)로 요청을 처리하기 위해 고정된 크기의 Thread를 보유한다. 이 size매개변수는 스레드 수를 제어합니다.

queue_size이를 통해 실행할 스레드가 없는 보류 중인 요청의 대기열 크기를 제어할 수 있습니다 . 기본적으로 -1무제한을 의미하는 것으로 설정됩니다. 요청이 들어오고 대기열이 가득 차면 요청을 중단합니다.

thread_pool:
    write:
        size: 30
        queue_size: 1000

 

 ㅇ fixed_auto_queue_size

고정된 수의 thread, 대상 응답 시간을 유지하기 위해 대기열 크기가 동적으로 변경된다. fixed_auto_queue_size Thread Pool은 서비스할 thread가 없는 보류 중인 요청에 대해 제한된 큐로 요청을 처리하기 위해 고정된 크기의 스레드를 보유한다. fixed thread pool과 유사 하지만 리틀의 법칙에 따라 계산되어 자동 조정된다 . 이러한 계산은 작업이 완료 될 때마다 queue_size가 위 또는 아래로 잠재적으로 50씩 조정된다.

thread_pool:
    search:
        size: 30
        queue_size: 500
        min_queue_size: 10
        max_queue_size: 1000
        auto_queue_frame_size: 2000
        target_response_time: 1s

 size는 스레드 수를 제어합니다.

queue_size를 통해 실행할 스레드가 없는 보류 중인 요청 대기열의 초기 크기를 제어할 수 있다.

min_queue_size 설정은  queue_size가 조정할 수 있는 최소량을 제어한다.

max_queue_size 설정은 queue_size가 조정할 수 있는 최대 양을 제어한다.

auto_queue_frame_size 설정은 대기열이 조정되기 전에 측정이 수행되는 작업의 수를 제어한다.

  단일 작업으로 계산을 과도하게 편향시킬 수 없을 만큼 충분히 커야 한다.

target_response_time 설정은 thread pool이  대기열 작업에 대한 대상 평균 응답 시간을 나타낸다.

 작업이 일상적으로 이 시간보다 많으면 스레드 풀 대기열이 조정되어 작업이 거부된다.

fixed_auto_queue_size 기능은 8.0+ 버전이 더 이상 사용되지 않는다.
참조페이지: https://www.elastic.co/guide/en/elasticsearch/reference/7.4/modules-threadpool.html#types

 

 

ㅁcat API를 통한 모니터링 

GET /_cat/thread_pool?format=json

 ㅇ cat API으로 thead pool을 확인 할 수 있다.

 ㅇ 데이터를 JSON으로 보는 것이 가독성이 있었다.

 ㅇ 결과에서 rejected 카운터를 확인할 수 있다.

 ㅇ cat API의 상세 정보는 Elastic cat thead pool 참조

 

 

ㅁ Nodes Stats API를 통한 모니터링

 ㅇ 키바나 > Dev Tool > console에서 명령어 자동완성을 지원해주고 있다.

 

GET /_nodes/stats

 ㅇ Nodes Stats API를 통해서 확인할 수 있다.

 ㅇ 결과 중 thread_pool의 지표를 통해 Thread Pool의 상태를 확인할 수 있다.

 ㅇ rejected 값은 현재 사태가 아닌 누적 개수이다.

 ㅇ Elastic Nodes stats API의 상세 정보 확인

 

 

ㅁ rejected Exception 해결방법

 때로는 요청이 거부되는 것을 방지하기 위해 대기열의 크기를 늘릴 수 있다. 그래서 실제 리소스에 따라 수정해야 하며 맹목적으로 수정하면 안된다. 실제로 값을 너무 크게 설정하면 오히려 역효과가 날 수도 있습니다. 더 큰 대기열 크기를 설정하면 노드가 대기열을 저장하기 위해 더 많은 메모리를 사용해야 하므로 실제 요청에 응답하고 관리하는 데 상대적으로 적은 메모리가 남게 된다.

게다가 대기열 크기를 늘리면 작업에 대한 응답이 대기열에 보관되는 시간도 늘어난다. 이로 인해 클라이언트 응용 프로그램이 시간 초과 문제에 직면하게 된다.

  요청 수가 급증하여 클라이언트에서 프로세스를 관리할 수 없고 리소스 활용도가 최대치에 도달하지 않는다.

 

 

ㅁ 함께 보면 좋은 사이트

 

 

rejected exception의 의미와 조치 방법

ElasticSearch 운영 | 일정 규모 이상의 ElasticSearch (이하 ES) 클러스터를 운영하다 보면 여러 가지 이슈를 만나게 됩니다. 그중에서도 애먹이게 하는 이슈 중에 하나가 rejected exception의 발생이 아닐까

brunch.co.kr

 

 

 

Elasticsearch thread pool and queue problem, please read this article first - 编程知识

1、 Thread pool related online combat issues problem 1: from Kafka Consumption data import elasticsearch when , Batch bulk Write exception rejected .ES The cluster has four nodes , among : Two nodes node1 and node4 thread pool bulk rejected 30 More th

cdmana.com

 ㅇ Elasticsearch thread pool and queue problem

반응형
Comments