Quick Flow
실시간 game session은 한 시점에 한 authoritative process가 소유합니다. 그 process만 player command를 tick 순서에 넣고, world state를 바꾸고, snapshot을 보냅니다. 수평 확장은 같은 world를 여러 process가 동시에 계산하게 하는 일이 아니라, 서로 독립적인 session을 더 많은 process에 배정하는 일부터 시작합니다.
matchmaking 또는 session service
-> idle process 선택 또는 새 process 기동
-> process가 match ID와 rule data를 받아 world 생성
-> ready 확인 뒤 client에 endpoint·admission grant 전달
-> 해당 process만 match의 authority를 유지process가 준비되기 전에는 endpoint를 client에 주지 않습니다. map load, rule data 검증, port bind, telemetry 준비가 끝난 뒤 ready 상태를 control plane에 보고하고, 그 뒤에만 placement 후보가 됩니다. hosting provider를 쓰면 그 provider의 activation·health callback은 이 상태 전이와 맞물려야 합니다.
소유권 경계
match ID는 owner process ID, build·rule revision, region, lifecycle state와 함께 control plane에 기록합니다. 이 기록은 discovery와 admission을 위한 것이며, 실시간 position·combat state를 매 tick database에 쓰라는 뜻은 아닙니다. live world는 owner process memory에 두고, 영속해야 하는 결과와 checkpoint만 별도 저장소에 둡니다.
function admit(request: JoinRequest) {
const owner = sessionDirectory.get(request.matchId);
if (!owner || owner.state !== "READY") return reject("match-unavailable");
if (!consumeGrantOnce(request.grantId, owner.processId)) return reject("invalid-grant");
return connectTo(owner.endpoint);
}두 process가 같은 match ID를 owner로 선언하면 split-brain입니다. player마다 다른 server에 붙거나 두 곳에서 보상이 확정될 수 있습니다. allocation은 match ID를 원자적으로 claim하고, 새 owner를 열기 전에 기존 owner가 실제로 종료됐는지 또는 fencing token이 더 최신인지 확인해야 합니다.
수평 확장의 단위
처음에는 process 하나가 game session 하나를 맡는 모델이 운영과 격리에 가장 단순합니다. CPU·memory가 남는 작은 match에서는 process 하나가 여러 session을 맡을 수도 있지만, session별 tick 지연과 memory를 분리해 측정해야 합니다. 한 session의 CPU spike가 같은 process의 다른 match deadline까지 밀면 capacity는 단순 player 수로 계산할 수 없습니다.
worker 수를 늘리기 전에 session startup 시간, 평균·상위 percentile match 수명, process당 동시 session 수, drain 시간, idle capacity를 측정합니다. "현재 CPU가 낮다"만으로 session density를 올리면 순간 전투와 snapshot burst에서 먼저 무너집니다.
자주 틀리는 부분
load balancer가 connection을 분산해 주므로 모든 process가 같은 match를 처리할 수 있다고 생각하면 안 됩니다. TCP 또는 UDP connection routing은 packet을 어디로 보낼지 정할 뿐, authoritative state 소유권을 합의하지 않습니다.
또한 match directory를 cache에만 두면 process crash 뒤 stale endpoint가 남습니다. health report, lease 만료, admission의 재확인을 함께 두고, stale owner를 발견한 client가 임의로 다른 process에 붙지 않게 해야 합니다.
참고 링크
2 sources