Home ElasticSearch JVM Options 설정과 살펴볼 점
Post
Cancel

ElasticSearch JVM Options 설정과 살펴볼 점

1. 글을 작성하게 된 계기


ElasticSearch를 학습하며 JVM 옵션에 대해 학습하게 되었고, 알게된 내용을 정리하기 위해 글을 작성하게 되었습니다.





1. ElasticSearch의 JVM 설정 파일


ElasticSearch는 자바로 개발된 애플리케이션으로,.성능과 안정성에 있어서 JVM 관련 옵션 설정이 매우 중요합니다. JVM의 설정은 ElasticSearch의 전반적인 성능과 메모리 관리 방식, 특히 GC(Garbage Collection) 방식 등과 깊은 관련이 있습니다.

이에 대한 상세한 내용은 Set JVM options, Elasticsearch Guide 를 참조해주세요.



이러한 JVM 관련 설정을 관리하는 주요 파일이 바로 jvm.options 파일입니다. 이 파일에서는 ElasticSearch가 사용하는 JVM의 힙 메모리 크기, GC(가비지 컬렉션) 방식 등 다양한 설정을 지정할 수 있으며, JVM 설정은 곧 ElasticSearch의 성능과 직결됩니다. 따라서 설정을 무조건 기본값으로만 사용하는 것이 아니라, 서비스의 사용 환경에 맞춰 적절히 조정하는 것이 필수적입니다.

1-1. heap size 설정

힙 메모리(heap memory)는 ElasticSearch가 데이터를 저장하고 처리하기 위해 사용하는 주요 메모리 영역입니다. ElasticSearch의 JVM 옵션 중에서도 특히 중요한 부분이 힙 메모리의 설정이며, 주로 다음과 같은 방식으로 지정합니다.

1
2
-Xms4g
-Xmx4g

Xms는 JVM이 시작될 때 초기 힙 메모리 크기를 나타냅니다. Xmx는 최대 힙 메모리 크기를 나타냅니다. 위 설정은 힙 메모리를 최소(-Xms)와 최대(-Xmx)를 같은 값으로 설정하라는 권장 사항을 반영한 예입니다. 예를 들어 4GB로 설정하는 경우 -Xms4g와 -Xmx4g로 동일하게 설정합니다. 두 값을 같게 설정하면 JVM은 메모리 사이즈를 확장하거나 축소하는 작업이 필요 없어지고, 성능의 변동성을 최소화할 수 있습니다.

만약 힙 메모리를 다르게 설정하면 JVM이 애플리케이션의 필요에 따라 힙 메모리를 확장하거나 축소할 수 있지만, 이는 메모리 확보 및 축소에 따른 오버헤드를 야기할 수 있습니다. 특히 메모리를 확장하거나 축소할 때 발생하는 성능 저하를 방지하기 위해 초기와 최대 힙 크기를 동일하게 설정하는 것이 성능상 이점이 있습니다.

ElasticSearch에서는 보통 전체 시스템 메모리의 50% 이하를 JVM 힙 메모리로 설정할 것을 권장합니다. 예를 들어 서버가 64GB의 메모리를 가진 경우 힙 크기를 32GB를 넘지 않도록 권장하고 있습니다. 이 권장은 JVM이 포인터 압축(OOP: Ordinary Object Pointer, Compressed OOP)을 효율적으로 사용하여 성능을 향상시킬 수 있기 때문입니다.

Set Xms and Xmx to no more than 50% of your total memory. Elasticsearch requires memory for purposes other than the JVM heap.





1-2. Compressed OOP 설정

포인터 압축(OOP, Ordinary Object Pointer)과 관련된 설정은 ElasticSearch의 JVM 성능에 중요한 영향을 끼치는 요소입니다. JVM에서 객체에 접근할 때 사용하는 주소 값은 기본적으로 시스템 아키텍처에 따라 달라지며 32비트 또는 64비트 주소 공간을 사용합니다.

An “oop”, or ordinary object pointer in Java Hotspot parlance, is a managed pointer to an object. An oop is normally the same size as a native machine pointer, which means 64 bits on an LP64 system.



Compressed OOP를 사용하면 실제 메모리를 32GB까지 사용하는 경우에도 효율적인 주소 표현이 가능합니다. 즉, JVM이 64비트 시스템에서 32GB 이하의 메모리를 사용하는 경우 포인터 압축이 기본적으로 활성화되어 메모리 사용량이 줄어들고 성능이 향상됩니다. 만약 힙 메모리를 32GB를 초과하여 할당하면 포인터 압축 기능을 사용할 수 없어지고 Native OOP가 사용되며, 메모리 소비가 더 커지고 성능에도 영향을 줄 수 있습니다. 따라서 ElasticSearch의 JVM 힙 메모리 설정 시 최대 32GB를 넘지 않도록 주의해야 합니다. 이를 넘을 경우 포인터 압축의 이점을 얻을 수 없게 되어, 성능과 메모리 효율성에 부정적 영향을 미치게 됩니다.

  • 32비트 시스템의 JVM: 최대 4GB의 주소 공간을 사용합니다. 메모리를 효율적으로 사용할 수는 있지만, 최대 메모리 제한이 존재합니다.
  • 64비트 JVM에서의 포인터 압축(Compressed OOP): 이론적으로는 16엑사바이트(16EB)까지 주소 공간을 사용할 수 있지만, JVM은 메모리 성능을 위해 포인터 압축을 사용하여 32비트 포인터 기반으로 제한된 주소공간(4GB)을 사용하는 방식으로 성능을 높입니다.





