The Idea: What the heck does the term MicroPlode mean and what is this all about?
The Architecture: A first sketch on a Microservice Architecture for the playground project.
Some Technical Stuff: Well, here comes some technical stuff, yeah :-).
Conclusion & Outlook Reflecting on the thoughts and results so far and what are the ideas for proceeding with this project.
Microservices! For sure a term you can hardly dodge in the IT world these days. First time I heard about it I thought something along those lines of “nice idea, sounds really interesting”. But pretty quickly daily routine in the project took over again and washed me away from it. Then – quite recently – an idea materialised in my brain while I was reading more and more about it: Instead of only reading about it in theory, let’s do this in practice using a small – but somewhat meaningful – “playground project”. And puh, there are tons of blog posts out there to read on the topic. For example lately I was reading through this more skeptical blog post on DZone including roughly 100 comments discussion. It was really interesting as it was going from technical aspects to social aspects and back again. I really gained some insights from that. In the end this encouraged me in my idea to try the whole thing out in practice. And thanks to our company’s great working model that allows us to spend a decent amount of time exploring new technologies, I have the opportunity to start this little experiment here and now :-).
The playground project will be a game based on an old gaming idea.
Unfortunately I forgot the name of the original game, so if someone recognises the original game it would be great to leave me a comment. Thanks to a colleague the name of the original game is no longer a mystery :-). We will do it here with a slightly different playing field that is more like a chess board to simplify things a bit.
The game is played in turns with two or more players on a playing field that for the beginning is assumed to have a fixed size of 10×10 fields. When starting a new game, all fields are unoccupied. Players can occupy one empty field when it is their turn or they can increase the load on one field already owned by them.
- If a field is empty, the field will be occupied by that player with a load of one.
- If a field is already occupied by that player the load on that field will be increased by one.
- Players can only access empty fields or those already occupied by them.
- If after increasing the load a field has a load that is higher than the amount of direct neighbouring fields it explodes and gives a load to each of those neighbouring fields.
- A field getting a load this way is changing ownership to the one of the exploded field. A load already on such a field is increased by one no matter by whom that field was owned previously.
- A field getting a load this way might explode itself again leading to nice chain reactions.
- If after the first round a player does not own any field on its turn that player lost the game.
It is really fun playing and I implemented this already a long time back using Java with SWT. Unfortunately I lost all the sources. So this is a nice goal to implement and at the same time I know it is possible in a reasonable amount of time. And it is fun implementing computer players for this, but that is a later story.
The version of this game I once implemented was called Explode, thus the name MicroPlode for this project :-).
This is really the beginning of a journey with an open end. I have implemented nothing so far and I only have a few ideas regarding the technologies I would like to use. Furthermore it might turn out it does not make sense at all to implement this game using Microservice architecture, even though I thought a little bit about this in advance. I also discussed it a bit with a colleague who has more experiences in this area. Anyway, as with every project I am also starting optimistic into this one :-).
Architecture, yeah! I always involuntarily cringe a bit when writing the term “Architecture” in a blog post as from my personal observation this term is a bit overused these days. But talking about Microservices and how to model them seems to well deserve that term :-).
Ok, I have read and heard that finding the borderlines between the individual services is one of the hardest parts in a Microservices Architecture. As always with examples it is easier than in real-life projects, but still this is the result of some hard thinking and discussion :-). I see three building blocks for the game that will be implemented as Microservices and communicate via messaging. Let’s sketch them shortly before we go into more details.
- GameService – Administration of games and players, keeps track of scores and knows whos move it is. It also detects if a player looses the game and if the game is over if there is only one player left in the game.
- PlayerService – Calculates moves based on the current game state for computer players. Allows human players to make a move.
- PlayingFieldService – This service knows the playing field or one could even say it is the playing field :-). It initializes the board and changes the board state depending on moves that have been made by players. It is furthermore capable of executing explosions when needed.
Right now my brain – used to monolithic applications – is already whispering: Hey, the GameService and the PlayerService are for sure sharing some information on players. And think of the computer player, that one needs to know everything about the playing field at least as good as the PlayingFieldService. – Well, I understood that duplicating data to a certain degree is one of the tradeoffs in a Microservices Architecture, so let’s wait and see. By the way, nobody told me so far that there is the danger of becoming schizophrenic when working with Microservices :-).
Technical aspects aside, those three Microservices need to exchange information of course. Such a game is now of course nothing that has a lot of asynchronous things to do. It is someone’s turn, a move must be calculated and the change in game state – that move triggers – must be tracked. Nevertheless we will use messaging for communication here for the sake of learning things. Let’s see what it might be good for in the end. The following figure is depicting the communication between the planned services:
As in every project, this is work-in-progress, but for the time being this is hopefully good enough to start implementation. Let’s take a look at the events and what actions they should trigger in the different services.
And again some thoughs are coming up I would probably not have in a monolithic approach. Is there an order I need to start the services in later on? (Though I know this must not be the case.) Then do I need to acknowledge all or certain events? Probably this should be solved technically by the platform used for sending/receiving events.
At the same time I get a positive feeling of clearly divided responsibilities. Even though all of the services need to work with the board state, they all do different things with it and thus I will be really forced (in a positive way) to split those responsibilities. Of course this will come at the cost of needing some kind of board representation in different services. A really interesting experiment :-).
The GameService has to know which players are available. Therefore we need the registration-event. This also leads to a somewhat open issue that is spooking around in my mind, namely that we will probably not have only one PlayerService, but multiple instances for different computer players and human players. Getting more concrete on that will be done at a later point in time, though.
Then the GameService must also know that the PlayingFieldService is ready to work using the board-ready-event.
If a new game is started, this must be propagated to the PlayerService(s) 😉 and the PlayingFieldService using the new-game-event. Also the PlayerService must be informed whose turn it is to either ask a move from a human player to calculate a move by a computer player. This notification is happening with the new-round-event. (If we will have several instances of the PlayerService this event must be processed only by one instance of course.)
Then the PlayingFieldService gets notified on a move to execute using the move-event. In turn it sends board-changed-events to the PlayerService and the GameService. The GameService needs to evaluate if a player has lost the game and if the game is over. Furthermore this indicates to send the next new-round-event as it shows that the current turn is finished. The PlayerService needs this information to be able to calculate the next move.
I would say that’s it for the time being and it is the foundation to start some implementation on with one small remark still: I left out any UI-related things on purpose so far. The UI of course will need to display information from the PlayingFieldService and the GameService. As I am confident that the architecture is flexible enough to implement this part of the application later, I leave it out happily for the time being.
Some Technical Stuff
First thing to solve here is probably setting up a messaging platform. Luckily a colleague of mine was pointing me to Kafka. Having a Windows PC can sometimes be a bit problematic with the tooling, but a first quick evaluation looks quite promising.
I simply downloaded the Kafka binary distribution and followed the quickstart documentation, but transferring the commands to those needed under Windows.
Therefore I first started the zookeeper-server as follows :
> cd c:/projects/microplode/kafka/bin/windows > zookeeper-server-start.bat ../../config/zookeeper.properties
Afterwards the kafka-server can be started:
> cd c:/projects/microplode/kafka/bin/windows > kafka-server-start.bat ../../config/server.properties
Now we can create a new topic and show the list of topics as follows:
> cd c:/projects/microplode/kafka/bin/windows > kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic microplode > > kafka-topics.bat --list --zookeeper localhost:2181 microplode
Finally messages can be sent and received using the following commands:
> cd c:/projects/microplode/kafka/bin/windows > kafka-console-producer.bat --broker-list localhost:2181 --topic microplode This is a test message > > kafka-console-consumer.bat --zookeeper localhost:2181 --topic microplode --from-beginning This is a test message Consumed 1 messages
This was working really well, BUT: At this point I am like a dummy-user for this whole messaging-thing, which is OK for a small playground project. It will of course get interesting if the first problems show up and it also shows that in a real project the team would probably need some quite good experience with the messaging infrastructure already. Especially for things like replication and partitions I have a vague idea at the moment, but that’s about it. OK, it can only get better in the course of this experiment :-).
So much for the technical stuff for today.
Conclusion & Outlook
A dear colleague of mine was saying lately that blog posts should be short, so that people will read them. So lucky me if you are still on board here :-).
Having implemented monolithic applications like forever my first impression with this approach is that it helps me dividing the problem more easily. It is often tempting to quickly start thinking in object-oriented terms and interfaces and common libraries and all that stuff. This is not happening that much here, but instead the focus is more on responsibilities (even if the data might be the same) and actions that must be performed.
But as already stated earlier there are also some doubts especially regarding the duplication of data and the need to process that same data in different services. Furthermore I am not 100 % convinced yet that the messaging-driven way of communication is really the best here as things need to happen in a rather strict order. At the same time, though, these aspects are one of the most interesting parts of this experiment to see how that works out – or does not work out – in the end.
So next time (hopefully this means next week) the implementation for the first service will be started using Spring Boot. Looking forward to it :-).
Update 2015-11-30: Read on in Part II: MicroPlode – Implementing the first Microservice