PM2 클러스터 모드, 포트 중복은 어떻게 되나요?
PM2 클러스터 모드에서 포트 점유를 어떻게 해결하는지 공유합니다. | Node.js, PM2, Cluster Mode
시작하기 전에…
클러스터 모드를 활용하면 어떤 이점이 있을까요?
Node.js 는 기본적으로 싱글 스레드로 동작합니다. 이로 인해 멀티 코어 환경에서 서버 자원을 완벽하게 활용하기 어려울 수 있습니다.
만약 서버 사양이 2코어, 4스레드라고 가정해보았을때, 최대 4개의 코어를 활용할 수 있습니다만, 싱글 스레드인 Node.js 구조에 따라 완벽하게 자원 활용이 불가한 상황이 생깁니다.
이런 문제를 클러스터 모드를 활용하여 해결할 수 있습니다. 클러스터 모드는 아래 그림과 같이 멀티 프로세스 형태로 구성하여 서버의 자원을 최대한 활용할 수 있도록 할 수 있습니다.
잠시만요, 멀티 프로세스라면 구동되는 소스는 똑같지 않나요?
맞아요, 실제로 클러스터 모드를 구동하는 커멘드를 보면 별도의 소스를 지정하지 않고, 간단한 옵션 (-i
)으로 클러스터 모드를 켤 수 있었습니다.
1
> pm2 start app.js -i max
그렇다면, 구동되는 소스들마다 포트 점유를 요청할탠데 문제가 없을까요?
1
server.listen(3000); // ???? 클러스터 모드에서 문제가 없을까?
이번 포스트에서는 이 질문에 대한 해답을 공유해보려 합니다.
PM2 문서 살펴보기
PM2 문서 를 살펴보았는데, 문서 초반에 아래와 같은 내용이 있어요.
Under the hood, this uses the Node.js cluster module such that the scaled application’s child processes can automatically share server ports.
PM2의 클러스터 모드는 Node.js의 클러스터 모듈을 활용하여 구동되고, 이로 인해 하위 프로세스들이 서버의 포트를 공유할 수 있다는 내용인데요, 따라서 Node.js의 클러스터 모듈의 포트 공유 방법에 대해 찾아보았어요.
Node.js 클러스터 모듈에서의 포트 공유
Node.js 클러스터 모듈 문서 를 살펴봤습니다. 이전에 언급한 것 처럼, 멀티 코어의 이점을 가지고 갈 수 있도록, 클러스터 모드에서는 하위 프로세스들을 생성하게 됩니다. 이떄 활용되는 메서드는 child_process.fork()
메서드로, 부모 프로세스와 자식 프로세스간 통신이 가능하도록 IPC 채널이 존재하게 됩니다.
child_process.spawn()
과 달리fork()
메서드는 IPC 채널이 존재하고,send()
메서드를 통해 통신이 가능하다는 내용이 있습니다. (공식 문서)
자식 프로세스를 생성하고 난 다음, Node.js 에서는 아래 두가지 방법들 중 하나를 활용하여 트래픽을 처리하게 됩니다. 각각의 방법은 cluster.schedulingPolicy
를 수동으로 지정하여 변경할 수 있습니다.
Round-Robin 방식 (SCHED_RR
, Windows OS가 아닌 경우 기본값)
부모 프로세스는 포트를 점유하여 요청을 받게 되고, round-robin 방법으로 하위 프로세스들에 IPC 채널을 활용하여 전파하는 방법입니다. 단일 프로세스가 과부하를 받지 않도록 적절한 빌트인 기능이 있습니다.
OS 스케줄러에게 위임 (SCHED_NONE
)
Round-Robin 방법과 달리 부모 프로세스가 아니라 하위 프로세스에서 직접 연결을 수락하여 처리하는 방법입니다. 따라서 부모 프로세스가 아니라 운영체제의 스케줄러가 트래픽을 분배하게 됩니다. SO_REUSEPORT
소켓 옵션을 활용하여 동일한 포트에 여러 프로세스가 바인딩 될 수 있도록 처리됩니다.
이론적으로는 Round-Robin 방법보다 효율적입니다만, OS 스케줄러는 단순히 작업의 실행을 예약하는 목적으로 설계되었고, 트래픽의 부하분산을 위해 설계되지 않았기에, 트래픽이 Round-Robin 방법보다 쏠림 현상이 확인되어 기본값으로 활용되지 않습니다. (테스트 시 70% 이상의 연결이 총 8개의 프로세스 환경에서 2개의 프로세스로 몰려서 처리됨)
Comments powered by Disqus.