-
Notifications
You must be signed in to change notification settings - Fork 896
1st Party / Distributed Matchmaker support #660
Description
Objective
To be able to support matchmaking systems that require a gameserver to register themselves with the matchmaker -- such as first party matchmakers.
Background
Many matchmakers that console and others companies provide as hosted services, have a matchmaker workflow in which:
- A gameserver will register itself with the matchmaker when ready (usually for a specific period of time), with their IP and port(s) for gameplay
- The matchmaker will choose the gameserver out of the pool that have registered themselves
- The matchmaker will communicate to the game server that the matchmaker has chosen it for gameplay
- Players will then play on the game server.
This would be an alternative flow to FleetAllocation or GameServerAllocation, which will remain the preferred method of GameServer allocation, so that Agones can retain fine control of scheduling within the cluster, but since this is quite a prevalent workflow, Agones should also support it, with appropriate documentation on the tradeoffs.
Requirements and Scale
The design and implementation must ideally have no potential race conditions, and actively prevent the user from incurring race conditions in their usage as well.
Design Ideas
To support this within Agones, we will need to add three enhancements:
- A new
ReservedGameServerstate - A new SDK function
Reserve(seconds) - A new SDK function
Allocate()
Reserved GameServer State
Reserved state is to signify that the GameServer cannot be deleted, as it may move to allocated in a given time frame. Therefore:
- When scaling down a Fleet,
Reservedinstances will not be deleted - When autoscaling a fleet, they will be counted towards the current buffer, and therefore a change of state to
Reservedwill not incur an increase in GameServers in the Fleet.
This will mean that if a GameSerer is not demarcated for a game session by the matchmaker, it can move back to Ready in a timely manner, and is able to be scaled down as needed.
SDK Function: Reserve(seconds)
This new SDK function, Reserve will set the GameServer record to the Reserved state for the given number of seconds. (0 indicating forever). When that time period has ended, the GameServer shall revert back to Ready.
It is assumed that when working with a matchmaker, the developer will mark the GameServer as Reserved for slightly longer than it is registered with the matchmaker, so as to avoid scale down race conditions.
Technical Details
Rather than implementing this with a queue, this should be a synchronous call to the Kubernetes API, with in-built retry and a timeout (30s) on failure. Otherwise there is potential for race conditions between calling the SDK function, and the GameServer being moved to Reserved state.
SDK Function: Allocate()
This new SDK function all allows a game server to mark itself as Allocatedwhen called.
Technical Details
Rather than implementing this with a queue, this should be a synchronous call to the Kubernetes API, with in-built retry and a timeout (30s) on failure. Otherwise there is potential for race conditions between calling the SDK function, and the GameServer being moved to Allocated state.
SDK Function: Ready()
As currently exists, Ready() should return the GameServer to a ready state, but also remove any timeout that may be in place from a Reserve(n).
Proposed Matchmaker Workflow
The following would be the workflow for a game server process as it is integrated with Agones and 1st party matchmaker.
In this workflow, there is no requirement for a GameServer to mark themselves as Ready - they can Reserve(n) themselves as soon as they are about to register themselves with the matchmaker.
@startuml
GameServer -> "Agones SDK": Reserve(n)
note right: n is longer than the known\nReservation time with the\nmatchmaker
GameServer -> "MatchMaker SDK": Register()
GameServer <- "MatchMaker SDK": GameStarting()
GameServer -> "Agones SDK": Allocate()
GameServer -> "MatchMaker SDK": Confirm()
@enduml