일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 코틀린 코루틴의 정석
- MySQL
- AWS EKS
- Linux
- 정보처리기사 실기 기출문제
- CKA
- Kubernetes
- Spring
- PETERICA
- IntelliJ
- kotlin querydsl
- minikube
- aws
- CKA 기출문제
- AI
- Java
- mysql 튜닝
- Pinpoint
- kotlin
- 정보처리기사 실기
- CloudWatch
- kotlin spring
- Elasticsearch
- 정보처리기사실기 기출문제
- 기록으로 실력을 쌓자
- 공부
- APM
- 티스토리챌린지
- kotlin coroutine
- 오블완
- Today
- Total
피터의 개발이야기
[Elasticsearch] Elasticsearch rejected exception 분석 본문
[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 해결방법
때로는 요청이 거부되는 것을 방지하기 위해 대기열의 크기를 늘릴 수 있다. 그래서 실제 리소스에 따라 수정해야 하며 맹목적으로 수정하면 안된다. 실제로 값을 너무 크게 설정하면 오히려 역효과가 날 수도 있습니다. 더 큰 대기열 크기를 설정하면 노드가 대기열을 저장하기 위해 더 많은 메모리를 사용해야 하므로 실제 요청에 응답하고 관리하는 데 상대적으로 적은 메모리가 남게 된다.
게다가 대기열 크기를 늘리면 작업에 대한 응답이 대기열에 보관되는 시간도 늘어난다. 이로 인해 클라이언트 응용 프로그램이 시간 초과 문제에 직면하게 된다.
요청 수가 급증하여 클라이언트에서 프로세스를 관리할 수 없고 리소스 활용도가 최대치에 도달하지 않는다.
ㅁ 함께 보면 좋은 사이트
ㅇ Elasticsearch thread pool and queue problem
'DevOps > Elasticsearch' 카테고리의 다른 글
[Elasticsearch] 클러스터의 높은 메모리 사용률에 대한 원인 분석 방법 정리 (1) | 2024.07.01 |
---|---|
[Elasticsearch] Data Node 볼륨 병목현상 확인 및 처리 (0) | 2023.01.16 |
[Elasticsearch] EFK 설치(minikube)-2 (2) | 2022.08.15 |
[Elasticsearch] EFK 설치(minikube)-1 (0) | 2022.08.07 |
[Elasticsearch] EFK(Elasticsearch, Fluentd, kibana)란 (0) | 2022.08.02 |