Blog /

An Overview of Microservice Architecture: Recent Trends and Challenges

A comprehensive review of microservice architecture covering its evolution, core principles, communication patterns, deployment strategies with Kubernetes, serverless computing, and concurrency challenges like race conditions and deadlocks.

A
Aman Nirala
15 min read
An Overview of Microservice Architecture: Recent Trends and Challenges
This article is available as a downloadable PDF
Download PDF

This article was originally written as a review paper for the School of Computer Science Engineering at Vellore Institute of Technology, Vellore, India.

Abstract — Microservice architecture is one of the trending ways to build complex, highly scalable and high-performing IT infrastructure. This review article aims to provide a comprehensive overview of the microservice architecture, its evolution, needs, recent trends and problems related to it. It also discusses some of its implications in FaaS, server-less computing and technologies like Kubernetes. The article also aims to cover some design problems that come with such concurrent systems like race conditions, data inconsistency and deadlocks.

KeywordsMicroservice architecture, Concurrency, FaaS, Server-less computing, Kubernetes, Race Conditions, Cloud Functions


I. Introduction

An architecture is the blueprint for any system under which it works, evolves and communicates with its components. The architecture plays an important role in the system’s performance, quality, maintainability and overall success [1]. Recently, microservice architecture has come up as a design and architecture of choice for modern software development [2]. This development however took a lot of innovation and time [3]. Before starting with microservice architecture, discussing other design paradigms like Monolithic Architecture would provide a better understanding and need for microservice architecture.


II. Monolithic Architecture

A monolith (a system that follows the monolithic architecture) is a system whose components are encapsulated and tightly coupled. The elements of a monolith cannot be executed independently. The mainstream server-side development languages like JAVA, C/C++, and Python are designed to create single executable artefacts, making deploying a monolith very easy [3, 4].

Diagram of a monolithic system architecture showing a single tightly-coupled application with all components encapsulated together, including UI, business logic, and database layers Figure 1: A diagrammatic representation of a monolithic software system

A monolithic architecture has its disadvantages which are discussed in section 2.1. Monoliths are still widely used as many high business value services and applications today still follow this architecture due to its ease of deployment and ability to program small and simple tasks. Choosing this architecture for starting a software project is considered a good option as it allows for exploring the system’s complexity and boundaries [2, 4, 5, 7].

2.1 Problems with Monolithic Architecture [3, 4]

This section provides a comprehensive list of the disadvantages that come with monolithic architecture that lead to the development of microservice architecture.

  1. Difficult to maintain — Even a small change can lead to chaotic behaviour in the system and tracking down bugs will need lots of testing and changes to be made throughout the system.

  2. Dependency hell — Changing or updating a dependency can lead to incompatibility with other dependencies, changes in the behaviour of the program or unable to compile the code completely.

  3. Higher downtime — Any maintenance or upgrades will need the whole application to be shut down.

  4. Technology lock-in — Developers usually face a technology lock-in when using this architecture as all the elements of the system will have to be built and maintained in the language and framework used initially.

  5. Difficult to scale — To cater to more clients monoliths will have to be redeployed completely even in situations where only a few services are in demand. This adds extra operations expenses for the service provider.


III. Microservice Architecture (MSA)

Microservice architecture provides a design where the whole system is divided into small loosely connected systems called microservices that interact with each other through message passing on request [1, 3, 4, 6, 7]. They are built on the principles of:

  • Single responsibility
  • Loose coupling
  • Scalability
  • Deploy-ability
  • Independent execution

These are not the characteristics of monolithic systems [7].

A Practical Example

A very intuitive example of a graph plotting system using microservice architecture is provided in [3] where:

  1. A user inputs to a microservice “Plotter”
  2. The Plotter passes the message/data to another microservice “Calculator”
  3. The Calculator calculates the shape of the graph according to the provided function and returns it to the Plotter
  4. The Plotter then calls for another microservice “Display” which is responsible for displaying the received plot to the user

Diagram of a microservice architecture example showing separate Plotter, Calculator, and Display services communicating via message passing to process user input Figure 2: An example of a system that follows MSA [3]

It’s interesting to see that all these microservices are responsible for individual tasks and still coordinate via message passing as a system to provide meaningful service. One of the benefits of using MSA is the ability to use different technologies and deployment environments for each microservice according to their needs and demands. This architecture opens new doors for paradigms like distributed computing, cloud computing, clustered computing and FaaS (a product of the prior mentioned paradigms).


3.1 Communication Between Microservices

