A natural consequence of the adoption of a micro-services architecture was the rise in the use of messaging infrastructure, sometimes also referred to as an event bus. The principle reason for this is to avoid the temporal coupling that can occur when micro-services are chained together. This coupling can reduce the availability of functionality due to direct and potentially brittle coupling between each service.
A messaging approach allows for services to be de-coupled and more independent, this can lead to an increase in the functionality that can be attached to certain events happening within your system without this causing more and more complication in your codebase.
Unfortunately as with any architectural pattern it isn't all good news, no matter what approach you take to solving a problem its possible for anti-patterns to develop. This article is by no means an argument against messaging patterns, it is simply a guide to the potential anti-patterns that can weaken, or even eradicate, the positive impact this pattern can have on your software.
Dependencies and Leaky Events
Events should not have dependencies between each other, it should be possible to process any individual event in its entirety without having to wait for any other event to be dispatched. This will often require careful consideration to strike a balance between a large event containing a lot of data and one that is too small to be of any practical use.
Events should also encapsulate a clearly defined business process and be easily understandable simply from its name. This also means they should not leak the implementation detail of the system that produced the event.
An example of this kind of leaky event can be seen when they represent CRUD operations being performed on a database or some other storage mechanism. For example an Order Updated event lacks clarity and is simply exposing an operation performed on an underlying data structure. Instead events like Order Placed, Order Dispatched or Order Cancelled have a much clearer business context and are not tied to a data storage mechanism.
Implementing Sequences
Most messaging system are asynchronous in nature and therefore guaranteeing the order of delivery and processing can be an expensive and complex process.
Many processes often do represent a series of events so it isn't always easy to avoid these sequencing problems but in these situations the consequence of event processing happening out of order needs to be considered and every effort taken to avoid these situations.
Returning to our previous example tying payment and dispatch to an order updated event opens up the possibility of a problem if an order is dispatched before payment has been successfully taken. However triggering the shipping of an order from a Payment Received event avoids this situation.
As with our previous point accurately modelling our events on the business domain, and not its implementation, leads to an easier to understand and more robust system.
Commands in Disguise
In a micro-services architecture services will often be required to interact with each other. Traditionally this will be via a REST interface but once a messaging infrastructure is introduced it can be tempting to implement similar mechanisms using events.
When a service publishes an event it should be to impart the information of a business process having taken place to the rest of the system. The service should have no knowledge or requirements around who will consume the event and what action they will take.
An indicator that this approach is being broken is when you can identify services that publish an event and subsequently wait to receive an event in return. When this happens the services involved have lost independency and have become coupled. This isn't to say that the dependency is wrong or should be avoided but it should be made more explicit and clear via the use of REST.
This also prevents another source of leaky events where a service is forced to publish many events relating to error scenarios because other services are waiting on the outcome.
Messaging patterns can enrich micro-services in a way that makes them undeniably part of an effective micro-services implementation. But they aren't a suitable way to interconnect services in all situations, when used in these situations they can actively degrade the architecture of the system. When working in a micro-services architecture develop a play book for when to use REST and when to use events, take time to carefully construct events around business processes making every effort to avoid complex scenarios around there processing.
No comments:
Post a Comment