We are all reliant on banking apps, music apps, streaming entertainment apps, and online marketplaces to make our lives easier.
As a software engineer, my job is to create consumer and business software apps that work seamlessly and efficiently. Microservices is a new approach being used to ensure the software is reliable, easy to read, testable, easy to maintain and to extend.
Microservices is a single application developed as a suite of small services, each running in its own process and communicating with lightweight mechanisms often an HTTP resource API.
In layman’s terms, Microservices builds software the way old-school stereo components are assembled: you have an amplifier, speakers, and a source of music (e.g. cd player, turntable). Each stereo component works on its own, and is independently replaceable and independently upgradeable.
I’m an advocate of Microservices although it is still a relatively new discipline in the software development world. We currently don’t have the luxury of relying on best practice techniques that help us navigate our way through its implementation as the Microservices textbook simply hasn’t been written yet.
To provide context, I’ll briefly explain the evolution of Microservices and then share what I consider to be four fundamentals when mapping out a Microservices project plan. These insights are based on my experience in implementing this Microservices model for our major international transport client, Mainfreight.
The evolution of web-based user interfaces
Years ago, software was a stand-alone application, loaded on individual computers (image 1). Programs were developed to suit this structure, with different functionality intertwined together in a single program.
Fig 1: The early days of delivering software
Developers then started isolating functionalities and building reusable modules and components (image 2). This was a vast improvement, as well as a cost-saving one as those modules could be re-used in different programs. The modules were still bundled together in a single program, and still needed to be installed on every computer.
Fig 2: Modular approach for delivering software
With ease of access to the internet, client-server architecture became commonplace (image 3). Software was run in a server with users accessing it through a browser. This was easier to develop and maintain however functionalities remained grouped and interlinked together in a big, monolithic application.
This meant that every time a change was needed in one module, connections between modules would be compromised, resulting in a break in some functionality. The fix was to ‘smoke test’ the application which meant more time and money between releases. Delays in releases are never good, and usually equated to lost revenue.
Fig 3: Web applications basic architecture
To address this, the practice of using Microservices evolved whereby a single application is developed as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.
4 Best Practice Essentials of Microservices
1) Componentization via services, not libraries
The aim of a good Microservice architecture is to maximise the number of independently deployable single services and minimise the number of library dependencies.
There are two benefits of this structure. First, if one service is down or under maintenance, other services in the application may not be affected, and the user can still engage with other features of the application.
Secondly, any required changes means that only a specific service needs to be redeployed, rather than having to redeploy the entire application. This takes less time, is less expensive and is less prone to errors.
Netflix is one of the most well-known companies using Microservice architectures. Unbeknownst to the user, their login system, the accounting system, streaming systems and user-rating system all operate as independent systems. If the viewer rating system is down or under maintenance, subscribers can still log on, stream and edit their account.
The same is true for Mainfreight’s website. Users can access the website to track shipments, get quotes, access updates amongst other tasks. When we carry out maintenance on a particular service, disruption is limited to that individual service only and not the entire website.
2) Decentralized Data Management
Expanding on the point above, it is also essential that these independently deployable single services do not share the same database (if they do, they can be defined as ‘small services’, but not Microservices). The benefit is better control and management of your services with fully independently deployable components and corresponding databases, talking to each other through a service interface.
Picture a typical pre-Microservices environment in which a quoting, billing and customer management system share the same database. Introducing changes for the sole benefit of the quoting team increases the potential for errors in the billing and customer management systems. Alternatively, when every Microservice has its own database, the above scenario is avoided since you are sharing details via an API.
The difference between Monolithic vs Microservices database architecture is shown in the diagrams below:
3) Organise around business capabilities
The Microservices approach splits up a monolithic application into services organised around business capability (e.g. DB, UI, development) rather than technologies (front end, back end and database teams). In this structure, each team should be focussed on the end user and be as full stack as possible.
Such services take a broad-stack implementation for that business area, including UIX, back end, database and any external collaborations. The teams are cross-functional with all the full range of skills required for the development.
Here at Sandfield, we use this approach for Mainfreight, by having teams organized around products such as Mainstreet, MIMS, Maintrak and Customer Facing Applications, with each team having a close relationship with the customer. In this structure, each product team is wholly capable of delivering the best solution for their customer’s needs, with specialists brought in on occasion to provide support when needed.
4) Design for failure
Remote services are not fail proof, especially if you distribute them across multiple nodes. This is why monitoring is so important. Resiliency, the system’s ability to tolerate failures, is typically a requirement, yet development teams struggle to meet this requirement, (usually a result of lack of time or knowledge). Netflix have addressed this systemic issue and have built a tool called Chaos Monkey to continually test the resiliency of their Microservices architecture
The singular purpose of their product is to randomly destroy nodes to test how resilient their network is. What is even more impressive is they usually run this tool in live environments provoking infrastructure failures, network failures or application failures.
The Microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API in order to provide more scalability, reliability and distributed applications.
Although the term Microservices has been around for a few years, this is an architecture with few guiding principles in place. Therefore, in lieu of a sanctioned Best Practice bible on the topic, I’ve provided my suggestions on some fundamentals when mapping out your Microservices plan.