[Go] 우아하게 종료하기

devlcw·2024년 9월 1일

우아하게 종료하기

우아하게 종료한다는 의미는 Terminated된 작업 없이 모든 작업이 끝난 채로 종료되는 걸 말한다.

프로덕션에서 서버를 종료할 수 밖에 없는 상황이 있을 것이다. 여기서 우아한 종료를 구현하지 않으면 생길 수 있는 Abrupt Shutdown의 문제점을 톺아보자.

  1. 클라이언트 요청이 Terminated 된다.
  2. 자원이 Cleanup 되지 않는다.

(데이터 무결성은 요새 데이터베이스가 워낙 좋아서 안 넣었다.)

SIGTERM, SIGINT

대부분의 유닉스 운영체제에서 위 두 신호를 사용하여 우아한 종료를 구현할 수 있다. 두 신호별로 차이가 있다.

시그널설명예시
SIGTERM강제 종료 시 발생하는 시그널kill <PID>
SIGINT유저가 중단하기 위해 인터럽트 시 발생하는 시그널CTRL+C

윈도우같은 경우는 SIGTERM 신호를 못 받는다. 그래서 완벽한 Graceful Shutdown을 구현하려면 winapi를 사용해야한다..

이 신호들을 애플리케이션에서 캐치해서 적절히 잘 처리해주면 된다.

Go같은 경우는 signal 패키지에서 이 신호들을 채널로 잡아낼 수 있다.

flag := make(chanl os.Signal, 1) // Notify를 사용할 땐 버퍼 채널로 사용해야 함
signal.Notify(flag, syscall.SIGINT, syscall.SIGTERM) // 동기적으로 인자의 신호들이 올 때까지 블락

<-flag
log.Println("우-아하게 종료 중입니다..")

// 후처리

이후에 자신이 사용하는 라이브러리나 패키지를 종료하면 된다.
나는 fiber를 예시로 들었다.

app.ShutdownWithTimeout(5 * time.Second)

Go의 내장 http 패키지에서는 직접 context를 넘겨주는 shutdown 방법이 있는데 fiber는 내장 timeout이 달려있어서 편했다.

profile
모든 스택에는 이유가 있다

1개의 댓글

comment-user-thumbnail
2024년 9월 6일

좋네요

답글 달기