[Dimelo Project] pm2 cluster mode session 공유 안되는 문제

Suyeon Pi·2022년 3월 7일
0

Dimelo

목록 보기
20/22

https://velog.io/@suyeonpi/Dimelo-Project-nest.js-docker%EC%97%90-pm2-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

지난 내 글을 보면 pm2를 fork 모드가 아닌 cluster모드로 instance를 2개를 사용하여 서버를 돌렸다.

사실 fork, cluster 차이도 잘 모르고 cluster로 2개의 프로세스를 만들어서 서버의 부하를 막을 수 있겠구나(?!) 해서 2개의 instance로 만들었다.

하지만 뭔가 이상한 버그가 발생했다.

로그인을 분명 했는데 로그인한 유저 정보를 불러왔다가 안왔다가 랜덤하게 되었다. 현재 express-session을 이용해 브라우저 메모리에 세션을 보관하고 있었다.

혹시 설마 pm2 cluster가 2개라서 그런가? 해서 찾아봤더니
pm2 cluster mode는 stateless라는 것이다. 즉 세션 공유를 cluster간 할수 없다는 것이다. 이 상태에서는 로컬 데이터 저장소를 프로세스에서 사용할수 없다. 사용을 하고 싶으면, connect-redis와 같은 저장소를 이용했어야 했다.

우선 빠른 배포를 위해 cluster모드를 다시 fork모드로 바꿨더니 정상적으로 작동하였다.

https://pm2.keymetrics.io/docs/usage/cluster-mode/
Statelessify your application
Be sure your application is stateless meaning that no local data is stored in the process, for example sessions/websocket connections, session-memory and related. Use Redis, Mongo or other databases to share states between processes.


그렇다면 대체 cluster mode란 무엇인가 ??

pm2 cluseter mode ?

Node.js 애플리케이션은 단일 CPU코어에서 실행되기때문에 하나의 코어밖에 사용하지 못한다. 만약 컴퓨터의 CPU가 하나가 아니라 8개의 CPU라면 자원을 낭비하고 있는셈이다. 그러면 CPU자원을 낭비하지 않고 모두 쓰게 하려면 어떻게 하면 될까? 그래서 나온게 cluster mode이다. pm2의 cluster mode를 사용하면 자동으로 시스템의 코어 개수에 맞는 프로세스들을 생성하고 각 프로세스의 상태에 따라서 로드 밸런싱도 해준다. CPU개수에 맞게 형성된 프로세스 들이 멀티프로세싱 할 수 있는 것이다.

그렇다면 왜 cluster mode는 stateless일까?

멀티프로세싱 Multiprocessing

프로세스란 OS입장에서 가장 작은 작업단위이다. 각 프로세스는 할당된 메모리를 가지며, 서로 할당된 영역에 간섭할 수 없다. 멀티프로세싱이란 여러 프로세스를 동시에 실행하는 것을 말하는데, 여기서 동시실행은 진짜 프로세스가 동시에 실행되는 것과 동시에 실행되는 것 처럼 보이는 실행이 있다.
동시에 실행되는 것 처럼 보이는 실행은 CPU가 여러 프로세스를 동시에 실행하는 것이 아니라, 한 프로세스가 사람이 인지할 수 없을 만큼 빠르게 CPU를 사용하고 다른 프로세스에 CPU를 양보함으로써 마치 동시에 실행되는 것 처럼 보이게 하는 것을 말한다.
진짜 동시 실행은 프로세스가 진짜 동시에 실행되는 것을 말하므로 CPU의 코어개수만큼 프로세스는 항상 동시실행 될 수 있다.

여기서 각 프로세스는 서로의 메모리 공간에 간섭을 못한다. CPU가 프로세스 간에 이동할때는 문맥교환이 일어난다. 간단하게, 문맥교환이란 CPU가 프로세스 간 이동할때 이전의 프로세스 상태를 보관하고 새로운 프로세스의 상태를 적재하는 것을 말한다.

멀티 쓰레딩은 하나의 프로세스 내에서 같은 메모리를 공유 한다는 점에서 멀티프로세싱과 다르다.

멀티쓰레딩 Multithreading

쓰레드란 한 프로세스 내에서 작업을 쪼개는 단위이다. 말그대로 한 프로세스 내에서의 일꾼이다. 한 프로세스가 관리하는 여러 스레드는 같은 메모리 공간을 공유할 수 있다. 멀티쓰레딩이란 여러개의 쓰레드가 동시에 실행되는 것인데 여기서도 동시 실행은 진짜 쓰레드가 동시에 실행되는 것이 아니라 쓰레드간 메모리를 공유하면서 이동한다. 멀티쓰레딩에서는 스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어든다. 즉, 쓰레드간 작업량이 작아 문맥교환이 빠르다. 그래서 멀티프로레싱보다 멀티쓰레딩이 더 선호된다.

하지만 Node.js는 기본적으로 싱글 스레드(thread)다. 그래서 멀티쓰레딩이 불가능 하다. 그래서 pm2를 이용해서 동시에 작업을 수행하는 다른 방법인 멀티프로세싱을 하는 것이 싱글스레드인 Node.js에서 권장되고 있다! 멀티코어를 활용하여 I/O작업들을 다른 코어에 분산시킬 수 있다.


왜 Node.js에서 pm2를 쓰는지, cluster mode는 왜 stateless인지 알게 되었다.

읽고 박수를 친 글
https://blog.appleseed.dev/post/nodejs-non-blocking-io-and-multicore-processing/

profile
Stay hungry, Stay foolish!

0개의 댓글