A very intriguing question to ask is how microservices communicate with each other even though they can be deployed in totally different environments and developed with different frameworks and standards.

Monolithic vs. Microservice Communication

In a monolithic application, the elements use language-level methods or procedure calls to communicate with other elements [8]. Since the elements of a monolithic system share the same environment, memory space and processor, the communication is faster and secured (assuming that the integrity of the backend machine is intact).

In contrast to the monolithic architecture, microservice-based systems are distributed systems. The microservices can be deployed on multiple machines in different environments. One can look at each of those instances running a microservice as a process which needs some IPC (Inter-Process Communication) to work together.

3.1.1 IPC Interaction Styles

Any inter-process communication can be categorized along two dimensions:

First dimension — Type of connection:

  • One-to-One — Client/Service requests are catered by only one service
  • One-to-Many — Client/Service requests are processed by multiple processes

Second dimension — Nature of interaction:

  • Synchronous — Client/Service receives a periodic response from the service and the client might halt while waiting for the response
  • Asynchronous — Client/Service doesn’t block while waiting for a response and responses are not sent immediately
One-to-OneOne-to-Many
SynchronousRequest/Response
AsynchronousNotification, Request/Async responsePublish/Subscribe, Publish/Async responses

Table 1: Interaction styles [8]

Brief descriptions:

  • Request/Response — A client sends a request to a service and waits for a response
  • Notification — A client sends a request to a service but no response is expected
  • Request/Async response — A client sends a request to a service and doesn’t halt for a response. It assumes that the response might be delayed
  • Publish/Subscribe — A client broadcasts a message which is consumed by subscribed services
  • Publish/Async responses — A client broadcasts a message and waits for certain services to respond

3.1.2 IPC Technologies

Two broadly classified technologies are:

Asynchronous Message-based Communication

In message-based communication, a message is the data that is transmitted through a medium or channel between services. A message has:

  • Headers — containing various metadata like the sender’s details, protocols and standards involved and even authentication tokens
  • Message body

Some open-source messaging systems (systems that facilitate message composition and transmission through the implementation of various protocols and standards):

  • RabbitMQ
  • Apache Kafka
  • Apache ActiveMQ
  • NSQ

The message-based IPC adds extra complexity as the whole messaging system is yet another element that becomes part of the system and adds extra dependency.

Synchronous Response/Request IPC

In a response/request IPC, the client sends a request for services and waits for a response. This request could be made from:

  • A synchronous process — blocking the thread that is making the request
  • An asynchronous process — not blocking the thread while waiting for a response

Two important protocols used are:

  • REST — A design to implement API end-points that can be accessed through HTTP requests
  • Thrift — An alternative to REST. Apache Thrift is a framework used to write cross-language remote-procedure call clients and servers

3.2 Deployment and Orchestration

Deploying a microservice system and ensuring the integrity and health of all the components can be a very challenging task. Before introducing the technologies used for deployment, let me define some basic entities and terms:

Definition 1: Cloud Computing — Cloud computing is a kind of computing technique where computing services are provided by low-cost computing units connected via IP networks [9]. This definition however may vary as there seems to be no agreement on what is cloud computing and what its scope is as it’s expanding continuously [9, 10].

Definition 2: Container — Containers are entities that contain the execution environment, VMs, OS, physical hardware everything encapsulated that is needed for the microservice to execute [11].

Definition 3: POD — A Pod is a unit computing entity that is copied multiple times to achieve scalability. A Pod can have multiple containers [12, 13].

Definition 4: Cluster — A Cluster is a collection of resources like storage, network, and computing systems that are used to distribute workload [12].

Definition 5: Node — A Node is a single host that can be a physical machine or a VM. Nodes are responsible for executing pods [12].

Definition 6: Master — A master is a special node that is responsible for handling other nodes and their resources [12].

Deployment Strategies

The distributed nature of MSA requires it to be deployed using cloud computing. There are multiple cloud service providers today which provide a substantial and reliable infrastructure for the deployment of an MSA-based application. Notable cloud service providers include:

  • Google Cloud Platform (GCP)
  • Amazon Web Services (AWS)
  • Microsoft Azure

