@@ -13,34 +13,113 @@ use of resources to run multiple concurrent game sessions from within a single `
13
13
The tradeoff here is that this requires more management on behalf of the integrated game server process and external
14
14
systems, since it works around the common Kubernetes and/or Agones container lifecycle.
15
15
16
- Utilising the new allocation ` gameServerState ` filter as well as the existing ability to edit the
16
+ Here are two different approaches to solving this problem with Agones:
17
+
18
+ ## Session/Room Counters
19
+
20
+ {{< beta title="Counters And Lists" gate="CountsAndLists" >}}
21
+
22
+ Utilising the allocation ` gameServerState ` filter as well as the new ability to add Counter capacity and counts to
23
+ ` GameServer ` records at both [ allocation time] ({{% ref "/docs/Reference/gameserverallocation.md" %}}), and from
24
+ within the game server process, [ via the SDK] [ sdk-counter ] , means Agones is able to atomically track how many sessions
25
+ are available on a given a ` GameServer ` from the list of potentially Ready or Allocated ` GameServers ` when making an
26
+ allocation request.
27
+
28
+ By also using Counters, we can provide Agones the allocation metadata it needs to pack appropriately across the high
29
+ density ` GameServer ` instances as well.
30
+
31
+ <a href =" ../../../diagrams/high-density-counters.puml.png " target =" _blank " >
32
+ <img src =" ../../../diagrams/high-density-counters.puml.png " alt =" High Density Allocation Diagram (Session Counters) " />
33
+ </a >
34
+
35
+ ### Example ` GameServerAllocation `
36
+
37
+ The below ` Allocation ` will first attempt to find a ` GameServer ` from the ` Fleet ` ` simple-game-server ` that is already
38
+ Allocated and also available capacity under the ` rooms ` Counter.
39
+
40
+ If an Allocated ` GameServer ` does not exist with available capacity, then use the next selector to allocate a Ready
41
+ ` GameServer ` from the ` simple-game-server ` ` Fleet ` .
42
+
43
+ Whichever condition is met, once allocation is made against a ` GameServer ` , the ` rooms ` Counter will be incremented by
44
+ one, thereby decrementing the available capacity of the ` room ` Counter on the ` GameServer ` instance. Generally
45
+ speaking, once there is no available capacity on the most full ` GameServer ` , the allocation will prioritise the next
46
+ least full ` GameServer ` to ensure packing across ` GameServer ` instances.
47
+
48
+ It will then be up to the game server process to decrement the ` rooms ` Counter via the SDK when a session comes to end,
49
+ to increase the amount of available capacity within the ` GameServer ` instance.
50
+
51
+ ``` yaml
52
+ apiVersion : allocation.agones.dev/v1
53
+ kind : GameServerAllocation
54
+ spec :
55
+ scheduling : Packed
56
+ priorities :
57
+ - type : Counter
58
+ key : rooms
59
+ order : Ascending # Ensures the "rooms" with the least available capacity (most full rooms) get prioritised.
60
+ selectors :
61
+ # Check if there is an already Allocated GameServer with room for at least one more session.
62
+ - gameServerState : Allocated
63
+ matchLabels :
64
+ agones.dev/fleet : simple-game-server
65
+ counters :
66
+ rooms :
67
+ minAvailable : 1
68
+ # If we can't find an Allocated GameServer, then go get a `Ready` `GameServer`.
69
+ - gameServerState : Ready
70
+ matchLabels :
71
+ agones.dev/fleet : simple-game-server
72
+ counters :
73
+ rooms :
74
+ minAvailable : 1 # not 100% necessary, since our Ready GameServers don't change their count value, but a good practice.
75
+ counters :
76
+ rooms :
77
+ action : Increment
78
+ amount : 1 # Bump up the room count by one on Allocation.
79
+ ` ` `
80
+
81
+ {{% alert title="Note" color="info" %}}
82
+ When using ` Packed` `scheduling`, Counter and List `priorities` are used as a tiebreaker within nodes, to ensure packing
83
+ across the nodes is done as efficiently as possible first, and the packing within each `GameServer` on the node is done
84
+ second.
85
+
86
+ For a `Distributed` `scheduling` implementation, Counter and List `priorities` are the only sorting that occurs across
87
+ the potential set of GameServers that are to be allocated.
88
+ {{% /alert %}}
89
+
90
+ # # GameServer Label Locking
91
+
92
+ Utilising the allocation `gameServerState` filter as well as the existing ability to edit the
17
93
` GameServer` labels at both [allocation time]({{% ref "/docs/Reference/gameserverallocation.md" %}}), and from
18
- within the game server process, [ via the SDK] [ sdk ] ,
94
+ within the game server process, [via the SDK][sdk-label ],
19
95
means Agones is able to atomically remove a `GameServer` from the list of potentially allocatable
20
96
` GameServers` at allocation time, and then return it back into the pool of allocatable `GameServers` if and when the
21
- game server process deems that is has room to host another game session.
97
+ game server process deems that is has room to host another game session.
22
98
23
- <a href =" ../../../diagrams/high-density.puml.png " target =" _blank " >
24
- <img src =" ../../../diagrams/high-density.puml.png " alt =" High Density Allocation Diagram " />
99
+ The downside to this approach is that there is no packing across re-allocated `GameServer` instances, but it is a very
100
+ flexible approach if utilising Counters or Lists is not a viable option.
101
+
102
+ <a href="../../../diagrams/high-density-label-lock.puml.png" target="_blank">
103
+ <img src="../../../diagrams/high-density-label-lock.puml.png" alt="High Density Allocation Diagram (Label Lock)" />
25
104
</a>
26
105
27
106
{{< alert title="Info" color="info">}}
28
107
To watch for Allocation events, there is the initial `GameServer.status.state` change from `Ready` to `Allocated`,
29
108
but it is also useful to know that the value of `GameServer.metadata.annotations["agones.dev/last-allocated"]` will
30
- change as it is set by Agones with each allocation with the current timestamp, regardless of if there
109
+ change as it is set by Agones with each allocation with the current timestamp, regardless of if there
31
110
is a state change or not.
32
111
{{< /alert >}}
33
112
34
- ## Example ` GameServerAllocation `
113
+ # ## Example `GameServerAllocation`
35
114
36
- The below ` Allocation ` will first attempt to find a ` GameServer ` from the ` Fleet ` ` simple-udp ` that is already
115
+ The below `Allocation` will first attempt to find a `GameServer` from the `Fleet` `simple-game-server ` that is already
37
116
Allocated and also has the label `agones.dev/sdk-gs-session-ready` with the value of `true`.
38
117
39
118
The above condition indicates that the matching game server process behind the matched `GameServer` record is able to
40
119
accept another game session at this time.
41
120
42
121
If an Allocated `GameServer` does not exist with the desired labels, then use the next selector to allocate a Ready
43
- ` GameServer ` from the ` simple-udp ` ` Fleet ` .
122
+ ` GameServer` from the `simple-game-server ` `Fleet`.
44
123
45
124
Whichever condition is met, once allocation is made against a `GameServer`, its label of `agones.dev/sdk-gs-session-ready`
46
125
will be set to the value of `false` and it will no longer match the first selector, thereby removing it from any
@@ -56,34 +135,37 @@ kind: GameServerAllocation
56
135
spec:
57
136
selectors:
58
137
- matchLabels:
59
- agones.dev/fleet : simple-udp
138
+ agones.dev/fleet: simple-game-server
60
139
agones.dev/sdk-gs-session-ready: "true" # this is important
61
140
gameServerState: Allocated # new state filter: allocate from Allocated servers
62
141
- matchLabels:
63
- agones.dev/fleet : simple-udp
142
+ agones.dev/fleet: simple-game-server
64
143
gameServerState: Ready # Allocate out of the Ready Pool (which would be default, so backward compatible)
65
144
metadata:
66
145
labels:
67
146
agones.dev/sdk-gs-session-ready: "false" # this removes it from the pool
68
147
` ` `
69
148
70
- {{< alert title="Info" color="info"> }}
149
+ {{% alert title="Info" color="info" % }}
71
150
It's important to note that the labels that the `GameServer` process use to add itself back into the pool of
72
151
allocatable instances, must start with the prefix `agones.dev/sdk-`, since only labels that have this prefix are
73
- available to be [updated from the SDK][sdk] .
74
- {{< /alert > }}
152
+ available to be [updated from the SDK]({{% ref "/docs/Guides/Client SDKs/_index.md#setlabelkey-value" %}}) .
153
+ {{% /alert % }}
75
154
76
155
# # Consistency
77
156
78
- Agones, and Kubernetes itself are built as eventually consistent, self-healing systems. To that end, it is worth
79
- noting that there may be minor delays between each of the operations in the above flow. For example, depending on the
80
- cluster load, it may take up to a second for an [SDK driven label change][sdk] on a `GameServer` record to be
81
- visible to the Agones allocation system. We recommend building your integrations with Agones with this in mind.
157
+ Agones, and Kubernetes itself are built as eventually consistent, self-healing systems. To that end, it is worth
158
+ noting that there may be minor delays between each of the operations in either of the above flows. For example,
159
+ depending on the cluster load, it may take approximately a second for an SDK driven
160
+ [counter change][sdk-counter] or [label change][sdk-label] on a `GameServer` record to be visible to the Agones
161
+ allocation system. We recommend building your integrations with Agones with this in mind.
82
162
83
163
# # Next Steps
84
164
85
- * View the details about [using the SDK][sdk] to set
86
- labels on the `GameServer`.
165
+ * Read the [Counters and Lists]({{< ref "/docs/Guides/counters-and-lists.md" >}}) guide.
166
+ * View the details about [using the SDK]({{% ref "/docs/Guides/Client SDKs/_index.md#setlabelkey-value" %}}) to change
167
+ values on the `GameServer`.
87
168
* Check all the options available on [`GameServerAllocation`]({{% ref "/docs/Reference/gameserverallocation.md" %}}).
88
169
89
- [sdk] : {{% ref "/docs/Guides/Client SDKs/_index.md#setlabelkey-value" %}}
170
+ [sdk-label] : {{% ref "/docs/Guides/Client SDKs/_index.md#setlabelkey-value" %}}
171
+ [sdk-counter] : {{% ref "/docs/Guides/Client SDKs/_index.md#counters-and-lists" %}}
0 commit comments