In the ever-expanding world of software engineering buzzwords, “microservices” are a fairly recent addition. Introduced around 2012, it has steadily gained in popularity. But what are microservices and what are the pros and cons of adopting them?
At its most basic level, the term “microservices” denotes a style of software architecture with applications broken out into smaller autonomous services. The opposite would be “monolithic” application architecture, characterized by a single service or process handling all application responsibilities. Microservices are based on the idea of “service-oriented architecture” (SOA), but with very focused and fine-grained services as well as lightweight and simple communication. It takes the programming concept of breaking out functionality into different classes or libraries and moves that to the service level.
As an illustration, suppose you have a web application for your local library allowing users to browse the book catalog, see upcoming events hosted at the library, and view the history of the books they’ve checked out. A monolithic architecture would be characterized by a single WAR or EAR file (for instance) deployed to an application server and interfacing with one or more databases. A microservices architecture divides up various responsibilities into multiple WAR or EAR files, deployed individually, either to the same application server or across different servers. For example, one service to provide the data for the book catalog, one for providing the library’s calendar information, one to provide user account information, and another to process checkouts and renewals. These independent services contribute their portion of the data to the main process but potentially run on different machines.
INDEPENDENT – An advantage to a microservices architecture is that each service is developed and deployed independently from all the other services. This means an update to any one component does not require the entire application to come down in order to deploy that update, only the component in question. This allows for improved uptime and safer deployment processes.
TARGETED – Similarly, just as services are developed independently, a microservices architecture makes it easier for different portions of an application to be implemented using different languages. This is desirable when a particular language is better suited or targeted at a given task.
FLEXIBLE – Since all communication happens over the network instead of within the same in-memory process, there is more flexibility in terms of how each endpoint is composed. This also makes it easier for teams that have different skill sets to contribute to a project without spending time learning a new language or operating outside of their areas of expertise.
ROBUST – Applications using microservices architecture are more robust as a whole. When there is a loose coupling between services, if any service fails, there’s a greater chance the application as a whole can continue to provide value to users. The robustness depends on the nature of the services, how they interact and whether the application is designed with fault-tolerance.
REFACTORING – Certainly, if the various behaviors of your application are well understood and easily separated, a microservices architecture can provide some additional benefits. But suppose a project has been implemented in this style but the proper relationship between components was initially misunderstood? Refactoring an application across multiple services is much harder than refactoring a monolith and any interface changes will need to be coordinated between all the affected teams. Suddenly, using different languages for different components does not seem like such a benefit when functionality from one service has to be ported over to another.
COMPLEXITY – As it was previously stated, splitting an application into multiple independent services generates more artifacts to manage with potentially diverse deployment processes. This can increase the complexity of deploying the entire application at once.
TESTING – Spinning up test environments is more involved with microservices due to the increased number of nodes required. Tools such as Electric Flow make managing and tracking these artifacts and environments easier, but this issue can’t be ignored.
PERFORMANCE – Another area potentially impacted is overall performance. Communication over a network is considerably slower than in memory. For many applications, this may be negligible, particularly as network speeds improve, but it’s clearly something that should be taken into consideration.
On a related note, the design of an application will need to be skewed towards asynchronous behavior. This is neither inherently good nor bad but represents a potential challenge if trying to convert the design of an existing application.
In conclusion, microservices represent an increasingly popular style of application architecture. From a DevOps standpoint, they are a mixed blessing due to the relative ease and reduced liability of deploying individual components coupled with the increased complexity of the managing a larger number of components that grow and change on varying schedules.