Quick Flow
서버를 내릴 때 process exit부터 호출하지 않습니다. 먼저 drain 상태로 바꿔 allocator와 matchmaking이 새 session·reservation을 만들지 못하게 하고, 이미 진행 중인 match만 제한 시간까지 마무리합니다. deadline 안에 끝나지 않는 match는 현재 state와 결과 처리 상태를 남긴 뒤 recovery 또는 명시적 종료 정책으로 넘깁니다.
ACTIVE
-> DRAINING: 새 placement·입장·backfill 중지
-> CLOSING: 남은 match에 종료 시각과 정책 통지
-> FINALIZING: 결과·보상·telemetry를 한 번만 기록
-> STOPPED
deadline 초과 -> state checkpoint 또는 복구 경로 -> 강제 종료DRAINING에서는 기존 player의 현재 match만 진행시키고 새 placement·seat reservation·backfill을 막습니다. CLOSING에서는 종료 공지와 결과 확정만 허용하며, FINALIZING에서는 idempotent result 저장과 연결 정리를 끝냅니다. deadline 뒤의 forced stop은 정상 종료로 기록하지 않습니다.
drain은 load balancer에서 health check가 통과하는지와 별개입니다. process가 살아 있어도 match allocator가 이 instance를 후보에서 빼야 하며, admission service도 drain flag를 확인해야 합니다.
종료 신호를 받았을 때
async function beginDrain(deadline: Date) {
serverState = "DRAINING";
await allocator.removeInstance(instanceId);
await matchmaking.cancelBackfills(instanceId);
for (const match of activeMatches()) {
match.setShutdownDeadline(deadline);
match.notifyClients("server-draining", { deadline });
}
}새 connection을 즉시 끊을지, lobby까지만 허용할지는 서비스 경계에 따라 정합니다. 진행 중인 game session에는 이미 발급된 reconnect token을 deadline까지 허용할 수 있지만, 새 player를 채우는 backfill은 중지하는 편이 보통 안전합니다. 어떤 경우든 admission은 drain 상태를 authoritative하게 확인해야 합니다.
match가 정상 종료되면 게임 결과와 보상을 transaction 또는 unique result key로 한 번만 저장합니다. process 종료 callback 안에서 수천 건을 동기 저장하는 설계는 deadline을 넘기기 쉽습니다. match 진행 중 checkpoint가 필요한 게임은 주기적으로 쓸 수 있어야 하며, shutdown 순간에만 모든 state를 저장하려 해서는 안 됩니다.
deadline 뒤의 선택
deadline은 종료를 영원히 기다리지 않도록 정한 운영 계약입니다. 남은 match가 있으면 다음 셋 중 하나를 mode별로 고릅니다: 현재 결과를 무효 처리하고 client를 lobby로 돌려보내기, checkpoint에서 재개하기, 승패·보상을 규칙에 따라 확정하기. 어떤 정책이든 client 공지, persistence 상태, analytics reason code가 일치해야 합니다.
SIGTERM을 받자마자 socket을 닫으면 client는 일시 network failure와 의도된 종료를 구분하지 못합니다. 가능한 범위에서 종료 예정과 reconnect 또는 결과 조회 경로를 먼저 알립니다. 다만 인프라가 보내는 termination deadline을 넘길 수 없으므로, 이 알림은 graceful path일 뿐 복구의 유일한 수단이 되어서는 안 됩니다.
자주 틀리는 부분
drain flag만 memory에 두면 process가 crash한 뒤 allocator가 instance를 계속 배정할 수 있습니다. service discovery 또는 control plane의 상태를 바꾸고, 새 placement와 admission request 양쪽에서 그 상태를 확인합니다.
또한 종료 중 발생한 result를 재시도 없이 버리면 정상 match가 무보상으로 끝날 수 있습니다. 반대로 결과 저장 retry를 idempotent하지 않게 만들면 retry가 중복 보상을 만듭니다. 종료 절차는 availability와 data correctness를 함께 다뤄야 합니다.
참고 링크
2 sources