1-3. GC 설정

JVM은 주기적으로 메모리 내에서 더 이상 사용하지 않는 객체를 수거하고 메모리를 재활용하는데, 이때 JVM의 성능과 응답 시간에 영향을 줄 수 있습니다. ElasticSearch는 주로 두 가지의 GC 방식을 지원합니다.

1-3-1. CMS

CMS 방식은 오래된 Old 영역의 메모리에서 불필요한 데이터를 제거하는 방식을 사용합니다. 메모리 사용량이 일정 임계치를 초과하면 Old GC가 발생하며, 기본 임계값은 보통 힙 메모리 사용량의 75%입니다. 즉, 힙 메모리 사용량이 설정된 최대치의 75%에 도달하면 Old GC가 수행됩니다. CMS 방식에서는 old GC를 수행할 때 잠시 애플리케이션을 멈추는(stop-the-world) 현상이 발생합니다. 따라서 이 방식을 사용할 때는 힙 메모리 크기와 old GC가 수행되는 임계값을 신중하게 설정해야 합니다.

1-3-2. G1 GC

최근의 JVM에서는 G1(Garbage First) GC 방식이 기본값으로 권장됩니다. G1 GC는 CMS보다 더 세밀하게 메모리를 관리하고, stop-the-world 시간이 짧으며 예측 가능한 지연 시간과 더 나은 성능을 제공합니다. 가능하다면, 특히 대규모 시스템에서는 G1 GC를 권장하며 반드시 사전에 테스트 후 적용해야 합니다.







2. JVM 설정 시 추가 고려 사항


2-1. GC Logging 설정과 분석

ElasticSearch 운영 시 JVM의 Garbage Collection(GC) 성능은 전체 시스템 성능에 결정적 영향을 줍니다. 따라서 GC 로그를 통해 JVM의 동작 상태를 모니터링하고 분석하는 과정이 필수적입니다.

GC 로깅은 JVM이 GC를 수행할 때마다 관련 정보를 기록하도록 설정하여, 성능 병목 현상이나 장애 원인을 빠르게 진단할 수 있게 합니다. 일반적으로 사용하는 옵션은 다음과 같습니다.

1
-Xlog:gc*:file=/var/log/elasticsearch/gc.log:time,uptime,level,tags:filecount=32,filesize=64m



이 옵션은 GC 관련 로그를 /var/log/elasticsearch/gc.log 경로에 저장하고, 최대 파일 개수 32개, 파일당 64MB 크기로 로그 로테이션을 수행합니다. 로그 파일에는 GC가 발생한 시간, 가동 시간, 레벨, 태그 등의 상세 정보가 기록됩니다.

GC 로그는 GCeasy, GCViewer, VisualVM, Java Mission Control(JMC) 등 다양한 GC 로그 분석 도구를 통해 JVM의 메모리 소비량, GC 주기, stop-the-world 시간, 메모리 누수 현상 등을 분석할 수 있습니다. 이를 통해 시스템 장애나 성능 저하의 원인을 조기에 식별하고 해결할 수 있습니다.





2-2. Stack 영역과 Thread 설정

스택(Stack) 영역은 JVM에서 각각의 스레드가 독립적으로 사용하는 메모리 공간으로, 메서드 호출 시 사용되는 지역 변수, 임시 데이터, 매개변수 등이 저장되는 영역입니다. ElasticSearch는 내부적으로 다수의 스레드를 이용하여 클러스터 관리, 인덱싱 작업, 검색 처리 등을 수행하며, 스레드의 개수가 많아지면 그만큼 JVM의 스택 메모리 사용량도 증가합니다.

ElasticSearch에서 JVM의 스택 메모리 크기를 설정할 때는 보통 다음과 같이 설정합니다. 이 설정은 스레드별로 스택 크기를 1MB로 제한합니다. 스택 크기를 너무 크게 설정하면, 많은 수의 스레드를 생성할 때 전체 메모리 사용량이 증가하게 되어 시스템에 부정적 영향을 미칠 수 있습니다. 반대로 너무 작게 설정하면 복잡한 작업 수행 시 StackOverflowError가 발생할 수 있으므로, 서비스 운영 환경에 따라 적절히 조정하는 것이 중요합니다.

1
-Xss1m





2-3. Metaspace 영역 설정

메타스페이스(Metaspace)는 JVM이 클래스 메타데이터(Class Metadata)를 저장하는 공간으로, Java 8 이후부터 사용된 영역입니다. 이전 버전의 JVM(Java 7 이하)에서는 PermGen(Permanent Generation)이라 불리는 영역을 사용하였지만, Java 8부터는 Metaspace로 변경되었습니다.

