Architecture Guide

Architecture Guide

Architecture Guide

This guide is meant to give you instructions and an overview of our distributed system. As it is a challenge to properly design and implement distributed systems we are going to dive into the architecture step by step. The key point of this guide is just to document design decisions in a way it is understandable, detailed References can be found in the Reference Documentation.

Level 1: The BlackBox Perspective

On the most abstract perspective we will just take a look at our Architecture as a Black Box. Here we will take a look at our Microservice Dungeon just a distinct and isolated component. The Dungeon itself performs all the game mechanics necessary for the game. Therefore this is the place where all our “Core Services” live and we will often refer to it in this way. But we do also have various applications that live conceptually outside the Dungeon. For example we might have a UI that shows the current state of the game or other clients. But most imporantly, we also have Players that do play our game.

Level 1

Level 2: The Player Perspective

This is the point where we will look at the players perspective as it plays a special role in our architecture. Conceptually all Players are also part of the Game, but are in a more general way Clients of our Dungeon. All players interact with a central component of our Dungeon, which is reachable from the outside. This is the so called “Game” service. The trick and conceptual model here is, that the game service will not answer directly (synchronous) with a proper response. Instead, the Game service will collect the requests, validates them, and then dispatches them internally in our Dungeon. So the Game service is the Gateway for players to the game. If the request has been dispatched and internally the Dungeon has processed it, a response will be sent asynchronously into a message queue that belong solely to one player.

Level 2

Level 3: The Service Overview

Now we can take a look at our Dungeon’s internal structure. This is the place where our “Core Services” are located. However, another central component here is our Message Broker Apache Kafka. The message broker is a central instance in our services here as the target here is that all our internal communication happens asynchrously. The internal structure can be referenced to as an Event-driven architecture. However, for our architecture overview you need to understand that all our core services communicate between each other by leveraging Kafka as our message broker and that this broker is not available from the outside.

Level 3

Level 4: The Integration

Now that we know that services mainly communicate by using Kafka and is located inside our Dungeon and that the Players are located outside of our Dungeon, there is still one part missing. How do the Players receive their messages? This is done by introducing a second message broker that is accessible from outside the Dungeon. We are using RabbitMQ for our purposes here and as we already know, each player has its own message queue here. Specific Messages from Kafka will be transferred to RabbitMQ and from there being routed/distributed into each players queue.

Level 4

Level 5: The Overall Perspective

Now everything combined looks like the following, but each level should give you the insights to understand the architecture. We maintain a Miroboard with the overall architecture picture. The picture below is a current excerpt, but concept-wise it should not be outdated unless we change something.

Level 5

FAQ

Why the second message broker?

In the past we had a lot of troubles with services hiding their operations (called “obfuscation”) to not let anything leak to a player. As a result there was an overly complicated communication between the services and players. Therefore, we decided that it is definetly a subject to change. On of the crucial points in Event-driven architectures is, that events are the source of truth and should never hide anything, they should instead replicate the change of a given subject. So we had several subjects to choose from:

  1. Make everything public by default
  2. Encrypt Messages
  3. Introduce a second “public” message broker with routing capabilities

We decided to go with option 3.

Why RabbitMQ?

RabbitMQ has been chosen because it supports the AMQP protocol which enables us to route messages and leveraging point-to-point communication. This is increadibly hard to achieve with Kafka as it is built for publish/subscribe. RabbitMQ also is a very flexible, mature and broadly-supported message broker and therefore there are plenty of libraries, tools and resources.

Last modified December 14, 2023: fixes #36 (043e447)