ElasticSearch 대용량 처리를 위한 시스템 최적화.
노드의 실행환경과 JVM옵션
ElasticSearch 6버전 이상부터는 JAVA 1.8 이상을 사용하도록 강제하고 있다.
ElasticSearch에 적용된 JVM옵션.
ElasticSearch도 JVM위에서 실행되는 자바 어플리케이션이기 때문에 실행시 적용될 JVM옵션들을 튜닝해서 기본 설정으로 제공한다. 그리고, 분산 시스템 특성장 Scale-up / Scale-Out 이 빈번하며, 장애복구시 데이터 리밸런싱에 의해 많은 메모리를 사용하기 때문에 전체적인 성능 향상을 위해 JVM튜닝은 필수라 할수있다.
JVM튜닝값은 ElasticSearch에서 기본적으로 제공한다.
수년동안 개발되어 오면서 경험을 바탕으로 분산시스템에 적합한 JVM 옵션이 대부분 최적화 되어서 제공되므로, 기본값에서 크게 수정할 필요는 없다.
오히려, 기본값으로 제공되는 JVM옵션값을 수정하는것은 권장하지 않으며, 기본값을 사용하기를 권고한다.
그러나, 반드시 변경해야 하는 값도 있다.
기본적으로 JVM Heap Size가 기본적으로 1GB로 설정되어 있는데, 실제 운영환경에서는 반드시 거 큰 크기로 변경해야 한다.
(Default Heap Size가 1GB인 이유는 ElasticSearch를 실행하는데 필요한 최소한의 힙크기가 1GB이기 때문이다. )
---
그렇다면, 적당한 Heap의 Size는 얼마일까?
너무 Heap Size가 작으면 OOM(Out od Memory)가 발생할 수 있고, 너무 크면 STW(Stop The World)를 발생시킬 수도 있다.
HeapSize는 아래의 옵션으로 설정
Xms(최소 힙 크기) / Xmx(최대 힙 크기)
JVM이 실행될때, Xms크기로 동작하다가 Heap이 부족하다고 판단되면, Xmx크기만큼 Heap사이즈를 확장하는데, 늘어나면서 성능의 저하가 발생할 수 있다.
그래서, 실제 ElasticSearch서버를 구성할때, 미리 메모리를 많이 활용한다는 점을 인지하고 Xms=Xmx를 같게 설정하는것이 운영상 유리할 수 있다.
Xms(최소 힙 크기) = 4G
Xmx(최대 힙 크기) = 4G
권장하는 Heap Size는 최대 32GB 이하를 권장한다.
이유는?
Hot-Spot JVM의 Object Pointer 정책 때문이다.
사실 모든 자바 어플리케이션에서는 Object Pointer 정책이 모두 동일하게 적용되기 때문에, ElasticSearch 뿐만 아니라 모든 자바 어플리케이션에서 32GB 이하를 권고한다.
"Object Pointer"는 간단히 말하면 객체의 메모리 번지를 표현하는 주소값이다. 이 주소값을 32bit / 64bit JVM이 모두 32bit 주소값을 가지고 동작하기 때문이다. 따라서 메모리 낭비의 단점을 피하기 위해, 32GB이하로만 설정하기를 권고한다. |
그러나 32GB를 넘어가면 안된다는것은 아니다.
다만 일반 OOP를 사용하면 포인터를 표현하는데 64비트를 사용하기 때문에 여러 이점들이 사라지기 때문에 권장을 하는것이지 불가능한것은 아니다.
---
분산환경에서의 메모리 스와핑(Swapping)
메모리 스와핑(Swap) - 효율적인 메모리 관리를 위해 Swap을 사용하는데, 디스크의 일정 영역을 스왑 영역으로 지정하여 메모리를 disk로 Swap 하여 사용한다.
Swap-in/Out 시에 시스템 성능이 다소 떨어질 수 있기에, 시스템 리소스가 부족하지 않다면 가급적 스와핑이 일어나지 않도록 설정하는 것이 좋다.
ElasticSearch 특성상 Swap 작업으로 인해 GC가 비정상적으로 수분동안 지속되거나 응답이 느리질 수도 있으며, 클러스터 연결이 불안정하여 연결이 끊어짐이 반복되는 현상이 발생할 수도 있다.
따라서, 가급적 Swap을 Off하여 사용하는 편이 운영상 여러모로 유리하다
# sudo swap off -a # vi /etc/fstab (swap영역 off로 파일수정) |
---
시스템 튜닝 포인트
Max Open File Limit 설정
엘라스틱서치 노드는 많은 수의 Socket을 사용해 클라이언트와의 통신을 수행한다.
더불어 내부에 존재하는 루씬이 index를 효율적으로 관리하기 위해 많은 수의 파일을 사용한다.
그러다 보니 엘라스틱서치가 운영되는 시스템에서는 일반적인 시스템보다 더 많은 수의 파일을 생성할 수 있어야 한다.
# vi /etc/security/limits.conf
irteam softnofile 81920 irteam hardnofile 81920 |
추가로, elasticsearch의 파일 디스크립터를 충분한 값을 설정하고 있는지 확인해보자.
_nodes API를 이용하면 노드의 정보를 확인할 수 있다.
GET _nodes/stats/process?filter_path=**.max_file_descriptors { … "open_file_descriptors": 155, //현재 열려있는 파일 디스크립터 수 "max_file_descriptors": 10240, // 최대 사용가능한 파일 디스크립터 수 … } |
해당 파일 디스크립터의 수를 늘리다가 오류가 난다면?
커널에서도 내부적으로 설정 가능한 파일 개수가 있는데, 이를 늘려줘야 한다.
# cat /proc/sys/fs/file-max
# sysctlfs.file-max
fs.file-max = 1609581
Max Thread Limit 설정
ElasticSearch는 빠른 처리를 위해 대량의 Thread를 생성해서 처리한다.
이를 위해 Thread Pool을 도입해서 활용한다.
Max Thread수 역시 사용자가 직접 설정도 가능하지만, ElasticSearch가 CPU 수를 기반으로 최적의 Thread 수를 자동 계산하기 때문에, ElasticSearch에게 위임하는 편이 좋다.
책 - 엘라스틱서치 실무 가이드(위키북스)