$ npm i @godaddy/terminus --save
이번 글에서는 Health Check를 통한 Shutdown 대응 방법에 대해 알아보도록 하겠습니다.
정상적인 종료
애플리케이션의 새 버전을 배포할 때 이전 버전을 교체해야 합니다. 사용 중인 프로세스 관리자는 먼저 응용 프로그램에 SIGTERM 신호를 보내 응용 프로그램이 종료될 것임을 알립니다.
애플리케이션이 이 신호를 받으면 새 요청 수락을 중지하고 진행 중인 모든 요청을 완료하고 데이터베이스 연결 및 파일 잠금을 포함하여 사용한 리소스를 정리한 다음 종료해야 합니다.
const server = app.listen(port) process.on('SIGTERM', () => { debug('SIGTERM signal received: closing HTTP server') server.close(() => { debug('HTTP server closed') }) })
상태 확인
로드 밸런서는 상태 확인을 사용하여 애플리케이션 인스턴스가 정상이고 요청을 수락할 수 있는지 확인합니다. 예를 들어 Kubernetes에는 두 가지 상태 확인이 있습니다.
- 컨테이너를 다시 시작할 시기를 결정하는 활동성.
- 컨테이너가 트래픽 수락을 시작할 준비가 된 시점을 결정하는 준비 상태. 포드가 준비되지 않은 경우 서비스 로드 밸런서에서 제거됩니다.
외부 솔루션
Terminus
Terminus는 상용구 코드를 작성할 필요가 없도록 애플리케이션에 상태 확인 및 정상적인 종료를 추가하는 오픈 소스 프로젝트입니다. 정상적인 종료를 위한 정리 논리와 상태 확인을 위한 상태 확인 논리만 제공하면 터미널이 나머지를 처리합니다.
다음과 같이 터미널을 설치합니다.
$ npm i @godaddy/terminus --save
다음은 터미널 사용을 설명하는 기본 템플릿입니다. 자세한 내용은 https://github.com/godaddy/terminus를 참조하십시오.
const http = require('http') const express = require('express') const { createTerminus } = require('@godaddy/terminus') const app = express() app.get('/', (req, res) => { res.send('ok') }) const server = http.createServer(app) function onSignal () { console.log('server is starting cleanup') // start cleanup of resource, like databases or file descriptors } async function onHealthCheck () { // checks if the system is healthy, like the db connection is live // resolves, if health, rejects if not } createTerminus(server, { signal: 'SIGINT', healthChecks: { '/healthcheck': onHealthCheck }, onSignal }) server.listen(3000)
Lightship
Lightship은 애플리케이션에 상태, 준비 및 활성 검사를 추가하는 오픈 소스 프로젝트입니다. Lightship은 별도의 HTTP 서비스로 실행되는 독립형 HTTP 서비스입니다. 이를 통해 공개 인터페이스에 노출하지 않고도 health-readiness-liveness HTTP 끝점을 가질 수 있습니다.
다음과 같이 Lightship을 설치합니다.
$ npm install lightship
Lightship 사용을 설명하는 기본 템플릿:
const http = require('http') const express = require('express') const { createLightship } = require('lightship') // Lightship will start a HTTP service on port 9000. const lightship = createLightship() const app = express() app.get('/', (req, res) => { res.send('ok') }) app.listen(3000, () => { lightship.signalReady() }) // You can signal that the service is not ready using `lightship.signalNotReady()`.
Lightship 설명서는 해당 Kubernetes 구성의 예와 Express.js와의 완전한 통합 예를 제공합니다.
http-terminator
http-terminator는 express.js 서버를 정상적으로 종료하기 위한 논리를 구현합니다. Node.js에서 HTTP 서버를 종료하려면 열려 있는 모든 연결을 추적하고 서버가 종료된다는 신호를 보내야 합니다.
http-terminator는 시간 초과 시 모든 연결 및 종료를 추적하는 논리를 구현합니다. 또한 http-terminator는 현재 이 서버로부터 응답을 받고 있는 모든 클라이언트를 종료하려는 서버 의도의 정상적인 통신을 보장합니다.
다음과 같이 http-terminator를 설치합니다.
$ npm install http-terminator
http-terminator 사용을 설명하는 기본 템플릿:
const express = require('express') const { createHttpTerminator } = require('http-terminator') const app = express() const server = app.listen(3000) const httpTerminator = createHttpTerminator({ server }) app.get('/', (req, res) => { res.send('ok') }) // A server will terminate after invoking `httpTerminator.terminate()`. // Note: Timeout is used for illustration of delayed termination purposes only. setTimeout(() => { httpTerminator.terminate() }, 1000)
http-terminator 문서는 API 문서 및 기존 타사 솔루션과의 비교를 제공합니다.
express-actuator
express-actuator는 애플리케이션을 모니터링하고 관리하는 데 도움이 되는 엔드포인트를 추가하는 미들웨어입니다.
다음과 같이 익스프레스 액추에이터를 설치합니다.
$ npm install --save express-actuator
express-actuator 사용을 설명하는 기본 템플릿:
const express = require('express') const actuator = require('express-actuator') const app = express() app.use(actuator()) app.listen(3000)
express-actuator 설명서는 사용자 지정을 위한 다양한 옵션을 제공합니다.