** 이 포스트에서 수정하는 설정값 들은 elastic에서는 공식적으로 수정하지 말도록 권장하고 있습니다. 꼭 필요한 경우에만 충분한 테스트를 거쳐서 적용하시기 바랍니다. **
ElasticSearch
에 대량의 데이터를 bulk insert
하는 과정에서
- 예상했던 값보다 indexing rate가 낮은 경우
- 데이터를 밀어넣는 클라이언트에 EsRejectedExecutionException 이 발생 하는 경우
여러가지 튜닝 포인트가 있겠지만 그중에서도 Thread pool
은 매우 중요한 값인것 같습니다.
공식 홈페이지의 문서를 살펴보면
노드 안에서 효과적으로 쓰레드 메모리를 소비하기 위해서 노드는 여러개의 쓰레드풀을 가지고 있다. 많은 쓰레드 풀들은 큐들을 가지고 있고 그 큐들로 인해 넘치는 요청들이 버려지는 대신 큐에 담겨질 수 있다.
라고 소개되고 있습니다.
여러가지 중요한 Thread pool
들이 소개되어 있지만 개인적으로 특히 더 중요하다고 생각되는 Thread
는 아래 세개 입니다.
** index ** : index/delete 연산 용. type은 fixed
이고 size는 가용한 프로세서갯수와 동일 합니다. queue_size는 default 200
** search ** : count/search/suggest 연산 용. type은 fixed
이고 size는 ((가용한 프로세서갯수 * 3) / 2) + 1 입니다. queue_size는 default 1000
** bulk ** : bulk 연산 용. size는 가용한 프로세서갯수와 동일 합니다. queue_size는 default 50
여기서 주의 깊게 봐야 할 설정이 바로 queue_size
입니다.
쓰레드풀 자체의 사이즈는 위에서 설명 한것과 같이 가용한 프로세서의 갯수에 의존성이 있기 때문에 튜닝하기 쉽지 않고, queue_size
를 늘려줌으로써 EsRejectedExcutionException
이 나는것을 방지 할 수 있습니다.
elasticsearch.yml
에 다음과같이 설정해 놓고 사용할 수 있습니다만
1 | threadpool.index.type: fixed |
운영중인 클러스터에 elasticsearch.yml
을 변경하고 순차적으로 재시작 하는 작업은 부담이 가는것은 사실 입니다.
** 좋은소식은 ThreadPool 설정은 dynamic setting 이므로 운영중인 클러스터를 재시작 할 필요 없이 api를 날려서 적용 시킬수 있습니다 **
먼저 내 클러스터의 쓰레드풀 설정을 살펴봅시다.
1 | #내 쓰레드풀에 대한 개요 |
위 명령어는 sense
기준이고 curl
로 확인하는 경우 아래와 같이 날려보면 됩니다.
1 | curl -XGET 'http://myclusterip:port/_nodes/thread_pool' |
이제 다시 맨 처음의 주제로 돌아와서 내 생각보다 bulk insert 되는 속도가 느린것 같거나 자꾸 익셉션이 발생하는 경우
bulk queue가 너무 적은것은 아닌가 의심해 볼 수 있습니다.
쓰레드풀의 상태를 봤을 때 rejected
된 건수가 많이 보이면 bulk queue
를 늘려보는게 좋습니다.
벌크 인서트할때도 그렇고, 검색할때도 자꾸 밀리는것 같은 느낌이 들어서 다음과 같이 설정을 변경해 봤습니다.
(기존 설정은 default값인 bulk.queue_size는 50, search.queue_size는 1000 이었습니다.)
1 | PUT _cluster/settings |
좀 더 지켜봐야겠지만 위와 같이 변경 하고 나서 클라이언트에서 EsRejectedExecutionException
도 더이상 보이지 않고 클러스터가 훨씬 안정적이게 됐습니다.