There are multiple strategies for deploying these services:

  1. Design — Breaking the application into microservices by following the principles mentioned in Section III. Choose a proper IPC design as discussed in section 3.1.

  2. Containerization — Technologies like Docker can be used to containerize the application environment which provides a level of virtualization, isolation and consistency between microservices and their deployment. These containers can be managed using services like Kubernetes.

  3. Cloud Provider Selection — Choosing a CSP according to the need is one of the crucial steps of deploying a microservice. Some important aspects to look into are pricing, the region the services are catered and the ecosystem.

  4. Orchestration — Orchestration refers to services like logging, scaling, cost and resource optimisation and error handling. Most of the cloud services provide built-in orchestration services while Kubernetes can be used to manage clusters of Pods. Services like AWS EKS and GCP GKE can be used to deploy Kubernetes clusters.


3.3 Kubernetes

Kubernetes, an open-source container orchestration platform, oversees the deployment, monitoring, and scaling of containerized applications across numerous hosts. Initially developed by Google, it was subsequently contributed to the Cloud Native Computing Foundation (CNCF) in March 2016 [13].

Kubernetes allows the user to declare states of application using concepts of “deployments” and “services” [13]. For example, a user can specify they need to deploy 5 instances of Python3 with Flask. Kubernetes will continuously monitor and manage the instances and maintain the integrity of their states.

Kubernetes architecture diagram showing the relationship between Master node, kube-apiserver, etcd, kube-controller-manager, kube-scheduler, and worker nodes with pods and containers Figure 3: A diagrammatic representation of Kubernetes architecture [13]

Key Components

  • Master — Controls and manages the cluster
  • kube-apiserver — Used to modify the resources running in the cluster
  • etcd — A distributed key-value store used to store cluster states
  • kube-controller-manager — A monitoring system that looks into the elasticity of the components
  • kube-scheduler — Used to schedule pod initialization based on node configuration

Docker plays an important role in the deployment of Kubernetes clusters. The nodes in the cluster have a docker container which is like a stripped-down OS with only packages installed that are needed for the execution of the microservice application.


IV. Serverless Architecture

Serverless architecture is a product of cloud computing and an amalgamation of two types of services [1]:

  • BaaS (Backend as a Service)
  • FaaS (Function as a Service)

In serverless architecture, the developer doesn’t need to bother about setting up and maintenance of the backend environment and hardware. All they need to do is use a cloud service like Firebase from GCP that provides a ready-to-use infrastructure for the deployment of services and an interface/API to interact with it.

These same services provide a way to deploy simple lightweight endpoints without setting up any servers, network, port configs, etc. These are called FaaS:

  • Cloud Functions by Firebase (GCP)
  • AWS Lambda

Screenshot of Firebase Cloud Functions dashboard from Google Cloud Platform showing serverless function deployment and FaaS management interface Figure 4: Cloud Function from Firebase Dashboard

These FaaS services can be used for RESTful IPC which was discussed in section 3.1.2.


V. Problems with Concurrency

The MSA comes with a feature that allows developers to make use of parallel computing. Multiple nodes on a cluster can be used as processing units that can work together to solve a single problem. Such systems face the issues of concurrency.

Example: Race Condition

Let’s say we have two services “Alice” and “Bob” which share the same source of truth — a database which stores a variable “Count”. The instruction requires:

  1. Alice to first access the value from the variable “Count” and increment it by 1
  2. Bob to access “Count” and multiply the value by 2
  3. At the end, read the value of “Count” as the output
ALICE ( COUNT ) :
    COUNT = COUNT + 1
END

BOB ( COUNT ) :
    COUNT = COUNT * 2
END

START:
    COUNT = 5
    THREAD 1 : ALICE(COUNT)
    END
    THREAD 2 : BOB(COUNT)
    END
END

Figure 5: Instruction for Alice and Bob

The Problem

The method calls of Alice and Bob are taking place concurrently. The expected output:

  1. Alice increments the value by 1: 5 + 1 = 6
  2. Bob multiplies it by 2: 6 × 2 = 12

Expected result: 12

But let’s assume that for some reason the thread or process responsible for running Alice got delayed or suspended. The process responsible for executing Bob will get the preference and the whole condition will change:

  1. Bob multiplies Count by 2: 5 × 2 = 10
  2. Alice increments the value by 1: 10 + 1 = 11

Actual result: 11 — which is not what was expected.

This whole situation is termed as a Race Condition [14-16]. Many techniques and methods to avoid such conditions are discussed in [14, 15].

Deadlock

Deadlock is a situation where elements of a system halt in a situation where they wait for a condition to fulfill which never does [17]. Generally, it is seen with elements that share a circular conditional dependency. This deadlock situation persists until some special action is taken from the outside.

A very elegant solution to the problem of race conditions and deadlocks using Communication Sequential Processes is provided in [14].


VI. Conclusion

