In this post, I’ll be going over how I achieved graceful shutdown of my game servers with my own services; the Chungustrator aka orchestrator and Chungusway aka the gateway between the orchestrator and game server. I also did some fiddling with the game’s internals.
If you don’t know what these chunguses (yes that’s what I’m calling these services now) are or how they fit into the grand scheme of things, I suggest reading the second blog that goes over the functionality of both chunguses!
The prerequisite idea from the last blog is the utility of the gateway. So far, I’ve only used it unidirectionally, gRPC to ENet, to send unique verification codes to the game server for users to validate against. In order to achieve a graceful shutdown of the game server, the intuition is to make the communication bidirectional, translating ENet to gRPC, notifying the orchestrator to shutdown the game server once the match is done.

ENet Host
The game server’s main event loop has an authoritative ENet Host that ingests packets from game clients, such as people shooting, moving, and chatting—specifically for gameplay. At the same time, it’s used to broadcast all these events to other clients too. I thought it’d be messy, design wise, to have the same ENet host that’s responsible for gameplay packets, to send chungus packets too. So, I decided to create another ENet host specifically for the chunguses.

In short, on a match end event, queue a packet flagged for shutdown including the game server’s container ID, and let the loop handle the timing of the delivery.
Speaking of flags.
Processing Packets
I wasn’t sure how to go about processing packets in an organized way, this was my first time doing this after all. I knew in the future that the gateway was going to consume many other types of packets. I looked into how Cube 2 does it, and it’s a simple and direct protocol: FLAG payload_x. Where the flag specifies the type of event to tell the consumer how to parse it according to the flag. It’s now the protocol for my ENet packets.

System
I didn’t have to change much, other than to make the gRPC connection between the Chungustrator and Chungusway bidirectional.

Conclusion, What’s Next
Well, it works! This was something that I was eager about, so I’m glad I took time to fully understand the solution, given what I have. This opens up some doors that I’d love to get into such as grabbing player stats at the end of the game or even in real time!
As mentioned previously, I currently have a middleman service that grabs data from the game server, which is fine. The issue arises when the game server has to be explicit to the middleman to do so. It’s like asking someone to search something up for you when you can just do it yourself! I think it’s okay, but not okay for scaling towards real time statistics. To me, it makes more sense for the game server to have full control of how its own data is distributed.
Here’s a quick demo:
Thanks for reading!
Here’s the Twitter thread for further discussion. Project’s Github