우아한 서버 종료 : Spring boot의 graceful shutdown

Kai·2024년 3월 8일
0

스프링

목록 보기
15/18

📌 이 글에서 사용한 코드 : 깃헙

🧐 graceful shutdown


server:
  shutdown: graceful
spring:
  lifecycle:
    timeout-per-shutdown-phase: 10s

spring boot 옵션에는 shutdown 옵션이 있다.
기본 값은 immediate이고, graceful이라는 값으로 설정할 수도 있다.

immediate로 설정했을 경우 서버가 종료되어야할 때, 즉시 종료된다.
그렇다면, graceful로 설정했을 경우엔 어떻게 동작하는 것일까?

graceful shutdown의 동작

graceful 옵션이 활성화되어 있으면, 서버는 바로 종료되지 않고 현재 처리 중인 요청을 다 처리한 후, 종료된다.
그리고, timeout-per-shutdown-phase에 정의된 시간이 남은 요청들을 처리할 수 있는 최대 시간이다.
즉, 이 시간 안에 처리하지 못한 요청들은 완전히 처리되지 못하고 서버가 종료되므로 에러를 응답하게 될 것이다.

왜 사용하는 것일까?

개발환경에서는 불필요할 수도 있는 옵션이지만, 실제 서비스를 운영하는 환경에서는 매우 중요한 옵션이다.

다중 서버 환경에서는 서버가 Scale-in, Scale-out되는 경우가 많을 것인데 Scale-in될 때, 이 옵션을 활성화하지 않으면, 특정 서버에서 작업이 이루어지는 중간에 서버가 갑자기 종료되버리는 불상사가 발생할 수 있다.

그래서 사실상 이 옵션은 '필수'적이라고 할 수 있다.

로컬에서 테스트

위에서 작성한대로 설정하고, 로컬에서 서버를 실행했다가 꺼보면, 우아하게(?) 서버를 잘 종료됐다는 메세지가 뜨게 된다.
이렇게 메세지가 잘 뜨면 설정은 잘 됐다는 의미라고 볼 수 있다.

하지만, 사실 중요한 것은 실제 서버 환경에서 서버 인스턴스가 '종료 (Terminating)'상태로 들어갔을 때, Spring boot서버가 graceful shutdown으로 잘 동작하는지이기 때문에 EC2 서버를 하나 만들고, 테스트를 해보도록 하자.


☠️ Kill


EC2인스턴스로 테스트해보기 전에 짚고 넘어갈 것들이 있다. 그 중에 하나가 kill명령어이다. kill명령어는 Unix, Linux 계열의 OS에서 특정 PID의 프로세스를 종료할 때 사용된다. kill 명령어 하나에도 다양한 옵션이 있는데, 그 중에서도 이번에는 2가지 옵션에 대해서 알아보도록 하겠다.

kill -9

kill -9 {프로세스의 PID}

kill -9 $(sudo lsof -t -i:8080)

프로세스 "강제" 종료에 해당한다. -9옵션으로 명령어를 실행하면, 해당 프로세스에 SIGKILL신호를 보내게 되고, 이 신호를 수신한 프로세스는 즉시 종료되게 된다.

이 옵션으로 Spring boot 서버를 종료하게 되면, graceful shutdown옵션이 활성화 되어 있어도 서버가 즉시 종료되게 된다.

kill -15

kill -15 {프로세스의 PID}

kill -15 $(sudo lsof -t -i:8080)

프로세스 종료에 해당한다. 프로세스에 SIGTERM신호를 보내게 되고, 이 신호를 수신한 프로세스는 '아 프로세스 종료해야되는 구나'라고 인지하고 프로세스를 종료하게 된다.

graceful shutdown 옵션을 활성화해놓은 상태에서 이 신호를 받으면, 실행중인 로직을 모두 처리하고 프로세스가 종료되게 된다.

서버의 종료 이벤트를 Spring boot 서버는 어떻게 알까?

Linux 서버의 경우, 서버 종료 명령을 받으면 실행중인 프로세스들에게 SIGTERM신호를 보내게 된다. 즉, Spring boot도 당연하게도 SIGTERM 신호를 받게 되는 것이다.


🤓 EC2로 테스트


이론적인 것들을 정리해봤으니, 실제로도 그렇게 동작하는지 알아보도록 하자.

EC2 인스턴스를 만들고, 그 안에서 서버를 실행해보았다.
정상적으로 잘 실행된 것을 확인할 수 있다.

이제, EC2 인스턴스를 종료해보겠다.
"Terminate"하면, 인스턴스 자체가 삭제되고 ssh 연결도 끊겨서 Graceful shutdown이 잘됐는지 로그로 확인할 수 없으니, "Stop"한 후에 인스턴스를 재실행해서, Graceful shutdown로그가 잘 남아 있는지 확인해보자.

EC2인스턴스를 중지 & 재실행한 후, 서버에 들어가서 로그를 확인해보니 graceful shutdown 로그가 잘 찍혀있는 것을 확인할 수 있었다. 🫡

0개의 댓글