In this article, I discussed and explored different architectures used for the development of IT infrastructure. Key points covered:

  1. Monolithic Architecture — Its problems that led to the development of MSA
  2. Core Principles of MSA:
    • Single responsibility
    • Loose coupling
    • Scalability
    • Deploy-ability
    • Independent execution
  3. Microservice Communication — Different IPC styles and technologies like REST and Thrift
  4. Deployment — The role of Kubernetes and Docker in the modern tech stack
  5. Serverless Architecture — How MSA led to the development of new paradigms like BaaS and FaaS
  6. Concurrency Problems — Race conditions and deadlocks in distributed systems

MSA has been a revolutionary design that led to the development of modern IT infrastructure and brought a generational innovation of the Internet.


References

  1. Jaiswal, Manishaben, “Software Architecture and Software Design” (November 5, 2019). International Research Journal of Engineering and Technology (IRJET) e-ISSN: 2395-0056, p-ISSN: 2395-0072, Volume:06 Issue:11, pp.2452-2454, Nov 2019. Available at SSRN: https://ssrn.com/abstract=3772387

  2. Selmadji A, Seriai AD, Bouziane HL, Oumarou Mahamane R, Zaragoza P, Dony C. “From Monolithic Architecture Style to Microservice one Based on a Semi-Automatic Approach.” 2020 IEEE International Conference on Software Architecture (ICSA). 2020 Mar.

  3. Dragoni N, Giallorenzo S, Lafuente A, Mazzara M, Montesi F, Mustafin R, et al. “Microservices: yesterday, today, and tomorrow” [Internet]. 2017 [cited 2023 Sep 20]. Available from: https://arxiv.org/pdf/1606.04036.pdf

  4. F. Ponce, G. Márquez and H. Astudillo, “Migrating from monolithic architecture to microservices: A Rapid Review,” 2019 38th International Conference of the Chilean Computer Science Society (SCCC), Concepcion, Chile, 2019, pp. 1-7, doi: 10.1109/SCCC49216.2019.8966423.

  5. Gos K, Zabierowski W. “The Comparison of Microservice and Monolithic Architecture.” 2020 IEEE XVIth International Conference on the Perspective Technologies and Methods in MEMS Design (MEMSTECH). 2020 Apr.

  6. Ramu VB. “Performance Impact of Microservices Architecture.” The Review of Contemporary Scientific and Academic Studies. 2023;3(6).

  7. Abgaz Y, McCarren A, Elger P, Solan D, Lapuz N, Bivol M, Jackson G, Yilmaz M, Buckley J, Clarke P. “Decomposition of Monolith Applications Into Microservices Architectures: A Systematic Review.” IEEE Transactions on Software Engineering. 2023 Jun 23.

  8. Richardson C. “Building Microservices: Inter-Process Communication” [Internet]. NGINX. 2015. Available from: https://www.nginx.com/blog/building-microservices-inter-process-communication

  9. Qian L, Luo Z, Du Y, Guo L. “Cloud computing: An overview.” In Cloud Computing: First International Conference, CloudCom 2009, Beijing, China, December 1-4, 2009. Proceedings 1 2009 (pp. 626-631). Springer Berlin Heidelberg.

  10. Kim W. “Cloud computing: Today and tomorrow.” J. Object Technol. 2009 Jan 2;8(1):65-72.

  11. Turin G, Borgarelli A, Donetti S, Johnsen EB, Tapia Tarifa SL, Damiani F. “A formal model of the kubernetes container framework.” In International Symposium on Leveraging Applications of Formal Methods 2020 Oct 20 (pp. 558-577). Cham: Springer International Publishing.

  12. Sayfan G. Mastering kubernetes. Packt Publishing Ltd; 2017 May 25.

  13. Kubernetes T. Kubernetes. Kubernetes. Retrieved May. 2019;24:2019.

  14. Martin JM. “Designing and Verifying Microservices Using CSP.” In 2021 IEEE Concurrent Processes Architectures and Embedded Systems Virtual Conference (COPA) 2021 Apr 25 (pp. 1-4). IEEE.

  15. Beckman NE. “A survey of methods for preventing race conditions.” May. 2006 May 10;10:1-20.

  16. Bruce KB, Danyluk A, Murtagh T. “Introducing concurrency in CS 1.” In Proceedings of the 41st ACM technical symposium on Computer science education 2010 Mar 10 (pp. 224-228).

  17. Holt RC. “Some deadlock properties of computer systems.” ACM Computing Surveys (CSUR). 1972 Sep 1;4(3):179-96.