ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java Native Memory Leak 원인을 찾아서 - 토스(박동호)
    세미나, 영상 요약정리 2022. 7. 1. 00:01
    728x90

    https://www.youtube.com/watch?v=w4fWgLgop5U 

    토스 페이먼츠의 서버 개발을 맡고 있는 박동호님의 영상을 보고 요약한 내용입니다.

     

    JIT 컴파일러와 JVM GC에 대한 이야기가 조금씩 나오기 때문에 최소한 다음 글의 JIT 컴파일러 부분만 보시더라도 읽는데 도움이 되실 것 같습니다.

     

    https://junuuu.tistory.com/126?category=989459 

     

    [Java] JVM(Java Virtual Machine)의 모든것을 알아보자

    JVM이란? Java Virtual Machine의 약자로 자바 가상 머신이라고 불립니다. 자바와 운영체제 사이에서 중계자 역할을 합니다. 따라서 자바가 운영체제 종류에 영향받지 않고 돌아갈 수 있도록 합니다. =(

    junuuu.tistory.com

     

    오류의 시작

    Slcak 으로부터온 OOM Killed 메시지

    시스템에서 오류 가능성이 있어 보이는 항목들을 모니터링하며 슬렉으로 메시지 연동이 되어있습니다.

     

    OOM Killer란?

    OOM Killer는 Linux OS에서 특정 프로세스가 과도하게 메모리를 사용하여 메모리 여유가 없을 때 전체 시스템 안정성을 위해 희생할 작업을 선택합니다.

     

    보통 Java로 서비스하는 서버에는 Java Process가 메모리를 많이 사용하기 때문에 OOM Killer가 Java Process를 죽입니다.

     

    문제의 서버 상황

    Java 11버전을 사용했으며 도커의 메모리는 4GB입니다.

    OOM Killer가 Java를 죽일 때 Java 프로세스가 4GB의 메모리를 사용했습니다.

    Java의 Max Heap Size는 1.5GB이기 때문에 Heap Size를 제외하면 2.5GB가 사용되었을 텐데 이 알 수 없는 메모리 사용량은 이상한 수치입니다.

     

    실제 사용량 측정

    Java를 구동할 때 NativeMemoryTrcking옵션을 주면 jcmd 명령어를 통해 자바 가상 머신의 실제 메모리를 측정할 수 있습니다.

     

    Heap은 1.5GB

    클래스공간은 190MB

    Thread, Code, GC 등 자바 전체 가상 머신의 메모리 사용량은 2GB

     

    이때 프로세스가 메로리를 할당하여 쓰고있는 RES수치는 2GB보다 큰 3.1GB였습니다.

    즉, 1.1GB의 오차가있으며 이 오차가 2GB 이상 발생했을 때 OOM이 발생한 것입니다.

     

    이 정체를 알 수 없는 오차가 Native Memory Leak일 가능성이 매우 높습니다.

     

    Native Memory Leak 원인 찾기(예상 범위 찾기)

    1. JNI & JNA

    C로 구현한 모듈을 Java에서 직접 호출하는 기능으로 C 구현체에서 Memory Leak이 발생할 경우 Java 가상 머신에서는 이를 인지할 수 없음

     

    하지만 문제의 서버는 JNI와 JNA를 쓰는 부분이 없음

     

    2. JDK 1.4부터 지원하는 DirectBuffer

    DirectBuffer로 메모리를 할당하면 GC로 관리되지 않는 네이티브 메모리가 할당됨

     

    하지만 NativeMemoryTracking 옵션을 통해 확인할 수 있으며 문제의 서버에서 사용량은 매우 적었음

     

    3. JavaAgent 기반의 APM 툴

    Java Agent란?

    JVM 에서 동작하는 Java 어플리케이션으로 JVM의 다양한 이벤트를 전달받거나 정보 질의, 바이트코드 제어 등을 특정 API를 통하여 수행할 수 있습니다.

    APM이란?

    Application Performance Management의 약자로 APM은 서버의 성능을 관리하는 툴입니다.

     

    조사 결과 특별한 문제가 없었음

     

    4. Linux OS의 Process 레벨 탐색

     

    4-1 메모리 dump

    프로세스 메모리를 dump하고 dump 된 파일 내의 문자열을 조회하려고 했습니다.

    메모리 dump란 컴퓨터 프로그램이 특정 시점에 작업 중이던 메모리 상태를 기록한 것입니다.

     

    하지만 힌트가 될만한 내용은 보이지 않음

     

    4-2 메모리 profile 툴을 적용

    메모리 프로파일러는 앱의 메모리 사용 현황을 실시간 그래프로 보여주며, 메모리 프로파일러를 사용하여 힙 덤프를 캡처하고 가비지 컬렉션을 강제 실행하고 메모리 할당을 추적할 수 있습니다.

     

    리눅스에서는 기본적으로 malloc을 사용하는데 이를 jemalloc으로 변경하면 jemalloc에서 제공하는 프로파일 툴을 사용할 수 있습니다.

    메모리 할당 상황

     

    이때 C2 Compiler에서 1.9기가를 사용하고 있었습니다.

     

    openjdk의 bug tracking system을 살펴보니 C2 Complier 메모리 릭 이슈가 리포팅되어있었습니다.

     

    C2 Compiler란?

    .java -> .class -> 기계어로 변환하는 과정에서 javac 컴파일러와 , JIT 컴파일러가 사용되는데 이때 JIT 컴파일러는 5단계로 나뉩니다.

     

    이때 5단계에 해당하는 Level 4 컴파일러가 C2 컴파일러입니다.

     

    C1 컴파일러는 클라이언트 컴파일러이며 C2 컴파일러는 서버 컴파일러입니다.

     

    클라이언트에서는 앱을 띄우면 빠르게 구동 시간이 줄이는 것이 포인트입니다.

     

    서버에서는 구동 시간은 느리지만 JIT 컴파일러의 최적화를 이용하여 빠른 연산을 수행하는 것이 포인트입니다.

     

    즉, 한번 구동하면 오랫동안 많은 연산을 하기 때문에 서버들은 C2 컴파일러를 사용합니다.

     

    문제 해결 시작

    C2 컴파일러가 진짜 문제인지 확인하기 위해서 Tiered Stop at  Level이라는 옵션을 주어 JIT Complier의 Level을 선택할 수 있습니다.

     

    C2 컴파일 대신에 C1 컴파일을 적용해보니 문제가 발생하지 않았습니다.

     

    하지만 CPU 사용률이 40% -> 70%으로 증가했습니다. (최적화가 되지 않기 때문!)

     

    문제는 없애고 CPU 사용률만 낮추고 싶어

    JDK 버전을 11 최신 버전으로 JDK 17 최신 버전으로 변경해보았지만 문제가 해결되진 않았습니다.

     

    이때 OpenJDK의 Graal Compiler라는 것을 알게 되었습니다.

     

    이 기능을 사용하려면 Java 가상 머신에서 실험적인 기능을 쓰겠다면 옵션을 넣어주어야 하며 JVM CI Compier 옵션을 주어야 합니다.

     

    실험적인 것이 마음에 걸렸지만 HA를 확보하고 있고 무중단 배포 환경이 구축되어 있었습니다.

     

    HA란?

    고가용성(HA)은 단일 사이트에서 인프라 또는 애플리케이션을 보호하여 지속적인 운영을 보장합니다. 일반적으로 이중 액세스 경로 및 구성 요소 복구를 통해 컴퓨팅 스택의 단일 장애 지점을 줄이는 것을 목표로 합니다. 환경에 고가용성 개념을 포함하면 서비스에 복구 능력이 기본으로 설정되므로 자체적으로 복구할 수 있습니다.

     

    문제가 발생하여도 영향도를 최소로 하며 빠른 롤백이 가능했기 때문에 적용해보기

    CPU 사용률을 70% -> 40%으로 줄어듬

     

     

    마지막 한마디

    선택한 방법이 최선이 아닐 수 있지만 문제 원인의 실마리를 찾아과는 과정이 중요하다

    이 영상으로 인해 비슷한 상황에서 실마리를 찾는데 시간을 줄일 수 있다면 좋을 것 같다

     

     

    출처

    https://www.youtube.com/watch?v=w4fWgLgop5U 

    https://catsbi.oopy.io/6136946a-9139-4541-b2af-2af93bb634a5

     

    Java Agent(-javaagent:)

    javaagent란?

    catsbi.oopy.io

     

    댓글

Designed by Tistory.