When talking about web application architecture today, everyone talks about microservices. It often seems like there is only one way to build up a web application, the microservices way. As we all know, there the truth is rarely absolute. While I was using Jersey microservices in my last job, I now have to deal with a monolith and furthermore I worked with the Spring Cloud/Netflix stack for a university project, where we had to transform a monolith to a complete microservices architecture. In this post, I will try to recap both architecture styles and show that there is something beyond.
When talking about a monolith web application, we think about one large application, where everything is included in one single project or container. This could be a basic Spring/Struts/Jsp/Hibernate war/jar container, where even the frontend is included. Basically modules are separated by interfaces on the language level and modules are coupled by method invocation. This is the base project, which I used at the university.
Microservices in comparison are small, loosely coupled parts of web services, where each module is a stand-alone web application. Basically microservices are a implementation of SOA, but with REST instead of this horrible SOAP stuff. Communication between these fragments is done by HTTP and optimally through a proxy and service registry and with a edge server. The service registry is a core concept in microservices architecture. Every service registers there and asks for other services. This is the same application with microservices, which would be a great example of over engineering. Read more about microservices here.
So at the end we trade method invocations against HTTP calls in the case a microservice consumes another microservice.
It should be clear, that this trade is an expensive trade, when thinking about performance. Http is much slower than a method call, even if we call the method via RMI. So why should we do something like this?
Well the first major advantage is the language independence. The Rest service doesn’t care about if there is Java, php or .Net behind the API. This is not an advantage of microservice, it is an advantage of RESTful web services in general.
Some other positive side effects from microservices are
- Required to separate concerns on a use case level
- Think about modular design
- Stable interfaces and versioning
- Independent team works (could also lead to “I don’t care”)
But not everything is that positive, besides the huge performance impact microservices add a huge complexity to the application, even if frameworks like spring cloud try to overcome the issue of service failure and network problems, with caching strategies and eventually consistency, we still must deal with the network problems and distributed transactions. Furthermore, deployment is much more complex, debugging and testing is harder and much more work to do. We also need to have a DevOps and a continuous integration environment.
The smarter way using microservices is to use them directly from the frontend (via a gateway), so the additional HTTP calls are only involved between microservices itself. With that architecture you need a modular frontend, which can handle this kind of different APIs (react.js, angular or another fancy javascritp l ibrary). Here you also need to introduce something like OAUTH to secure the services.
So would it be worth to introduce network communication just to have more independent modules, which could be also done with more time investigation on design? I don’t think so, so what is the point of microservices?
Yes, its scalability. Just think about a monolith application, which is complex and scaled by adding hardware. Feature by feature the application grows and the hardware does too. We all know, that the there is a limit of doing so and finally another node is added and extra work is needed to deal with synchronization and so on.
Maybe one single module in the container is the reason why the performance goes down, but there is no way to separate it, due the application is too big and too complex. Here microservices would be beneficial. Every single module can be scaled individually and furthermore it can be scaled automatically (e.g. docker). That’s the point of microservices.
While it makes no sense to build a simple small web shop with microservices, like in the university example, it also makes no sense to integrate a processing intensive task into the monolith or even built a high-availability application the monolith way. So there is no best architecture, it depends on the application.
I think one problem behind many monoliths is that the design has become inappropriate, so that components can´t be separated. The next problem with very big monoliths is, that developers tend to put all things in, even if they could be separated into small projects, maybe because they don´t get the extra time or just want to get the things done. Working in large Teams on monoliths is often a problem, when side effects occur.
My thought is, identify the components, which could be potential performance killers in the future and build them with the microservice idea in mind, so that it would be possible to separate them later or just make them available as a REST API, which is used by the monolith.