Microservice Architectures and the Future of Application Development
At any given time, 50% of all software developers are inexperienced. Last month my colleague Dorus Verhoeckx mentioned this statistic in a blogpost. This easily leads to the conclusion that experienced software developers will be important and expensive. In this blogpost I would like to argue that the current tendency towards microservice architectures actually lessens the need for experienced software developers.
The reasoning behind this is extremely simple. Whereas in ‘traditional’ systems the desired functionality for an application is embodied in one large software component, a microservice architecture provides the same functionality as an ensemble of multiple smaller software components. By ‘software component’ I mean an individually deployable piece of logic. This could be a service, a script, a web api, a web application, a Azure Web Job, etc. Apart from software components, a typical architecture will consist of one or more data storage components, infrastructure components, third-party software components and SaaS cloud components. Each individual software component is simple, but because the number of software components increases, the architecture grows more complex. Thus the burden of complexity is shifted from the application’s software design to the environment’s architecture.
Complexity of an architecture
First of all, there is the need to manage the complexity of the architecture. This is a challenge for both application development and operations. Fortunately, some trends that have risen over the last few years help us with this. Automated deployment is one of these – deploying many small software components by hand would be asking for trouble. The trend toward containerization is the next step along the same line. Log centralization helps keeping track of the working of the components. Autohealing is a big help in managing the components: many failures can be resolved without human intervention. On the application development side, the rise of REST APIs helps because their stateless nature enables the loose coupling needed for microservice architectures. Also the increase in use of PaaS cloud components in the development process helps, because it encourages smaller software components.
Overview of an architecture
Despite the help these trends provide us in managing the complexity of the architecture, there are still some challenges to crack. Creating an overview of the architecture is one of them. This goes for the infrastructural architecture as well as the logical architecture. On the infrastructure side we see the rise of service discovery solutions to create an overview of how many components of which type are actually running. Such an overview is of crucial importance. An increasing number of components means an increasing chance of one of them failing. And if this happens, you want to be able to have a quick insight in how many of which components are affected, and what are possible scenarios for recovery, etc. Especially if you are using PaaS cloud components, it is good to realize that there is absolutely NOTHING you can do when they fail. Yes, I know, it isn’t likely to happen, but believe me: they will fail. The least you want to be able to do is tell your client what exactly is happening and discuss the steps to take after the failure is over.
For an overview of the logical architecture, we still depend on the drawing skills of the software architect. It is time consuming to create and maintain one, not to mention challenging to keep it clear and simple. But it is paramount to have such an overview, because the development process is changing. Software components are small and simple. This lessens the need for understanding and applying Object Oriented concepts and abstraction layers within an application. This explains the growing popularity of scripting languages for server-side development. Because the software components are simpler, the onus of automated testing shifts from unit testing to integration testing. The challenge is to have all the small software components working well together, rather than testing the software components themselves. I know unit testing is a sensitive subject for some. So let me be as clear as possible. I am not saying that it is not important anymore. Unit testing still has its part to play. Unit testing is very important for ensuring the quality of the code when it is refactored as the functionality of a software component is expanded during the software life cycle. The unit tests form a safety net as the complexity of the software increases. However, in the microservice architecture model, new functionality is not added by expanding existing components, but by adding new ones. Because of this application development strategy, the relative importance of unit testing diminishes.
Let me give an example. For one of our clients we renewed the media processing strategy. The previous strategy was implemented using a monolith service that handled validation, writing to storage and registering the media in a database. We implemented the new strategy as a microservice architecture. It looks something like this:
Each service is hosted on a small EC2 machine and is part of a service-specific autoscaling group. Interesting thing to note here is that Service 2 that handles preprocessing was not there in the initial setup. Only after the system was up and running the client identified the need for a preprocessing step. The microservices setup enabled us to quickly develop and deploy the new desired functionality. Note that the new functionality in no way affected the software of the existing services. We just changed the configuration of Service 3 to connect to another SQS queue.
We create an operational overview of the architecture by having the hosting machines of the services report to a REST API. In case of a failure, we can use the permanent storage in the database to determine which media was being processed at the time of the failure, and which service was handling it. With this information we are quickly able to see if data is lost, and if so which and how many. This allows us to determine a plan to execute after the failure is over.
Impact of microservices
In conclusion, the trend toward microservice architectures in an important one. It is enhanced by other current trends. The adoption of microservice architectures has far-reaching consequences for both software development and operations. The consequences are challenging, and also promising. Our future with microservices is going to be interesting.