[Spring Boot, Java, Docker] Spring Batch Job 실행 중 java heap space 에러 해결

Sungjin Cho·2024년 9월 10일
0

Spring Boot

목록 보기
12/15
post-thumbnail

Java Heap Space 오류 트러블슈팅

문제 상황

BackupJob 실행 중 다음과 같은 에러가 발생했다.

2024-09-10T05:35:03.820Z ERROR 1 --- [gazapos_db] [ AsyncThread-19] o.s.batch.core.step.AbstractStep         : Encountered an error executing step backupStep in job backupJob
java.lang.OutOfMemoryError: Java heap space

원인 분석

  1. Java heap space 오류는 애플리케이션이 사용 가능한 메모리를 초과했을 때 발생하는 오류이다.
  2. 주로 대용량 데이터 처리나 메모리 누수로 인해 발생한다.
  3. 이 경우, MySQL 데이터베이스 전체 내용을 dump해서 파일로 저장하는 과정에서 문제가 발생했다.
  4. 생성되는 dump 데이터의 크기가 100MB 이상이며, 도커 컨테이너 내부에서 Spring 서버를 실행 될 때 발생한 에러이다.

메모리 할당 고려사항

최대한 많은 메모리를 할당하지 않는 이유

  1. 시스템 리소스 공유: 서버에서 여러 애플리케이션이나 서비스가 동시에 실행될 수 있다. 한 애플리케이션이 너무 많은 메모리를 사용하면 다른 프로세스에 영향을 줄 수 있다.
  2. 가비지 컬렉션(GC) 성능: 힙 크기가 너무 크면 GC에 더 많은 시간이 소요될 수 있어, 애플리케이션의 응답 시간에 영향을 줄 수 있다.
  3. 메모리 파편화: 큰 힙은 메모리 파편화 문제를 야기할 수 있어, 실제 사용 가능한 메모리가 줄어들 수 있다.
  4. 스왑 사용 증가: 물리적 메모리보다 큰 힙을 할당하면 스왑 사용이 증가하여 성능이 크게 저하될 수 있다.

메모리 설정 크기에 따른 장단점

더 크게 설정했을 때

장점:

  • 대용량 데이터 처리 용이
  • Out of Memory 오류 발생 가능성 감소
  • 객체 할당 및 해제 빈도 감소로 GC 횟수 감소

단점:

  • GC 수행 시 일시 정지 시간(Stop-the-world) 증가
  • 다른 프로세스나 애플리케이션을 위한 시스템 리소스 부족
  • 메모리 파편화 가능성 증가
  • 컨테이너 환경에서 리소스 제한에 도달할 가능성

더 작게 설정했을 때

장점:

  • GC 수행 시간 감소로 애플리케이션 응답성 향상
  • 다른 프로세스나 애플리케이션을 위한 시스템 리소스 여유
  • 컨테이너 환경에서 리소스 제한 준수 용이

단점:

  • 대용량 데이터 처리 시 성능 저하
  • Out of Memory 오류 발생 가능성 증가
  • GC 횟수 증가로 인한 CPU 사용량 증가

최적의 JVM 메모리 설정 접근 방식

  1. 애플리케이션의 메모리 요구사항 분석
  2. 시작점으로 전체 시스템 메모리의 50-70% 정도를 최대 힙 크기로 설정
  3. 성능 테스트 및 모니터링을 통한 점진적 조정
  4. GC 로그 분석을 통한 GC 동작 최적화

Xmx와 Xms 설정에 대한 고려사항

Xmx와 Xms를 동일하게 설정할 때의 장단점

장점:

  • 메모리 할당 시간 감소: JVM이 힙 크기를 조정할 필요가 없어 성능이 안정적
  • 예측 가능한 성능: 힙 크기가 고정되어 GC 동작이 일관됨
  • 메모리 단편화 감소: 고정된 힙 크기로 인해 메모리 단편화 가능성이 줄어듦

단점:

  • 유연성 부족: 다른 프로세스나 애플리케이션을 위한 여유 메모리가 줄어들 수 있음
  • 불필요한 메모리 사용: 애플리케이션이 항상 최대 메모리를 필요로 하지 않을 때도 메모리를 점유

Xmx와 Xms를 동일하게 설정하기 좋은 경우

  • 서버 환경에서 단일 Java 애플리케이션을 실행하는 경우
  • 성능이 매우 중요하고 예측 가능해야 하는 경우
  • 충분한 메모리가 있고 다른 애플리케이션과의 경쟁이 없는 경우

Docker 컨테이너 환경에서의 고려사항

Docker 컨테이너 환경에서는 제한된 리소스를 가지고 있으며, 여러 컨테이너가 동일한 호스트에서 실행될 수 있다. 이런 경우에는 Xms를 Xmx보다 작게 설정하여 초기에 필요한 만큼만 메모리를 할당하고, 필요에 따라 증가할 수 있도록 하는 것이 더 유리할 수 있다.

결론

따라서 개발 상황에 맞게 JVM의 메모리를 적절하게 설정하는 것이 필요하다. default 설정으로 도커 컨테이너에서 Spring 서버가 실행되면서 backupjob에서 에러가 발생했고, JAVA_OPTS에서 Xmx, Xms 옵션을 설정하여 JVM 메모리 크기를 늘려준 결과 java.lang.OutOfMemoryError: Java heap space 에러가 발생하지 않고 원하는 결과대로 dump 한 결과인 .sql 파일이 저장되는 것을 확인할 수 있었다.

기존에는 하나만 저장되고 두번째 파일이 저장되는 Spring Batch job이 실행될 때 에러가 발생하였지만 이제는 잘 저장되고, 여러 개도 잘 저장되는 것을 확인하였다.

0개의 댓글