Skip to content

Commit

Permalink
Merge branch 'main' into docs/high-density-counters
Browse files Browse the repository at this point in the history
  • Loading branch information
igooch authored Jan 9, 2025
2 parents 967f7a9 + 97c1f51 commit 1c27dbb
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 19 deletions.
3 changes: 2 additions & 1 deletion build/includes/website.mk
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ site-images: ${site_path}/static/diagrams/system-diagram.dot.png
site-images: $(site_path)/static/diagrams/gameserver-lifecycle.puml.png
site-images: $(site_path)/static/diagrams/gameserver-reserved.puml.png
site-images: $(site_path)/static/diagrams/canary-testing.puml.png
site-images: $(site_path)/static/diagrams/allocation-player-capacity.puml.png
site-images: $(site_path)/static/diagrams/allocation-player-capacity-tracking.puml.png
site-images: $(site_path)/static/diagrams/allocation-player-capacity-list.puml.png
site-images: $(site_path)/static/diagrams/reusing-gameservers.puml.png
site-images: $(site_path)/static/diagrams/high-density-label-lock.puml.png
site-images: $(site_path)/static/diagrams/high-density-counters.puml.png
Expand Down
70 changes: 52 additions & 18 deletions site/content/en/docs/Integration Patterns/player-capacity.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,63 @@ description: >
Find a `GameServer` that has room for a specific number of players.
---

Using this approach, we are able to be able to make an Allocation request that is akin to: "Find me a `GameServer`
that is already allocated, with room for _n_ number of players, and if one is not available, allocate me a `Ready`
`GameServer`".

Common applications of this type of allocation are Lobby servers where players await matchmaking, or a
persistent world server where players connect and disconnect from a large map.

{{% pageinfo color="info" %}}
[Counters and Lists]({{< ref "/docs/Guides/counters-and-lists.md" >}}) will eventually replace the Beta functionality
[Counters and Lists]({{< ref "/docs/Guides/counters-and-lists.md" >}}) will eventually replace the Alpha functionality
of Player Tracking, which will subsequently be removed from Agones.

If you are currently using this Beta feature, we would love for you to test (and ideally migrate to!) this new
If you are currently using this Alpha feature, we would love for you to test (and ideally migrate to!) this new
functionality to Counters and Lists to ensure it meet all your needs.

This document will be updated to utilise Counters and Lists in the near future.
{{% /pageinfo %}}

## Tracking Players Through Lists

{{< beta title="Counters And Lists" gate="CountsAndLists" >}}

<a href="../../../diagrams/allocation-player-capacity-list.puml.png" target="_blank">
<img src="../../../diagrams/allocation-player-capacity-list.puml.png" alt="Player Capacity Allocation Diagram" />
</a>

### Example `GameServerAllocation`

The below allocation will attempt to find an already Allocated `GameServer` from the `Fleet` "simple-game-server" with
room for at least 10, and if it cannot find one, will allocate a Ready one from the same `Fleet`.

```yaml
apiVersion: allocation.agones.dev/v1
kind: GameServerAllocation
spec:
selectors:
- matchLabels:
agones.dev/fleet: simple-game-server
gameServerState: Allocated # check for Allocated first
lists:
players:
minAvailable: 10 # at least 10 players in available capacity
- matchLabels:
agones.dev/fleet: simple-game-server
lists:
players:
minAvailable: 10 # not required, since our GameServers start with empty lists, but a good practice
```
## Player Tracking
{{< alpha
title="Player Tracking and Allocation Player Filter"
gate="PlayerTracking,PlayerAllocationFilter" >}}
Using this approach, we are able to be able to make a request that is akin to: "Find me a `GameServer` that is already
allocated, with room for _n_ number of players, and if one is not available, allocate me a `Ready` `GameServer`".

Common applications of this type of allocation are Lobby servers where players await matchmaking, or a
persistent world server where players connect and disconnect from a large map.

<a href="../../../diagrams/allocation-player-capacity.puml.png" target="_blank">
<img src="../../../diagrams/allocation-player-capacity.puml.png" alt="Player Capacity Allocation Diagram" />
<a href="../../../diagrams/allocation-player-capacity-tracking.puml.png" target="_blank">
<img src="../../../diagrams/allocation-player-capacity-tracking.puml.png" alt="Player Capacity Allocation Diagram" />
</a>
## Example `GameServerAllocation`
### Example `GameServerAllocation`