ElasticSearch의 경우 사용자 정의 플러그인(plugin)을 설치하거나 스크립트 사용이 많아질 경우, 클래스 메타데이터가 증가하면서 메타스페이스 영역의 사용량도 증가할 수 있습니다. 따라서 서비스의 규모가 크거나 플러그인을 다수 사용하는 환경에서는 메타스페이스 최대 크기를 명시적으로 설정하는 것이 좋습니다.

다음과 같은 설정을 통해 메타스페이스 크기를 지정할 수 있습니다. 이 설정은 메타스페이스의 최대 크기를 512MB로 제한합니다. 메타스페이스가 부족할 경우 클래스 로딩 실패나 OutOfMemoryError와 같은 문제가 발생할 수 있으므로, 시스템에 맞는 최적의 값을 설정하고 모니터링하는 것이 필요합니다.

1
-XX:MaxMetaspaceSize=512m







3. Garbage Collection(GC) 고급 설정 및 성능 튜닝


ElasticSearch에서 JVM 성능 최적화의 핵심은 GC 방식의 설정과 튜닝에 있습니다. 기본적으로 ElasticSearch는 CMS(Concurrent Mark Sweep)와 G1 GC(Garbage-First GC) 두 가지 GC 방식을 주로 사용합니다. 서비스 환경과 데이터 특성에 따라 적절한 GC 방식을 선택하고 세부적으로 튜닝하는 것이 중요합니다.



3-1. CMS GC 세부 튜닝

CMS GC는 Old 영역에서 메모리를 수거하는 방식으로, Old 영역의 메모리 점유율이 특정 임계값을 넘으면 GC를 수행합니다. 이 임계값을 조정하는 설정은 다음과 같습니다.

shell 복사 편집 -XX:CMSInitiatingOccupancyFraction=75 이 옵션은 힙 메모리의 Old 영역 사용량이 75%에 도달하면 GC가 수행되도록 설정합니다. 이 값을 낮게 설정하면 GC가 자주 발생하여 오히려 성능에 부정적일 수 있고, 너무 높게 설정하면 GC가 늦게 수행되어 장기적으로 서비스가 느려질 가능성이 있습니다. 따라서 ElasticSearch의 데이터 처리 특성 및 부하를 고려하여 적절한 값을 설정해야 합니다.



3-2. G1 GC 세부 튜닝

G1 GC(Garbage First GC)는 최근 JVM에서 권장되는 방식으로, 메모리를 세부적인 영역(Region)으로 나누어 관리하여 더 효율적인 가비지 컬렉션을 수행합니다. G1 GC에서는 다음과 같은 설정으로 튜닝할 수 있습니다.

1
2
-XX:MaxGCPauseMillis=200
-XX:G1HeapRegionSize=16m



MaxGCPauseMillis는 GC 수행 시 최대 허용되는 Stop-The-World 시간을 밀리초 단위로 설정합니다. 예시로 설정한 200ms는 GC로 인해 서비스가 멈추는 시간을 최대 200ms 이내로 제한합니다. 이 값을 너무 낮게 설정하면 GC가 너무 자주 발생하여 전체적인 처리량이 저하될 수 있습니다.

G1HeapRegionSize는 G1 GC에서 사용하는 개별 Region의 크기를 설정하는 값입니다. 일반적으로 8MB 또는 16MB를 추천하며, 이 값을 너무 작게 설정하면 메모리 관리 오버헤드가 증가할 수 있습니다.







4. JVM 설정 시 추가로 고려할 사항


4-1. JVM GC 로그 활성화 및 분석 도구 활용

ElasticSearch의 성능 문제를 진단하고 성능 튜닝 시 GC 로그 분석은 필수입니다. 다음과 같은 옵션으로 GC 로깅을 활성화하고 로테이션 관리를 설정할 수 있습니다. 아래 설정을 통해 GC 로그가 자동으로 로테이션되어 저장되며, VisualVM, GCeasy, Java Mission Control(JMC)과 같은 도구를 활용하여 로그를 상세히 분석하여 성능 문제나 메모리 누수를 정확하게 진단할 수 있습니다.

1
-Xlog:gc*:file=/var/log/elasticsearch/gc.log:time,uptime,level,tags:filecount=32,filesize=64m



4-2. 환경별 JVM 옵션 분리 관리

ElasticSearch는 config/jvm.options.d 디렉토리를 통해 JVM 옵션을 환경별로 별도 관리할 수 있습니다. 예를 들어, 개발(dev), 테스트(test), 운영(prod) 환경별로 설정 파일을 분리하여 관리하는 방식입니다. 각 환경마다 GC 옵션, 힙 메모리 크기, 메타스페이스 크기 등을 다르게 지정하여 관리의 용이성과 안전성을 확보할 수 있습니다.

1
2
3
config/jvm.options.d/dev.options
config/jvm.options.d/test.options
config/jvm.options.d/prod.options

This post is licensed under CC BY 4.0 by the author.

역색인은 무엇이고 왜 빠를까?

JPA를 사용할 때, 하나의 서버, 여러대의 데이터베이스는 어떻게 처리할까?