This will be the first on a series of posts on software architecture. I will start by talking, without getting into too much detail, about some of the key decisions when it comes to communication between different top level components of an application, say, app servers or microservices. Later on I will discuss other aspects of a solution, such as:
- High level communication
- Data storage and access
- Maintaining state
- Authentication and authorization
- Decoupling components
And maybe a few more! I won’t be saying what is best or worst, just mentioning some decisive factors. As always, this is meant as an open discussion, so feel free to join and have your saying at any time!
Web Service vs Service Bus
In the early days, all we had was web services (or web APIs, as they are also called). First, it was SOAP: the idea was that a web service that exposed a SOAP protocol endpoint would implement a business procedure, so we would send it a document containing all that it needed and somehow it would get the job done. It was even possible, through the help of the WS-* protocols and specifications, to create a distributed transaction and have multiple SOAP web services enlisted in it so that we could call them all inside the same transaction. SOAP messages were all XML, and tended to be somewhat complex.
Then came REST, essentially due to the complexity of SOAP, the need for specific software – distributed transactions require its own software, like Microsoft DTC running on Windows - and its associated specs. REST is not a protocol or a specification, it’s really an architectural style. When SOAP dictates the usage of HTTP POST and a specific XML message format, REST does not, instead, it leverages on the HTTP verbs – GET, POST, PUT, DELETE, PATCH – and the URLs (e.g., /Order, /Product, etc) and trusts that we know what we are doing. No message format is mandatory, too, but people usually use JSON or XML just for the convenience.
Both SOAP and REST were nice, because they allowed interoperability: a service implemented in any technology could talk to a client implemented in any other technology, just through HTTP. They just both had to know the message to be exchanged.
But they had some drawbacks. Both SOAP and REST were essentially client-server, point-to-point, message passing, request/reply style, synchronous APIs, and the modern world requires a bit more. Eventually, other technologies came along, such as gRPC. gRPC is an open-source RPC framework by Google which has bindings for all the languages that you can possibly think of and can complement some of the shortcomings of both REST and SOAP: remote method calls, a binary format that can potentially reduce latency by making messages shorter, uni or bidirectional streaming and truly asynchronous communication. gRPC uses contracts to define the messages and its operations.
There are, however, some problems that are common to all these solutions:
- There is a single point of failure: if the server hosting the REST or gRPC service goes down, the whole system goes down!
- Not easy to ensure required message delivery semantics - At Least Once, Exactly Once, At Most Once -, because the network is unreliable and we need to implement the support ourselves!
Enter the Service Bus!
So, what is a Service Bus, or Enterprise Service Bus (ESB)? Essentially, you drop a message to the bus and someone picks it up and processes it, asynchronously. There is no client and no server, any system can talk to any other system, through the bus. There is no immediate reply, any reply will also go through the bus. It’s a whole different way of doing things.
Now, there are essentially two main families when it comes to communicating: Messages and Events.
A message has a format, possibly a version, and is sent to a group, sometimes called a topic. Common usages are message queues: some system posts a message to a specific topic of a message queue and interested parties will read from it. Once a message is read (consumed) from a queue (a single time), it will be removed from that queue. Most of the time the consumers are dormant, and still waiting for a message for arrive.
Events are small messages produced by apps as response to internal state changes. They are signaled system-wide and listeners attached to the source of events can react to them, even by publishing more events. A log of all events is kept in the system. Parties can subscribe to multiple sources, be interested in multiple events, and publish their own events too. Playing all the occurred events in the system from a fresh installation should yield the same results, meaning, should leave the system on the same, consistent, state.
Comparing Web Services and Service Bus
We’ve seen some of the problems with web services (SOAP, REST, gRPC or other), now how can a Service Bus help?
Well, it’s not so much about the address finding – the address for the message queue or broker still needs to be known – but its the dependability: messages sent to a Service Bus are durable, meaning, they can withstand a service going down. And because the client does not talk directly to a server – nor does that concept even exist here – a message/event is sent to the bus and eventually, when one interested party wakes up, it will pick it up and process it. And there can be multiple parties connected asynchronously to the same bus. And, yes, modern Service Buses like Kafka are capable of implementing all of the message delivery semantics, including Exactly Once. Of course, if this is really what we need or not, is matter for a different conversation. Even though its true that you can have a cluster/load balancer for your web service, it’s not quite the same thing as to having multiple consumers waiting to process events/messages from a bus where you have certain delivery guarantees.
This decision is a hard one and one that will greatly influence how your system is implemented, behaves and evolves. Choose wisely, including a proper assessment of the tools available out there, their support and community. You should probably go with a Service Bus as it has significant advantages over web services but that doesn’t mean that web services don’t have their place – of course they do! In a modern, complex system, they all have their place.