우리는 AWS Elastic Container Service(ECS) Fargate에서 여러 Java 서비스(Corretto JDK21)를 실행합니다. 각 서비스에는 자체 컨테이너가 있으며 각 프로세스에 대해 비용을 지불하는 가능한 모든 리소스를 사용하려고 합니다. 하지만 이 단계는 EC2 및 기타 클라우드에 적용될 수 있습니다.
서비스는 일괄 작업을 실행하고 있으며 대기 시간은 중요하지 않습니다. 우리는 병렬 GC(-XX: UseParallelGC)를 사용합니다. 우리가 하는 일이라면 G1이 더 나을지도 모르지만, 그건 따로 연구하고 포스팅하는 주제입니다.
사용 가능한 모든 메모리를 사용하기 위해 MaxHeapSize는 컨테이너 메모리 크기보다 약간 낮습니다. 그러나 얼마 후 우리는 두 가지 문제를 발견했습니다. 때로는 컨테이너가 너무 많은 메모리를 사용하여 컨테이너가 종료되고 때로는 OutOfMemoryError 예외가 발생하는 경우도 있었습니다. 첫 번째 문제를 해결하기 위해 컨테이너 메모리 크기와 MaxHeapSize 사이의 간격을 늘렸고 두 번째 문제에 대해서는 빠른 수정으로 컨테이너 메모리를 늘린 후 힙 덤프를 살펴보기 시작했습니다.
힙 덤프는 흥미로운 세부 정보를 보여 주었고 실제 힙 크기는 MaxHeapSize보다 작았으며 Young Generation 힙은 Old Generation에 비해 작았습니다.
인터넷에서 검색해도 우리 사례에 맞게 JVM 매개변수를 조정하는 방법에 대한 좋은 가이드를 찾는 데 도움이 되지 않았고, 힙 및 매개변수 설명에 대한 몇 가지 높은 수준의 세부정보만 찾았습니다. 저는 제가 수행한 단계를 설명하기 위해 이 게시물을 작성하기로 결정했습니다.
첫 번째 단계는 다음과 같습니다.
Young:Old 세대의 기본 비율은 1:2이며, Young 세대의 일부만 동시에 GC를 수행하는 데 사용됩니다. 그리고 시작 후 JVM은 예상대로 모든 메모리를 할당했지만 얼마 후 Young Generation 힙 크기가 거의 수 메가바이트로 줄어들기 시작했습니다. 그래서 얼마 후 우리는 사용 가능한 메모리의 ⅔만을 사용했습니다.
몇 가지 조사 끝에 적응형 정책(-XX:-UseAdaptiveSizePolicy)을 비활성화하는 매개 변수를 찾았고 도움이 되었습니다. 힙 감소가 멈추고 가비지 수집 간격이 몇 배 이상 늘어났습니다. GC에 소요되는 시간도 늘어났지만 그다지 많지는 않습니다.
다음 단계는 컨테이너 메모리 크기 간의 최적의 간격을 찾는 것이었습니다. 기본적으로 초기RAMPercentage=100이더라도 JDK에서는 메모리만 할당하고 사용하지 않으므로 매핑되지 않습니다. Linux에서는 실제 메모리보다 더 많은 가상 메모리를 할당할 수 있습니다. 그리고 나중에 메모리가 실제로 매핑되면(JDK가 여기에 기록할 때) 컨테이너가 실패합니다. -XX: AlwaysPreTouch는 이 동작을 변경합니다. 불행하게도 일부 메모리는 아직 매핑되지 않았지만 OOM 종료가 훨씬 빠르게 발생합니다. 여러 번 시도한 끝에 8GB 이상의 메모리가 있는 컨테이너의 경우 다음 공식 컨테이너 메모리 크기 - 1024MB로 끝났습니다. 예를 들어, 8192 컨테이너 메모리 크기의 경우 -XX:MaxHeapSize=7168m.
를 사용합니다.추가 최적화를 위해 -XX:NewRatio를 변경하여 Young Generation 크기를 줄이고 GC 시간을 줄이는 것을 고려하고 있습니다. 그러나 이는 응용 프로그램의 개체 수명에 따라 달라집니다.
앞서 언급했듯이 매개변수(내가 찾은 최고는 vm-options-explorer)와 튜닝 단계에 대한 자세한 설명이 포함된 좋은 가이드를 찾지 못했습니다. 여러분의 지식과 결과를 공유해 주시면 좋겠습니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3