Microservice-based architectures are changing the way we design software today, raising new challenges in development and operations. These architectures are adding a strong network dependency on business logic, increasing the number of potential hazards, which grow proportionally to the connections or links that are created between services.
Microservice vs monolithic architecture
Monolithic architecture has been traditionally used as the model for software development. In this, the software is composed of a unified and self-contained application with strongly coupled components, so that changing a small part implies releasing a new version of the application.
Microservice architecture is an alternative to monolithic architecture. It usually requires dividing the application into multiple, weakly-coupled units in order to have independent services with defined operations and interfaces through which the units interact to perform the required operation. Thanks to this architecture, we gain (among other things):
However, this type of architecture also brings new challenges to the table that should be looked at closely.
New challenges for microservice architectures
In the late 1990s, James Gosling –designer of the Java virtual machine – compiled a list of fallacies that can make a distributed system inefficient, insecure and harder to maintain. A distributed architecture needs to be carefully built, and doing so without explicitly handling these issues is a setup for failures. Therefore, examining Gosling’s assumptions is essential to be able to successfully adopt a microservice architecture:
- The network is robust and reliable. A failure can be caused by faulty software, faulty hardware (e.g., a switch), or a DNS issue between other external services.
- Latency is zero. While today’s languages and libraries mask the repetitive logic required to invoke the calls to remote service functions, developers sometimes assume they are invoked as if it were a local service. And this is simply not true, a call over the network is much slower than a local call. If this is not dealt with properly, the application can be blocked for a long period of time. Service downtime is an extreme scenario and rarely happens. A much more common scenario is for a service to respond slowly because of load.
- Bandwidth is infinite. If there is a need for a new functionality, we usually prematurely conclude that a new microservice must be created for it. But this has a cost for services already deployed in terms of network capacity.
- The network is secure. Applications usually exchange information in plain text, exposing sensitive data, therefore the communication must be secured.
- Topology does not change. One of the reasons for adopting a microservices architecture is the agility it brings in the building, release and deployment of products. This means low coupling between services. A simple horizontal escalation in a service can change traffic flows and create unexpected failures.
- There is one system administrator. In a microservice-based environment, each device is responsible for maintaining and operating its own services independently of the others.
- Transport cost is zero. It is important to keep in mind that data transfer consumes resources and may also incur costs.
- The network is homogeneous. Meaning that the entire ecosystem uses the same hardware and all services communicate through a standard protocol. This idea is pointless for the microservice philosophy of independent autonomous work teams.
If we delve into each of these challenges, we will conclude that rather than being related to microservice business logic, they are related to the way in which different systems interact with one another. In a cloud-native ecosystem like Kubernetes orchestrator, these challenges can be addressed by implementing a service mesh.
Our next article will explain what this new element is, and how a service mesh can benefit you in facing the challenges described…