Disclaimer: All content of this post is based on my own experience regarding microservices topic. And, my idea is to constantly update it.
Micro services architecture is a concept where an application is decomposed into small and loosely coupled services, where each service has a single responsibility. Those services may be implemented using different technologies, and thus the application is not bound to a single language or stack (This is one of the advantages of micro services: The freedom to use the best tool for specific problems). It’s possible to have an application built out with many languages and libraries. Besides that, this architecture leads to a more maintainable and stable application, for example: it’s easier to change any service to another, instead of replacing the entire application, since the contract made with other services remain the same.
The concept behind micro services is not particularly difficult, but it raises a lot of questions, such as:
- How to test the services?
- How do they communicate?
- How to manage deployment?
- How to define services contract?
Micro services is the newest buzzword when it comes to software development. Many companies are opting to create their applications through various isolated services where they communicate through an HTTP API. But not everything is as beautiful as it looks. A micro service based architecture has many problems and it does not solve nor tries to solve all architectural problems of a monolithic application.
Currently, I work on 5 different projects, where each of them has its own stack (servers, isolated deployment pipeline, different languages, etc.) and they could live in isolation from each other. However, there is an interdependence between them and between other existing APIs in the company, such as: search API, semantic API.
Let’s imagine the following scenario: A publisher wants to write a story where it has: title, description, body content, for instance. And, in addition to basic information, the story needs to be semantically annotated (remember, there is another API in the company).
With this “simple” scenario, it’s easy to realize that we may have a team responsible for the CMS (Content Management System), another team responsible for creating the best semantic API and, even, another team responsible for creating the best BaaS(Backend as a Service). They have completely different domains and placing all three teams working on the same code base could generate CHAOS. Can you imagine what would happen when the semantic team wants to launch a new version of the API to make an A/B test? The entire application needs to be deployed. This is just one of the possible problems that we face.
As we have teams working separately, and they are constantly evolving the services, at the same time trying to keep a backward compatibility without breaking existing clients, or even launching a new version, an environment of micro services perfectly matches such a scenario.
Here, at Globo.com, we have been using two ways to integrate two or more services: over HTTP and through a message broker. And the communication takes place through a contract between the services, following a known pattern called: Consumer Driven Contract.
When we are working on a micro services environment, where the services depend on each other, the coupling between services becomes hidden. Because, when one service changes its API contract, the other service does not know about that change. By creating a contract, this dependence becomes explicit. A great tool to create contracts is JsonSchema (we’ve been using it for a while and the outcome so far is very satisfactory).
What if a communication between services fail? How can we rollback the entire “transaction”? Since the HTTP protocol is a stateless one, there is no transaction concept. One approach to achieving this is through compensating transaction. And the response to the original request should be as gracefully as possible. (I think that this should be easier when dealing with an asynchronous environment, since there is no need to compensate, to rollback at the exact moment of the request. We’re going in that direction, but we have not had any explicit case for treating this scenario yet.).
How big is a service
- Single Responsibility Principle: http://en.wikipedia.org/wiki/Single_responsibility_principle
- Consumer-Driven Contracts: http://martinfowler.com/articles/consumerDrivenContracts.html
- Compensating transaction: http://en.wikipedia.org/wiki/Compensating_transaction
Cover Photo by Mario Luzza