OS

[WAS] tomcat이 메모리 부족으로 OOM Killer에 의해 중지될때 톰켓 자동 재시작 하는 방법

개발 서버 메모리는 16GB인데, 아파치 톰켓은 7개가 동시에 가동중이다. 고객사는 메모리 증설 계획이 없다.

운영중인 나는 하루에 한 번 서버 상태를 확인하여, 톰켓 7개중에 하나라도 죽은게 있는지 없는지 체크하는게 일이다.

이런건 스트레스다!! 그래서 출근길에 문득 “서버가 죽었을때 자동 재시작하게 하면 되겠네!! 서버 상태 체크 후 재시작하는 쉘스크립트를 작성해서, crontab에 등록해서 30분 간격으로 체크하면 되겠다” 라는 생각을 했다.

출근해서 ai의 도움을 받아서 좀 더 간단한 방법이 존재하는걸 알게되어 기록해둔다.

-Xms512m -Xmx1024m 설정값을 줄이는 것도 방법이긴한데… 이건 나중에 해보자!!


Swap은 늘리는 것이 좋을까?

Swap을 늘리면 즉시 OOM Killer가 발생하는 상황은 완화될 수 있습니다. 하지만 Swap은 RAM보다 매우 느리므로 Tomcat이 Swap을 많이 사용하면 다음 문제가 생길 수 있습니다.

  • 응답 시간 급증
  • GC 지연
  • 시스템 전체 멈춤에 가까운 현상
  • 결국 OOM Killer 발생

따라서 우선순위는 다음이 좋습니다.

  1. 각 Tomcat의 -Xmx 축소
  2. Tomcat maxThreads 축소
  3. Metaspace, Direct Memory, 스레드 수 점검
  4. Swap 사용률 모니터링
  5. 그래도 부족하면 Swap 증설
  6. 트래픽이 높은 Tomcat과 낮은 Tomcat의 메모리 차등 배분

setenv.sh에 직접 설정해도 됨

현재 setenv.sh가 다음과 같다면:

export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=dev -Djava.net.preferIPv4Stack=true -Dhttps.protocals=TLSv1,TLSv1.2 -Dfile.encoding=UTF-8 -Dconsole.encoding=UTF-8"

아래처럼 추가할 수 있습니다.

#!/bin/sh 
export JAVA_OPTS="$JAVA_OPTS -Xms512m -Xmx1024m -Dspring.profiles.active=dev... 생략"

또는 CATALINA_OPTS를 사용할 수도 있습니다.

#!/bin/sh 
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m -Xmx1024m"
export JAVA_OPTS="$JAVA_OPTS \-Dspring.profiles.active=dev ....생략"

위 내용은 나중에 해보려고 기록으로 남겨둔다.


톰캣 catalina.sh 파일의 CATALINA_OPTS 옵션에 “-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError를 이용해서 서버 재시작하는 방법

catalina.sh에 직접 수정하기보다는 bin/setenv.sh에 설정하는 것을 권장합니다. catalina.sh는 Tomcat 업그레이드나 패치 때 덮어써질 수 있습니다.

1. Heap Dump 저장 디렉터리 생성

먼저 Heap Dump를 저장할 디렉터리를 만들고 Tomcat 실행 계정에 권한을 부여합니다.

sudo mkdir -p /var/log/tomcat/heapdump
sudo chown -R tomcat:tomcat /var/log/tomcat/heapdump
sudo chmod 750 /var/log/tomcat/heapdump

tomcat 계정명은 실제 실행 계정에 맞게 변경하세요.

계정 확인하는 명령어

ps -ef | grep tomcat

tomcat    12345     1  0 10:00 ?        00:00:10 /usr/java/bin/java -D... org.apache.catalina.startup.Bootstrap

첫 번째 컬럼이 계정명입니다 (예: tomcat 계정).

2. setenv.sh 설정

Tomcat의 각 인스턴스에 해당하는 파일을 수정합니다.( setenv.sh 파일은 톰켓 설치 경로에 있을 확률이 높음)

기존 JAVA_OPTS를 유지하고 있다면 다음처럼 작성해도 됩니다.

#!/bin/sh

export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=dev...생략"


export CATALINA_OPTS="$CATALINA_OPTS \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/tomcat/heapdump \
-XX:OnOutOfMemoryError=\"kill -9 %p; sleep 10; /usr/local/tomcat/bin/startup.sh\""

  • -XX:+HeapDumpOnOutOfMemoryError: Java Heap OOM 발생 시 Heap Dump 생성
  • -XX:HeapDumpPath=...: Heap Dump 저장 위치
  • -XX:OnOutOfMemoryError="kill -9 %p": OOM 발생 시 해당 JVM PID를 강제 종료
  • %p: OOM이 발생한 JVM의 PID

Heap Dump 기능은 OOM 발생 시 JVM Heap을 HPROF 파일로 저장하며, 저장 경로도 지정할 수 있습니다.

 -XX:OnOutOfMemoryError는 OOM 발생 시 OS 명령을 실행하는 옵션입니다. 

Hi, I’m 관리자