Thinking About Microservices
We have been doing more and more work with containers and container orchestration in an effort to manage microservices. So, I have been thinking a lot about microservices and wanted to share some of my ramblings.
When I first heard about microservices I saw no real difference from service oriented architecture (SOA). Today, I still see no real difference, but thinking about microservices helps me see how to do SOA better.
Microservice has many definitions by many people and the meaning of the term is showing signs of standardizing. I still don’t subscribe to a particular definition, but when I think about microservices I have certain things that come to mind.
When I think of a microservice I think of a self-contained distributable versioned package. The package is where I put my custom assemblies and integrated dependent assemblies that I want to ship for consumption. The package contains my interface (UI, API), service, and infrastructure including external services and internal private persistence.
Internal private persistence and state could be something that separates SOA from microservice. Isolating state is one way that this architecture helps limit the bad side effects that come up with shared databases in SOA. Building a system based on microservices is kind of like building a thread safe application. The difference is instead of being able to distribute across threads I want to distribute across the network. Just like isolated state is important in thread safety isolated state (persistence) is important in microservices. There is so much more that can be said on this one point, but I won’t. Just know that isolating state is something I think about and I am still learning about how to deal with this.
Continuing my microservice thoughts, the microservice package has a well defined backwards compatible contract for the service interfaces that provides accessibility to a responsive, focused and cohesive bounded context for a specific domain. The package optionally has the microservice configurations, logs, traces, tests, documentation, SDK, and common services like pulling or pushing logs to a central log server or east-west message based communication with other microservices (e.g. Actor System). This east-west service-to-service communication is a large topic when you bring monolithic relational normalized database thinking to microservices. I still sometimes incorrectly think of how to reduce redundancy across microservices and provide deep relations and dependencies between the service like I would in a monolith. So, thinking about microservice is also retraining my thought process, it’s a paradigm shift.
These microservice distributions are all-in-one neat little packages of independent composable component goodness. I can build a microservice place it in a container and independently ship it through an automated delivery pipeline, continuously monitor it, elastically scale it, deliver the service in a highly available manner that is recoverable from internal failure and still responsive when there are failures in dependent services.
My favorite aspect of a microservice is that it is easy to reason about and maintain. My least favorite aspect of microservice architecture is that it is difficult to reason about and maintain. Microservices are simple because they are small and self contained. They are difficult because when composed together to form a system they constitute a distributed system and distributed systems have been a thorn in the side of my development career. In the end, I still love microservices because there are many new strategies and frameworks to lessen the pain of distributed systems that make building these systems very interesting to me.