The below allocation will attempt to find an already Allocated `GameServer` from the `Fleet` "lobby" with room for 10
to 15 players, and if it cannot find one, will allocate a Ready one from the same `Fleet`.
Expand All @@ -51,11 +83,13 @@ spec:
agones.dev/fleet: lobby
```

{{< alert title="Note" color="info">}}
We recommend doing an extra check when players connect to a `GameServer` that there is the expected player capacity
on the `GameServer` as there can be a small delay between a player connecting and it being reported
to Agones.
{{< /alert >}}
## Consistency

Agones, and Kubernetes itself are built as eventually consistent, self-healing systems. To that end, it is worth
noting that there may be minor delays between each of the operations in either of the above flows. For example,
depending on the cluster load, it may take approximately a second for an SDK driven
[list change]({{% ref "/docs/Guides/Client SDKs/_index.md#counters-and-lists" %}}) on a `GameServer` record to be visible to the Agones
allocation system. We recommend building your integrations with Agones with this in mind.

## Next Steps

Expand Down
117 changes: 117 additions & 0 deletions site/static/diagrams/allocation-player-capacity-list.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
@startuml
/'
Copyright 2024 Google LLC All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
'/

'https://plantuml.com/sequence-diagram

actor "Player One" as Player1
actor "Player Two" as Player2
participant Matchmaker
participant Agones
participant "GameServer\nResource" as GameServer
box "Game Server Pod"
participant "Game Server\nProcess" as Binary
participant SDK
end box

activate GameServer

== GameServer Start ==

Agones -> GameServer: GameServer created through\na <i>Fleet</i> configuration
note left
<i>Fleet</i> configuration includes a <i>players</i> List with an initial empty value
and a capacity set to the total number of players that be can be hosted on a <i>GameServer</i>.
end note
activate GameServer
GameServer -> Binary: Agones creates a Pod with the\nconfigured Game Server Container
activate Binary
activate SDK
Binary -> SDK: SDK.WatchGameServer()
note right
Use the SDK Watch function
to watch and react to allocation
and List mutation events
end note

Binary -> SDK: SDK.Ready()
note right
Call <i>Ready()</i> when the
Game Server can take player
connections and is able to
be allocated.
end note
GameServer <-- SDK: Update to <i>Ready</i> State

== No allocated <i>GameServers</i> ==

Player1 -> Matchmaker: Requests a game session
Matchmaker -> Agones: Create: <i>GameServerAllocation</i>
note left
The <i>GameServerAllocation</i> is implemented to
optionally select an already allocated <i>GameServer</i>
with an available capacity under List <i>players</i>
of 1. If one cannot be found, allocate a <i>Ready</i>
<i>GameServer</i> instead.

Since at this stage there are no Allocated <i>GameServer<i>
Agones will allocate a <i>Ready</i> GameServer.
end note
Agones -> GameServer: Finds a <i>Ready</i> <i>GameServer</i>,\nsets it to <i>Allocated</i> State
Matchmaker <-- Agones : <i>GameServerAllocation</i> is returned\nwith <i>GameServer</i> details\nincluding IP and port to connect to.
Player1 <-- Matchmaker : Returns <i>GameServer</i> connection information
Player1 -> Binary : Connects to game server process
Binary -> SDK : SDK.Beta().AppendListValue("players", id)
note left
Process calls <i>AppendListValue(...)</i>
on player client connection.
end note
GameServer <-- SDK : Appends <i>id</i> to <i>status.lists["players"].values</i>

== Allocated <i>GameServers</i> with player(s) on them ==

Player2 -> Matchmaker: Requests a game session
Matchmaker -> Agones: Create: <i>GameServerAllocation</i>
note left
The <i>GameServerAllocation</i> will this time find the
Allocated <i>GameServer</i> with the <i>players</i> List
with available capacity, indicating it has room for
more players.
end note
Agones -> GameServer: Finds the <i>Allocated</i> <i>GameServer</i> where\n<i>length(status["players"].values) < status["rooms"].capacity</i>.
note right
This is the same <i>GameServer</i> that "Player One"
is currently playing on.
end note
Matchmaker <-- Agones: returns <i>Allocated GameServer</i> record
Player2 <-- Matchmaker : Returns <i>GameServer</i> connection information
Player2 -> Binary : Connects to game server process
Binary -> SDK : SDK.Beta().AppendListValue("players", id)
GameServer <-- SDK : Appends <i>id</i> to <i>status.lists["players"].values</i>

alt <i>Player</i> disconnects
Binary -> SDK: SDK.Beta().DeleteListValue("players", id)
SDK --> GameServer: Removes <i>id</i> from <i>status.lists["players"].values</i>
end alt
note right
When a player disconnects,
remove their id from the "players" List,
to increase the available capacity
on this <i>GameServer</i>.
end note


@enduml
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1c27dbb

Please sign in to comment.