Failover와 Fault Tolerant

서비스 중인 프로세스에 문제가 발생하는 원인은 매우 다양합니다. 감당하기 힘든 부하가 발생하거나 코드 문제일 수 있고, 운영체제에 문제가 발생하거나 다른 프로세스의 간섭으로 실행이 중단될 수 있습니다. 외부적으로는 하드웨어적인 결함이나 네트워크 문제, 심지어 사람의 실수 등 셀 수 없이 다양한 이유로 프로세스가 종료되기도 합니다. 이때 장애에 대응하는 방법으로 Failover와 Fault Tolerant란 개념이 있습니다.

마이크로서비스 아키텍처는 기본적으로 분산 아키텍처이기 때문에 마이크로서비스를 충분하게 분산 배치했다면 Failover 기능을 수행한다고 할 수 있습니다. 또 특정 마이크로서비스에 문제가 발생해도 다른 API를 서비스하는 마이크로서비스는 정상적으로 동작하기 때문에 Fault Tolerant 기능도 수행한다고 할 수 있습니다.

마이크로서비스 아키텍처는 장애에 강한 아키텍처입니다. 하지만 스스로 프로세스를 복구할 수 있는 기능이 없다면 고가용성 시스템이라고 하기 어렵습니다. 문제가 발생한 마이크로서비스가 자동으로 재실행되는 기능을 알아보겠습니다.

Cluster 모듈 활용

Node.js에는 cluster라는 모듈을 기본으로 제공합니다. cluster 모듈은 우리가 실행한 프로세스에서 원하는 만큼 자식 프로세스를 생성합니다. 문제가 발생해도 자식 프로세스 하나에서만 발생하기 때문에 다른 자식 프로세스는 정상적으로 서비스할 수 있습니다. 게다가 종료된 자식 프로세스를 감지해 또 다른 자식 프로세스도 실행할 수 있습니다. 이 기능을 활용하면 결함이 있더라도 영원히 중단되지 않는 서비스를 제공할 수 있습니다.

클러스터를 이용해 자식 프로세스를 3개 실행

클러스터를 이용해 자식 프로세스를 3개 실행

자식 프로세스 1에 문제 발생 – 나머지 자식 프로세스는 정상 서비스

자식 프로세스 1에 문제 발생 – 나머지 자식 프로세스는 정상 서비스

자식 프로세스 1이 종료되면 부모 프로세스가 이를 감지해 자식 프로세스 4를 실행

자식 프로세스 1이 종료되면 부모 프로세스가 이를 감지해 자식 프로세스 4를 실행

자식 프로세스를 3개 유지

자식 프로세스를 3개 유지

Cluster 모듈 예제

Node.js 공식 사이트에서 제공하는 cluster 모듈 예제 코드로 사용법을 알아보겠습니다. 원본은 **https://nodejs.org/dist/latest-v6.x/docs/api/cluster.html**에서 확인할 수 있습니다.

다음과 같이 코드를 작성한 후 cluster.js로 저장합니다.

const cluster = require('cluster'); // ➊ cluster 모듈 로드
const http = require('http'); // ➋ http 모듈 로드
const numCPUs = require('os')
    .cpus()
    .length; // ➌ CPU 코어 수를 알아 옴

if (cluster.isMaster) { // ➍ 부모 프로세스일 경우
    console.log(`Master ${process.pid} is running`);
    for (let i = 0; i < numCPUs; i++) { // ➎ 코어 수만큼 자식 프로세스 실행
        cluster.fork();
    }
    cluster.on('exit', (worker, code, signal) => { // ➏ 자식 프로세스 종료 이벤트 감지
        console.log(`worker ${worker.process.pid} died`);
    });
} else { // ➐ 자식 프로세스일 때 HTTP 서버 실행
    http
        .createServer((req, res) => {
            res.writeHead(200);
            res.end('hello world\\n');
        })
        .listen(8000);
    console.log(`Worker ${process.pid} started`);
}

cluster 모듈을 이용해 HTTP 서버를 실행하는 예제 코드입니다. cluster 모듈과 http 모듈을 로드합니다(➊, ➋). CPU 코어 수만큼 자식 프로세스로 실행하려고 os 모듈을 이용해 코어 수를 알아 옵니다(➌). cluster 모듈의 isMaster 값을 이용해 부모 프로세스와 자식 프로세스를 구분할 수 있습니다(➍). 부모 프로세스라면 코어 수만큼 자식 프로세스를 실행합니다(➎). fork 함수를 이용해 실행된 자식 프로세스가 종료되면 부모 프로세스에서 이를 감지할 수 있도록 exit 이벤트를 설정합니다(➏). 자식 프로세스로 실행되었다면 http 모듈을 이용해 HTTP 서버를 실행합니다(➐).

이제 cluster.js가 위치한 경로에서 다음과 같이 실행하면 자식 프로세스가 생성됩니다.

> node cluster.js
Master 3596 is running
Worker 4324 started
Worker 4520 started
Worker 6056 started
Worker 5644 started