From a Monolith to Microservices
Microservices are currently getting lots of attention in the IT industry. The microservices architecture (MSA) is emerging as an important approach for distributed mission-critical applications. In an MSA, the application is built upon a collection of services that can be developed, tested, deployed, and versioned independently. Enterprises are also increasingly carrying out cost savings, solving deployment problems, and improving DevOps and production operations by using containers (Docker engine based, as a de facto standard). When it comes down to it, microservices are about far more than refactoring code and deploying containers.
The Architecture: Monolithic vs Microservices
A monolithic application is a single-tiered application where the user interface and data access code base are combined to produce a single artefact. Unfortunately, this approach has some limitations, including loading times, scalability, and the fact that this type of application becomes an obstacle to continuous deployment. Successful applications have a habit of growing over time, and after a while, simple applications may grow into a complex monolith. This makes fixing bugs or implementing new features correctly difficult and time-consuming.
So how do we get around this? Organizations such as Amazon, eBay, and Netflix have solved this problem by adopting what is now known as the MSA pattern. Instead of building a single monolithic application, you split the application into a set of smaller, interconnected services. Each of these services can be deployed, tweaked, and redeployed independently without compromising the integrity of an application.
Thanks to its scalability, this architecture is ideal when it comes to enabling support for a range of platforms and devices—spanning the web, mobile, IoT, and wearables. When deployed properly, an MSA can bring significant value as it is organized around the business capabilities and priorities. Conversely, traditional monolithic application developers focus on UIs, databases, technology layers, or server-side logic.
A common approach for teams looking to adopt microservices is to identify the existing features in the monolithic system that are both non-critical and loosely coupled with the rest of the application. More sophisticated teams may simply require all new features to be developed as a microservice.
An API gateway can help combine individual services and integrate them into the existing monolith using some glue code. The main idea is to slowly replace the single-tiered application with discrete microservices. Just as Rome was not built in a day, your transition will take time and dedication – with impressive results.
Microservices are also not just about development. They involve deployment automation, smart logging, monitoring, and much more. They include many elements of the infrastructure which must exist or be decided upon before development begins.
Mitigating disadvantages and pitfalls
Each microservice must be self-deployable, either through an execution container or by integrating a container. For example, a JVM-based microservice could integrate a Tomcat container, reducing the need for a stand-alone web application server.
At any given time, there may be many similar microservices to allow for more reliable request management. Most implementations also include a software load balancer that can also serve as a service registry. This implementation also enables failover and query balancing.
Complexities in network calls and troubleshooting
Things get even more complicated when something goes wrong. Instead of examining a single application, you should limit interactions, network calls, requests, and responses between different services. If you have a performance problem, you will need to troubleshoot a network of related services.
You will soon realize that searching for log files on many servers and within multiple microservices will require standards in software development practices and modern tools such as log aggregation. Logstash and Kibana are good open source tools to consider. Logstash aggregates logs in a central location and Kibana allows you to search through the contents.
In an MSA, different nodes usually perform a task. One could easily lose sight of the big picture when studying problems, even if you have all log files centralized in one location. An easy way to correlate tasks to different nodes which belong to the same operation is by associating a correlation ID. This allows the ID to flow through the system so you can rebuild the history of an operation. If you are debugging a particularly nasty problem, the correlation ID will be the best starting point to find out what went wrong with a specific request.
Testability is a common problem: during the development of microservices, teams have to perform service integration tests. Developers provide sample queries and expected responses from the microservices. These specifications are then used to create relevant mock-ups and serve as a basis for an automated test suite that runs before integrating the new microservice into the application ecosystem.
This eliminates potential roadblocks for these teams and improves the feedback loop for the project as a whole. A common way to accomplish this is to containerize the entire system with Docker and automate with a tool like Rancher. This allows the team to quickly deploy environments for integration testing.
Build and Disseminate a Pipeline
Additional common considerations in the implementation of microservices are continuous integration and deployment pipelines. It is important to note that an MSA includes an on-demand, exclusive pipeline for construction and dissemination of each microservice.
Release practices should also include gradual upgrading or blue-green deployment; meaning, that at any time in a new generation and publication cycle, there may be simultaneous versions of the same microservice operating in production. A fraction of the users can be routed to the new microservice to test its operation, before gradually removing the old version. This ensures the reliability of the application. In case of failure, the load can be routed back to the old version.
The transition from a monolithic architecture to an MSA is an important one to consider. There are also crucial advantages associated with this in the long run, such as increased agility and efficiency, and reduced long term development costs. To manage this transition effectively, ensure that project responsibilities, limitations, and timelines are well understood, and define how your architects will work with each other. Finally, do not forget that a successful transition from monolithic to microservices depends on the scalability and security of your business.