JS/TIL(Today I Learned)

2025-03-05 <최종 프로젝트 D-9>

프린스 알리 2025. 3. 5.

Navigation Server 구현

문제 파악 및 구현 목적

  • 원격 서버(EC2)에서 테스트를 진행한 결과 필드에 몬스터가 늘어날수록 경로 탐색이 많아진 탓인지 게임이 느려지거나 끊겼다.
  • 복수의 플레이어와 몬스터들이 findPath 비동기 요청을 보냈고, 기존 서버에서 동기적으로 실행하느라 성능 저하가 발생한 것이라 판단했다. 혹은 CPU사용량의 문제일 수도 있다.(테스트엔 t2 micro를 사용했으므로)
  • 두 경우를 모두 고려하여 예방책을 생각해봤을 때, 별도의 네비게이션 서버에서 경로 탐색을 수행한다면 게임 서버의 부하를 줄이고 경로 연산을 병렬로 처리할 수 있을 것이다.
  • 다만, Node.js가 기본적으로 싱글 스레드 환경이므로, 병렬 처리를 위해서는 Worker Threads 또는 BullMQ 기반 분산 처리를 고려해야 했다.

BullMQ

  • 현재 메인 서버에서 Redis를 사용 중이고, 튜터님의 추천이 있었기에 BullMQ를 도입하기로 결정했다.
  • 사용법은 링크 참고 
  • BullMQ 공식 문서 : What is BullMQ | BullMQ

BullMQ에서 concurrency 값을 늘리는 것의 의미와 효과

concurrency 값은 각 Worker가 동시에 처리할 수 있는 작업 수를 의미한다.

즉, concurrency 값을 늘리면 한 개의 Worker 프로세스가 여러 개의 경로 탐색 요청을 동시에 처리할 수 있다.

1. BullMQ의 기본 처리 방식

BullMQ에서 Worker는 Redis의 큐에 쌓인 작업을 가져와 실행한다.

  • 기본적으로 Worker는 한 번에 하나의 작업만 처리한다.
  • 하지만 concurrency 값을 늘리면 Worker가 동시에 여러 개의 작업을 처리할 수 있다.
javascript
복사편집
import { Worker } from 'bullmq';

export const navigationWorker = new Worker(
  'navigationQueue',
  async (job) => {
    console.log(`job 처리하는 중 : ${job.id}`);

    const { sectorCode, start, end, socketId } = job.data;

    const navMesh = getNaveMesh(sectorCode);

    // 길찾기 수행
    const path = await findPath(navMesh, start, end);

    console.log(`경로 생성 됨 : ${job.id}`);

    // Job 결과 반환
    return { path, socketId };
  },
  {
	  concurrency: 2, // 동시에 2개의 경로 탐색을 처리 
	  connection 
  },
);

위 코드에서 concurrency: 4로 설정하면, 이 Worker는 최대 4개의 작업을 병렬로 실행할 수 있다.

즉, 새로운 경로 탐색 요청이 들어오면, 최대 4개까지는 동시에 처리되고, 그 이후 요청은 대기 상태가 된다.

 


구현해본 결과

 

 

 


 

추가로 공부해야 할 것

- BullMQ의 concurrency 매커니즘에 대해...이게 워커 스레드를 생성하는 게 맞나??

- t2.micro 환경에서 퍼포먼스 측정(부하가 어느 정도까지 되고 있는지)

(1) EC2 하나에서 서버를 나누고 측정해보기

(2) 별도의 EC2(2코어 서버)에서 싱글스레드로 서버 구축 후 측정해보기

응답 속도, CPU 사용량,

⇒ Jmeter

⇒ 리소스 모니터

⇒ 스크립트

싱글스레드 환경에서도 부하가 꽉 차게 이루어지는지?

 

---

 

워커 스레드를 생성하는 게 아니었다.

그리고 부하 테스트 결과가 별로 드라마틱하지 않다.

응답시간에선 딱히 이점이 없단 건데...CPU 사용량엔 영향을 미치려나?

댓글