(TIL) 2025-02-25 FINAL(16)
(TIL) 2025-02-25 FINAL(16)
분산서버 작업 - 7일차
헬스 체크
- 게이트 웨이 서버
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
class Server { constructor(serverId, socket) { this.socket = socket; this.socket.id = serverId; //여기에 유니크 아이디 this.type = serverId.split(':')[1]; this.stack = 0; // 헬스체킹 this.interval = setInterval(this.healthCheck, 5000); } healthCheck = async () => { // stack 증감 const test = await redisClient.hGet(this.socket.id, 'check', 'testing'); if (test === 'testing') this.stack++; else this.stack = 0; // stack 검증 if (this.stack >= 2) { switch (this.type) { case 'Game': onGameEnd(this.socket)(); break; case 'Lobby': onLobbyEnd(this.socket)(); break; } } // 테스팅 시작 redisClient.hSet(this.socket.id, 'check', 'testing'); redisClient.publish(this.socket.id, 'testing'); // console.log(`//HealthCheck// [Server] ${this.socket.id} / [Stack] : ${this.stack} `); }; clearChecker() { clearInterval(this.interval); } }
기존 서버 세션에서 Map으로 관리했던걸 Class로 변경하여 서버가 올라가 게이트 웨이 서버와 각 서버가 연결이 되면 게이트 웨이 서버에서 주기적으로 해당 서버에 레디스의 PUB/SUB기능을 이용하여 각 서버에 메세지를 전달한다. 그리고 레디스에 ‘Check’ 필드를 추가하여 대상 서버에 대한 체크 상태 값으로 변경한다. 각 서버가 정상적인 경우 해당 메세지를 통해 ‘Check’ 값을 변경할 거고 만약 반응이 없는 경우 계속 testing 값이 유지되기에 다음 시도에도 testing인 경우에는 스택을 올려 일정 이상 스택이 쌓이면 해당 서버가 문제가 있다는 의미로 판단하여 해당 서버와 연결을 강제로 종료한다.
- 로비, 게임 서버
1
2
3
4
5
6
7
8
// 헬스체크 Sub 매핑
subscriber.subscribe(name, healthCheck);
console.log('Redis 서버 오픈 알림 성공');
const healthCheck = (message, channel) => {
// console.log(channel, message);
redisClient.hSet(channel, 'check', 'update');
};
로비 서버와 게임 서버에서는 헬스체크 채널을 받아 레디스에 ‘Check’필드에 정상이라는 의미의 update 값으로 변경한다.
로드 밸런싱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 로드 밸런싱 후 게임 서버 이름 저장
const gameServers = serverSession.getGameServers();
console.log('size : ', gameServers.size);
let minGameCount = Infinity;
let gameServerId = null;
let minGameServer;
// game 수가 최소인 게임 서버 ID 확인
for (const [id, gameServer] of gameServers) {
const count = await redisClient.hGet(id, 'games');
if (count < minGameCount) {
minGameCount = count;
gameServerId = id;
minGameServer = gameServer;
}
}
// 게임 상태 동기화
for (const { name, userId: tempId } of payload.room.users) {
const tempUser = userSession.getUserByID(tempId);
tempUser.setGameState(payload.success);
tempUser.gameServer = gameServerId;
}
const serverPayload = { room: payload.room };
const reqPacket = makeServerPacket(
config.packetType.JOIN_SERVER_REQUEST,
serverPayload,
user.id,
);
console.log(`${gameServerId} 서버로 ${payload.room.users.length}수의 유저가 분배되었습니다!`);
minGameServer.socket.write(reqPacket);
테스트
로컬에서 테스트를 해본 결과 로드밸런싱이 정상적으로 작동되어 각 게임이 Game 1,2 서버에 배분되어 동작하는 것을 확인할 수 있었다. 이로서 정적인 서버에서 로드밸런싱과 헬스체크까지 모두 개발이 완료되었다. 내일은 오늘까지 한 것을 다시 AWS에 적용하여 테스트를 해볼 예정이며 후에 시간이 남으면 스케일아웃 상황을 고려한 로드밸런싱 처리에 대해서 작업을 해볼 생각이다.
This post is licensed under CC BY 4.0 by the author.
