1 comment

[ 4.5 ms ] story [ 9.6 ms ] thread
Mats is a Java library that makes it simple to code asynchronous, stateless (or stateful, depending on your point of view), multi-stage, messaging-based services. Mats Endpoints immediately provide all the benefits you get from a fully asynchronous messaging-based architecture, while being almost as simple to code as blocking, synchronous JSON-over-HTTP endpoints.

This code has been running in production for multiple years as the inter-service communication layer for a financial system consisting of >40 services and several hundred Mats Endpoints, processing several million Request/Reply messages per day.

Since I got interested in distributed computing early in my career, I've had a fundamental dislike of how multi-service systems connected by synchronous communication behaves in face of pretty much every kind of problem. While finding the concepts both in SEDA, and elements of the Actors model, very interesting wrt. dividing up a process in multiple steps, using some form of queues to bind them together, where you effectively get a buzzing network of "working entities" that asynchronously communicate with each other via messages, they are still mostly handling single-service problems.

I eventually realized that a proper messaging based architecture, typically using an external message broker, would be the proper solution to get both high availability, scalability, transactionality and hence fault tolerance. So why wasn't messaging used much more? Why is it that most developers when faced with inter-service communication needs, reach for Something-over-HTTP when it obviously is way worse than messaging?

After having plowed through Enterprise Integration Patterns, and read half the internet looking for simple solutions, I realized that the main issue is that it is simply much more complex to code a multi-service architecture using messaging. You loose the simplicity of coding a "straight down" service method, where you synchronously call out to other services and compose your service as if remote procedure calls are just local method invocations. You also loose the composability that a bunch of RESTish services give, since a set of messaging-based consumer-and-producer stages which constitute a service process are often bespoke to that particular process, where it typically isn't possible to easily reuse a part of such a process from a new service.

We were heading into a quite large project involving multiple integrations and domains, and were going for a "microservice" architecture - and with the insights above, I set out to create a way for making messaging-based services as simple to code as classical synchronous HTTP calls. While there are lots of discussion about lots of things among our developers, there aren't many calls for going back to HTTP.