Of Monkeys and Microservices: Introduction 03 April 2014

This is the first in a series documenting the process of building out an example application for the Seneca.js framework, which is built around the concept of microservices. This post is more about the theory behind microservices though, to lay the groundwork for future posts as I embark on this journey.

NearForm is paying for the development work, but blogging about it is all me.

The Parable of the Programmable Primate

I’m starting here because I think it’s probably going to be easier if everybody knows
what kind of article this is going to be upfront.

It is helpful to think of your application as a monkey...

Your application is a monkey that you have trained to take a note from you, and then perform whatever actions are required to produce the results you asked for on the note

When it has finished reading the note: it starts skittering around the factory floor, running in no discernible pattern, dashing between a random subset of these bespoke manafacturing behemoths on display in front of you.

Once it stops flipping levers and feeding industrial offal into the various machines, it comes back to you and gives you (hopefully) the result you requested.

If it doesn’t get everything perfectly right, it might lose a limb on the belt sander, or set off a catastrophic factory fire.

The monkey might be cleverer than most, but it’s still just a monkey. It doesn’t matter how well you dress it, it is still always just going to stay a monkey.

The monkey can never be smarter than the one who trained him, so if you didn’t warn it about putting ball bearings in the industrial microwaves… that’s your fault. If you didn’t tell him not to hand out the keys to your bitcoin vault when asked? That’s also your fault.

I think my distaste for needless complexity is nothing more than the realization that suspending a tightrope over a pit of alligators between the industrial lathes and the smeltery might look cool, but you can never be sure your monkey isn't going to need to drag a crate of sousaphones across it.

How do you train a better monkey?

When your monkey inevitably dies in a gruesome industrial accident, you are going to need to debug it by digging around in it’s entrails or cloning a new one and following it around carefully on the factory floor to see where it went wrong so you can train it how to do the right thing. You might even write some tests to include in future monkey training regimens.

You want to scale up your output? Sure, just build more factories with yet more monkeys. Redundancy is the same thing, but you just leave a few spare factories and monkeys lying around for when the others explode.

What about threads? There is no reason you can’t have more than one monkey per factory, you just have to be careful to orchestrate it in such a way that they never run into each other or get into fights for the same 2x4 from the wood pile.

Microservices are a humane alternative

Microservices are a relatively new and not widely known approach to designing systems in an incredibly distributed fashion. I say “relatively new”, but to put this into context, there isn’t even a wikipedia entry for the term yet.

What they come down to though, is the following :

Why don't we just give each machine it's own monkey?

Every monkey would just get a note, with whatever resources it needed,
that tells it to do exactly one thing.

If it is able, it does that one thing it knows how to do,
and then it will return the result.

That is the sum total of the expectations we make of the monkey.

And also, no matter how you slice it, training a monkey to do only one thing with one known set of inputs, is much much simpler and easier. Just about every monkey trainer out today should be able to do it with their eyes closed, and only nominal amounts of facial scarring.

Benefits of a Many-Monkey Maelstrom

Apart from just allowing us monkey trainers to sleep easier, with the knowledge that we are causing less senseless carnage, there are many benefits to this approach as well.

Scalability

Although not a requirement, systems designed this way are inherently distributable and parallelizable, since all of the monkeys only need a message and the required resources, it doesn’t matter if they are in the same factory, or hundreds of factories.

That alone makes them easier to scale, but let’s say you notice that it’s taking your monkey too long to paint things? How do you scale that? Easy, you just clone some more monkeys and give them paint brushes.

Because of their very nature, they are also easier to build redundant systems with because you can switch out individual monkeys/machines on the fly without bringing the whole factory to a halt.

You can even upgrade parts of your system without any downtime, and with the right metrics and tooling can even automatically rollback if any errors occur.

Simplicity

Read my post on a vocabulary to describe software complexity for the exact meanings of the terms simple, easy, complex, hard, complect and simplify as used in this context.

My favorite benefit is probably the focus on simplicity, that results in microservices getting down to less than 100 lines of code. The resulting code is often so simple, that many practitioners have found that they no longer need unit tests!

It’s just fundamentally simpler, and therefore easier to debug a system that has been built on these principles. They make sense for the same reasons that people have realized that functional programming really makes sense.

This also allows you to more easily coordinate projects, because each developer or team only has a very specific set of requirements and can work on these completely independently.

It’s also truly independent of the implementation language, because we don’t care if there’s a capuchin monkey or an orangutang pulling levers behind the scenes. It just doesn’t matter to us.

Is this just SOA by another name?

Service-oriented architecture (or SOA) does have very similar goals, but through nature or nurture, SOA has evolved in a direction that would be more accurately described as segmenting responsibilities through specialization.

In the context of this article, SOA would be like building a factory to house all your woodworking equipment, and forcing everything that involves wood in some way to pass through this factory. That’s still a valid approach, but it’s also not nearly as granular as microservices would suggest.

I think that the desire and need to build systems this way has been with us for a long time, but I think the environment this latest iteration is evolving in is going to allow us to get closer to some “platonic ideal” for distributed systems than before.

SOA is from an era before the advent of DevOps and the Cloud, and we have become a lot more efficient at cloning monkeys and propping up prefab factories in that time.

If only things were really that easy

Theories are wonderful things, but things often fall apart when it comes to putting them to practical use. Even if microservices seem attractive now, there are some really deep undercurrents of complexity flowing through this problem space.

What do we gain in net-simplicity?

Hopefully the most obvious one, is that we are really just moving problem complexity around by relying on our ability to route messages efficiently.

Message Queues and Service Buses are very complex factories with highly specialized monkeys all of their own, and there is a lot of domain knowledge that a web developer such as myself will have to pick up to truly be able to hit their stride.

The Fallacies of Distributed Computing still apply, and there will probably be some very difficult life lessons learnt the very hard way, until more people come to grips with them.

How applicable is all of this to the web?

I’m actually am not sure that microservices will be practical on the front-end, because a lot of the problems you face there seem almost antithetical to what they attempt to solve.

For instance, the DOM is like the shared-state that other shared-states tell their .children scary bedtime stories of, and if I were to imagine the browser environment as a factory, it looks like something out of the minds of HR Giger and the villains in Saw.

I’m not sure this approach can really map cleanly onto REST either, but I am starting to suspect that it might become a secret ingredient in the ‘real-time web’ recipe.

So bleeding edge it hurts

What I find fascinating about them, is that they currently only exist as a form of tribal knowledge, which has been evolving out of hard-earned lessons by engineers with decades of experience building really complex enterprise level systems.

Many of the “seminal” writings on microservices, were only published in the last 3 weeks, for instance. They also have a severe case of “wow, these things are awesome. go watch this hour long presentation so I can talk to you about them”.

To combat this last point I will be publishing a field guide to microservices soon. You can also follow me on twitter, where I will be posting more links as I find them.