EDA and Microservices – Meant for Each Other

We’re living in a new age of software development, a cloud-native application age. Applications built for cloud delivery must be highly transportable, very loosely coupled, highly resilient, and extremely responsive. That’s a lot to ask for. Comparing today’s development environment to what came before will help to explain how all of this has been accomplished.

In the Beginning, There Was the Monolith

Anyone who has been developing for more than a few years remembers how applications used to be developed, and still are in some corners, most of a given application was written as a single block of code. Every function, every Boolean option, every repetitive or iterative process, every service the application called for was contained within that code.

The flow of the code began at the beginning and proceeded on down, executing each command within each service in sequence until a decision-point was encountered. Perhaps a specific variable needed to be tested to determine where to proceed next. Perhaps a user needed to enter a selection or response before processing could continue. Communication between each of the services, processes, functions, subroutines, and libraries was inherent in the processing of the code.

A neatly organized, complete package. Not only was that an advantage, it was also a critical disadvantage. In a complete, monolithic application like this were anything to go wrong anywhere within the code, the entire application would completely come down. Program error. Critical error. Fatal error. Not pleasant, and often not easily resolved.

 

 

Solution! Just Add Granularity with a Side of Independence

If a flaw occurring in any service could bring down the entire application, the logical solution would be to isolate each service by running it separately and independently. A failure in any service would only bring that process down, not the entire application, which would keep running until the failed service was re-instantiated and became available.

This thinking, which actually began decades ago, led to the development of microservices, small services that interact with other services to form and run an application. To increase the isolation of each service, it would run in its own process in a container that included the code for the service, its configuration, all dependencies, libraries, and other resources required to run the code. Containerized services can be individually tested and are deployed as a containerized image instance to the host OS.

There are several significant advantages to creating applications as an assembly of independent containerized microservices.

  • Since they are each executed independently each can contain different code with differing dependencies created on diverse platforms.
  • They can be deployed across varying environments with no modification.
  • Running directly on the OS, containers have a much smaller footprint than VM images.
  • Scaling out is easily achieved by creating new containers for various tasks. Instantiation of a new image, the process for creating containers, is not unlike instantiating a service or web app.
  • Containers offer independence and isolation, portability, scalability, and control.

By interconnecting containers in a service mesh you build cloud-native apps that run reliably across whatever environments they may encounter.

The Nexus

There is a nexus where all the latest innovations in software development meet. Microservices, containers, DevOps, continuous improvement through continuous development and deployment (CI/CD), event-driven architecture (EDA) and more all coalesce around the achievement of increased agility.

Microservices in containers are each independent from all others, increasing application resilience by enabling deployment in pieces. Should a change be required to any particular microservice, it does not require rebuilding or even stopping the entire application. This permits simplified maintenance as well.

Developers enjoy a division of labor, forming small teams to build and maintain specific services. They can even build those services in any language since each service will run separately from all others.

Bringing this all together, containerized microservices align with the core concepts of agility. They are very loosely coupled, so a change to one does not necessitate changes to another. Since they are easily reproduced they are highly scalable. Should a change be required, only the service requiring the change needs to be modified. And containers are literally the definition of granularity.

There is only one more piece required to bring them all together.

Responsive, Interactive, Event-Driven Communication

In the monolithic architecture of the past everything happened within the over-arching application.

Microservices each run independently from each other. So how are they going to communicate with each other? Certainly not in the classic way of waiting for action from a user.

Classic code was command driven. A command was issued by a user and the system ran the application containing all the required services. To eliminate the need for human intervention, the software would need to be able to detect that something has happened, an event, and respond to that event appropriately.

 

This was the driving force behind the development of EDA. Make it possible for a significant change in the condition of a component of the system to be recognized by the system, thereby triggering further action or actions by the system. Now microservices can run, produce a resulting event which is then handled by an event producer who processes it, sends it to the event router which ultimately distributes it among one or many event consumers responsible for further action.

To operate, containerized microservices require the kind of responsive communication provided by EDA.

An Example of an Event-Driven Microservices Architecture

Event-Driven Microservices Example

A simple event often requires complex responses. In this illustration, a premises sensor has detected the event of an expensive ring being stolen. Event processors provide the guidance required to provide deterrence by sounding an alarm while also notifying the police to respond and also notify the owner of the event. None of these notifications need to be aware of the others, nor wait for them to occur before executing. The immediate action this sequence provides demonstrates the value of loose coupling.

Cloud-Native Applications

Interconnecting containerized microservices creates cloud-native apps that can easily transport to wherever on the network they are needed. To run reliably and consistently they must have a communications platform that automates all potential responses. While classic monolithic applications could not scale as well, or provide the resilience required, cloud-native apps take advantage of EDA to enable them to facilitate the agility that defines the goals of DevOps which is to achieve continuous improvement in a dynamic environment in which continuous development and deployment are highly facilitated.

 

We certainly hope you’ll include Tiempo Development in your search for a capable partner to work with on your EDA project. Knowledge transfer and earning our reputation for excellence are our highest priorities. Contact us today to learn how we can help.

 

Event-Driven Architecture eBook CTA