-Erich Oliphant, Dovel Technologies
Microservices has become a hot buzzword in the IT media, making business and technology leaders worldwide to look around and ask, are we doing that? Should we be doing that? But when you take a step back from the hype and look at microservices, you see it is not a new revolutionary technology, but rather the latest evolutionary step of the services approach we’ve been using for years.
Many organizations are moving away from monolithic architectures where all of the functions are all deployed as a single system (e.g. a Java or .NET web application). The introduction of SOA (service-oriented architecture) changed this traditional thinking about building software, introducing the idea of building and deploying individual components based on the service they provide and then linking them together at runtime to function as a whole. This approach was further fueled by the emergence of cloud-computing, which in essence, ‘componetized’ compute resources, as well as the increased adoption of DevOps development and delivery practices. No longer did all of the technology and infrastructure used by an organization have to “live” with the organization, and a continuous delivery cadence has become the norm. Microservices are the result of the marriage of cloud, DevOps, and ‘service-thinking’.
Microservices can be defined as small, independently deployable modules that interact with one another using lightweight, loosely-coupled communication pathways. But with the term “micro” people tend to get stuck on the concept of “small.” While individual microservices are smaller (in terms of lines-of-code, etc.) than the monolithic systems they are replacing, in practice, it is more than that, it is about a new way to rapidly and flexibly deliver functionality based on contemporary best-practices for distributed systems. It is less about size and more about the implementation and delivery of resilient software systems that embrace change and evolution.
To fully understand this approach, we must agree on a definition of “service.” A service is not a specific technology, but it is supported by technology. A service is a self-contained unit of solution logic. The self-containment aspect is critical. This generally means that services should be developed and deployed independently, from independent source code repositories, to separately deployed executables. From an architecture and design perspective, services should not directly access other applications’ (or services’) data stores, but rather only interact via ‘public’ interfaces that may be message or service-oriented. As was the case with SOA, it’s useful to be mindful of the distinction between ‘(micro)services’, the architecutural approach described here, and ‘web services’, a specific technology for remotely calling functions.
Advantages of Microservices
Moving from monolith to services has numerous advantages in terms of decreasing run time and design time coupling. Risk is also reduced as changes in one service do not inherently impact other services. Changes can be rolled out faster without the fear of breaking the whole system. For developers, there is a reduced cognitive load as with microservices you only need to understand a few hundred lines of code rather the thousands or even millions that exist in many contemporary codebases. Finally, proper microservices are designed with failure in mind, “anti-fragility” as a key architectural quality, creating a more resilient system. It’s important to note that these benefits can only be realized with the appropriate attention to architecture and design, with particular focus on the established best-practices for distributed systems.
Moving to Microservices
If current complexity, ‘pain points’, etc. warrant it, existing monolithic systems have all the pieces in place to evolve to a microservices-based architecture, but the switch is not all sunshine and roses. Microservices are more complex simply because there are more moving parts. In other words, more services, more potential problems. When an error happens, it can be harder to identify and correlate the issue. But those problems can be mitigated by the adoption of tooling (monitoring, tracing, etc.) and best practices.
Key best practices for microservice architecture are:
- Code has to be stored and managed at the service level.
- Adhere to single responsibility principle, i.e., each service is responsible for only one business function or context.
- Consider the adoption of domain-driven design, as it can facilitate the identification of service and transactional boundaries that tend to map nicely to individual microservices.
- Establish framework, coding, and related standards. Many services, can result in different approaches adopted by different teams, and this should be managed.
- Adopt tools and frameworks for monitoring, tracing, continuous integration/delivery such that you have maximum visibility into your runtime environment and can deliver microservices in a consistent and repeatable manner.
Microservices are not just a passing fad. They are a logical extension of long-term trends in the evolution of software development. We expect to see more and more organizations move to the microservices architecture as monolithic systems get updated and greenfield systems are microservice-based to begin to meet the needs of today’s users.