Would anyone explain this concept in technical terms, and metaphors? I need to be sure my mental model of the design is accurate.
Also, how are messages routed to the individual microservices? The author says that each microservice receives a note, and if the note tells it to do something it's capable of doing, it returns a result. So my first instinct is to assume that every message is multicasted to every microservice, and as long as you're careful that no two microservices respond to the same type of message, you'll always get exactly one result. (By "multicast" I just mean "every microservice sees every message and has the opportunity to respond to it," not literal UDP multicasting. This could be accomplished e.g. by sticking each message into a Redis list, which every microservice reads in its entirety. That would also give you a nice deterministic replay log for debugging purposes.)
I'm also guessing that when a microservice generates a result, it returns that result by e.g. stuffing it into a central Redis server, which is being polled by some other part of the architecture which is waiting for the result.
EDIT: Sorry, I meant, does the above design sound reasonable? What are some hidden gotchas? I just came up with it off the top of my head, so it probably isn't great.
Th concept of microservices has actually been around for a long time, just under a different guise - see Erlang and it's implementation of concept of the actor model and immutable state. Or the original unix neckbeards' conception of chainable console commands (sed, awk, grep etc.) - small highly specialised commands that do one thing exceptionally well with standardised input and output.
Microservice communication will usually work through a message broker such as RabbitMQ or IronMQ - these allow for lightweight routing of messages through subscribed queues, each microservice will listen to an exchange (which has it's own routing rules) which will either round-robin or broadcast to the queues that are attached to it.
In a nutshell, a microservice would set up it's input queues (lashed to exchanges) and it's output queues (pushing to exchanges) and react to incoming messages.
Messages are pushed to specific exchanges by the microservices creating them, they don't care where they go or what happens once they leave, because once they are in the pipe, they are the next service's problem.
You'd want to avoid SPOF such as a Redis instance being polled (the broker deals with that) though you may use it to keep some state information for your various microservices (in case they need to be restarted for example), though ideally, everything should be stateless.
The big problem with microservice architecture is that you potentially receive messages out-of-order, or that events happen across your messaging network in different and unexpected orders, so you need to develop defensively against many different situations if you final output requires a combination of states.
There's actually a whole pattern-based approach to this which is quite well documented in a book called Enterprise Integration Patterns - though it mainly deals with the idea of the Enterprise Service Bus, the patterns should hold true for a microservice architecture.
that's not defined by the term, and is left up to you to decide. All it requires is a lightweight interface, often http.
This is basically where the complex programming will be in these systems, understanding all of the various ways to route messages and where and how to deploy them effectively.
Seneca.js has support for redis, kafka, and so many others.
Next post: Microservice Architectures—"what is needed to create an architecture composed of Microservices"
Hmm, well, I eagerly await the next post.
It seems like what's needed is a concrete, simple tutorial on coding and deploying a microservice infrastructure. That'd demonstrate that this design is practical and, importantly, would reveal any pain points or cornercases that the design is susceptible to.
One pain point is that if a microservice goes down, any messages that were in the process of being handled may be dropped. So there has to be a way to ensure that every message eventually returns exactly one result, and that messages are never accidentally dropped due to microservice crashes.
Actually if you set you message broker up and message handling up properly, you can get your microservice to only acknowledge receipt once it's finished processing and output it's result. If it crashes in the process, the queue would try to redeliver the message once the next service comes on-line. It's built into AMQP as a standard.
There is very little difference (read: almost none) between a single thread of control transferring between objects and synchronous messages and associated return messages flowing between independent "microservices", providing the "microservices" aren't busy when not acting on a message or when waiting for the return value immediately after having sent a message.
In so far as things are easier to test in isolation, it'll be due to the more dynamically typed nature of message passing over and above traditional method calls.
"Microservices", or actors or whatever you want to call them, are more justified when you have concurrency inherent in your problem and you want to avoid the trouble threads create.
You seem to have fallen off the front page really fast - I suspect the all caps got you binned - excellent article by the way.
I am working on a similar blog / articles for a similar implementation - would be interested in sharing war stories - email is in the profile if you are interested
(I was not planning any monkey analogies though :-)
Hmm, the post was completely buried. I'd guess it was an accidental false positive due to the all caps title looking spammy, or a voting ring was detected. The article itself was pretty good.
Also, how are messages routed to the individual microservices? The author says that each microservice receives a note, and if the note tells it to do something it's capable of doing, it returns a result. So my first instinct is to assume that every message is multicasted to every microservice, and as long as you're careful that no two microservices respond to the same type of message, you'll always get exactly one result. (By "multicast" I just mean "every microservice sees every message and has the opportunity to respond to it," not literal UDP multicasting. This could be accomplished e.g. by sticking each message into a Redis list, which every microservice reads in its entirety. That would also give you a nice deterministic replay log for debugging purposes.)
I'm also guessing that when a microservice generates a result, it returns that result by e.g. stuffing it into a central Redis server, which is being polled by some other part of the architecture which is waiting for the result.
EDIT: Sorry, I meant, does the above design sound reasonable? What are some hidden gotchas? I just came up with it off the top of my head, so it probably isn't great.