ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • GC Overhead Limit Exceeded 발생..
    웹 운영 2022. 3. 1. 12:31
    반응형

    웹서비스 운영 담당하고있으면 장소와 시간의 제약없이 핸드폰이 울린다..

    여러 Exception들이나 무수한 에러들, 여러 서버의 상태 등등 평소와 다른 일반적이지 않은 상태에 대한 내용이 핸드폰으로 전송이되는데 보통 늘 발생하는 메시지들은 대수롭지 않게 여기어 넘기는데

    OutOfMemoryError로 GC overhead limit exceeded 에 대한 메시지가 갑자기 여러개 확인되어 급히 밥먹다말고 서버에 접속해서 로그를 확인했다.

    해당 메시지는 익숙하지 않은 메시지라 서비스의 정상 유무 확인과 서비스내의 중요 기능 테스트를 시작했고, 서비스에는 아직 이상 없음을 확인하고 바로 해당 메시지를 찾아 조치를 하려고 했다.

    현재 우리 회사는 APM으로 scouter를 쓰고 있는데 scouter에서 GC Count 라는 것을 확인할 수 있다.

    GC가 관련되어 보여 일단 GC Count를 확인하였는데 왠걸,,, 평소 1~3 을 웃도는 수치가 400까지 올라간 것이다...

    일단 서비스의 재기동으로 GC Count를 정상적인 수치로 만들었으나, 언제 다시 올라갈지 모르는 상황이라 빨리 원인을 찾았다.

     


     

    먼저, JVM 의 구조는 다들 아시다시피

    1. 클래스 파일을 로드하는 Class Loader
    2. Class Loader를 통해 JVM내의 Runtime Data Area에 배치된 바이트 코드를 읽고 실행하는 Execution Engine
    3. 힙 메모리 영역내의 참조되지 않은 객체들을 제거하는 Garbege Collector
    4. 애플리케이션을 실행할 떄 사용되는 데이터들을 적재하는 Runtime Data Area

    로 구성되고 또, Runtime Data Area 안에서는

    1. 인터페이스, 메소드 Static 변수들이 저장되는 Method Area
    2. 동적으로 생성된 객체가 저장되는 Heap Area
    3. 메소드 안에서 사용되는 매개변수, 지역변수, 연산 등의 값들을 저장하는 Stack Area
    4. 쓰레드의 명령 내용을 기록하는 PC Register
    5. 자바외 언어로 작성된 네이티브 코드를 위한 Native MEthod Stack

    으로 구성된다.

     

    여기서 알 수 있듯이 Garbege Collector는 Heap Area 내의 참조되지 않은 객체들을 제거하는데, 이를 조금 더 자세히보면

    1. Garbage Collector Stack 의 모든 변수를 스캔하여 각각 어떤 객체를 참조하고 있는지 Mark 한다.
    2. Reachable Object가 참조하는 객체를 찾아서 Mark 하고 마킹되지 않은 객체를 Heap 에서 Sweep 한다.

    이를 Garbage Collector 의 Mark and Sweep 과정이라 한다.


    조금 더 자세히 설명 하면 Heap 영역은 New Generation (Eden, Survival0, Survival1) 과 Old Generation 으로 구성되며,
    처음 객체가 생성이되면 Eden 영역의 메모리를 할당한다.

    Eden 영역의 메모리가 다 사용이되면, GC(Mark and Sweep 과정)이 발생하고, 이를 Minor 라 한다.
    이렇게 Minor 과정이 일어난 후 살아남은 객체는 Survial 0으로 이동하게 되고, Survival0 영역의 메모리가 마찬가지로 다 사용하게 되면 GC(Mark and Sweep)-Minor 가 발생하며 Survival1로 이동한다.
    * 이때 해당 객체들의 Age 값이 증가하게 된다.

    이런 과정이 반복되다가 특정 Age 값이 되면 Old Generation으로 이동하는데 이를 Promotion 이라고 한다.
    Old Generation 에서도 해당 영역의 메모리가 사용되면 GC가 발생하는데 이때는 Major 라고 한다.

    여기서 위에서 언급한 GC Overhead Limit Excceded 가 일어나는 원인이 나오는데,

    GC Overhead Limit Exceeded 는 

    1. Garbage  Collector 가 너무 빈번하게 일어나서 오버헤드가 발생하는 경우,
    2. Java 프로세스가 GC를 수행하는 시간의 98%를 소비했지만, Heap 메모리의 2% 미만으로 복구되는 경우,
    3. 응용 프로그램이 사용 가능한 거의 모든 메모리를 소진했고, GC가 메모리를 정리하는데 너무 많은 시간과 반복적 실패를 했을 경우

    로 나타난다.

     


     

    위에서 JVM 의 구조부터 Heap 영역의 할당, Heap 영역 내에서의 GC 과정을 아주 간단하게 이해했고,
    그렇기 때문에 웹 서비스가 동작중에 발생한 이유는

    Heap 영역의 객체가 생성이 되고 이에 대한 GC가 일어날 때 많은 시간을 소비했지만, Heap 메모리의 복구가 쉽지 않다.

    이고, 우리 서비스에서 어떤 코드 및 객체가 문제인지 파악이 필요했다.

    그래서 해당 문제가 발생한 서버에 접속하여

    1. jamp -dump:live,format=b,file=heapdump.hprof (서비스 PID) 를 통해 덤프 파일을 내려받았다.
    2. 내려받은 heapdump.hprof 파일을 IBM HeapAnalyzer 로 실행했다.

    위는 실제 내려받은 dump 파일을 분석한 내용을 캡쳐한 것인데 해당 객체의 크기가 1.5MB 로 상당히 큰것을 볼 수 있다.
    실체 이러한 객체가 생성되고 지워지는데 오랜 시간이 걸린것으로 추정이되고, 다 지워지지 못한 채 메모리를 잡고 있는것으로 보여졌다.

    해당 기능은 관리자 페이지에서 게시글을 불러오는 기능인데 CSS, HTML 의 불필요한 요소들이 글 작성 시에 입력이 되고, 이렇게나 불필요한 CSS,HTML 코드들이 많은 양으로 들어가다보니 Size가 커졌다.

    * 위의 문제에 대해 경험을 하여 해결하신 선배님들 혹은 경험이 아니더라도 올바른 방향으로 알려주실 수 있는 업계 선배님들께서는 답글로 알려주시면 배우겠습니다.!!

    반응형

    '웹 운영' 카테고리의 다른 글

    웹 서버에 설치된 MPM 확인  (0) 2021.03.27
    DNS  (0) 2020.03.07
    ISMS - Information Security Management System 심사 후기  (0) 2020.02.28
    데브옵스란..  (3) 2020.02.07
    웹 운영 회사 취업 후 신입 이야기  (1) 2019.12.24
Designed by Tistory.