Microservice Architecture, Its Design Patterns And Considerations

Introduction

Microservices architecture is one of the most useful architectures in the software industry. These can help in the creation of a lot of better software applications if followed properly. Here you’ll get to know what microservices architecture is, the design patterns necessary for its efficient implementation, and why and why not to use this architecture for your next software.

Microservices

An architectural pattern, a way or style of architecture, if followed properly, will result in software application that consists of several services, instead of one large Monolith.

Services in this pattern are easy to develop, test, deploy and maintain individually. Small teams are sufficient and responsible for each service, which reduces extensive communication and also makes things easier to manage.

This allows teams to adopt different technology stacks, upgrading technology in existing services and scale, and change or deploy each service independently.

Microservices VS Monolithic

Both microservices and monolithic services are architectural patterns that are used to develop software applications in order to serve the business requirements. They each have their own benefits, drawbacks, and challenges.

On the one hand, when Monolithic Architectures serve as a Large-Scale system, this can make things difficult. They can be cumbersome to work on when it comes to adding new features, implementing changes to existing functionality, or even removing some unnecessary functionality.

But, Monolithic Architectures are still a good option for the options given below:

  • Small scale applications
  • There's no need to upgrade technology
  • They take less time to hit the market
  • Teams are familiar with Monolithic approaches

On the other hand, Microservices architecture is not a good fit for Small-Scale applications that require a single technology stack, deployment platform, domain area, etc. But, for a large-scale application, there's almost nothing better than this architecture thus far.

 Microservices architectures are a good option for the following cases:

  • Large-scale applications
  • Required updates of technology
  • Different teams with different technical skills (programming languages, frameworks, etc.)
  • If you have various domains to tackle
  • And many more

Comparison

Here, we will compare some of the characteristics of Microservices and Monolithic architecture to better understand them.

Characteristics Microservices Monolith
Speed Comparatively slower in terms of development, as smaller services are developed separately. Faster when it comes to developing a single application that contains almost all the necessary things from the start.
Independence Each service has its own data store and responsibility of specific domain, and can be developed, changed, or deployed independently. Tightly coupled, the whole application is deployed when any change occurs, as all the business logic is in one place.
Flexibility Services are smaller in size, which makes them easily adaptable to new technological changes. Same technology is used and cannot be changed, as the whole application was developed using it.
Scalability Easy-to-scale services without affecting others. Have to scale the complete application, evne if just one feature inside needs to scale.
Reliability No need to bring down the application if change is required in a service. Have to redeploy the entire application if anything requires change.
Testability Services that are domain-specific are easy to test. It is difficult to test complete system at once.
Maintainability Individual services can be updated and changed as per market conditions. Hard to maintain as application size grows, because change in one place can have some regressive effects on others.
Teams Several small-size teams with different sets of technological skills can be utilized. One large team with almost similar technology skills and understanding required.
Management Managing different smaller teams, each working on a specific business domain, gives easy analytics about who is responsible for what. Managing one large team working on complete domain requires internal division.
Communication Slower when compared, but easy. Difficult to communicate to management about any problems encountered.
Infrastructure Exponential in terms of cost, as different teams with different skills with multiple repositories, environments, and pipelines. Cost effective, as teams work on the same repository, and all teams have almost the same skillsets when it comes to technology. So, there's no need for multiple different development and deployment environments.

Important Design Patterns

There are several patterns in microservices architecture, but some of the important are discussed below.

Strangler

This pattern addresses the incremental transformation to Microservices architecture from a Monolithic application. Old functionality is replaced by new services, and the latter is put to use after completion while the former is strangled.

The facade interface plays a vital role in the process where services are exposed to the external world when separated from the monolith. So, clients will know the new services behind the facade, and this will obscure the old system.

API Gateway

This provides single entry point for all services, instead of the client directly communicating with each service. API gateway provides aggregation, authentication, caching, etc.

API gateway helps in achieving the following factors:

Security

API gateway does not expose services to the external world directly to secure them. All security-related issues are handled at gateway, and only authenticated clients will gain further access.

Cross-cutting concerns

Concerns such as authentication, SSL termination, rate limiting, request throttling, caching, and more that need to be implemented in each service are the responsibility of gateway.

Coupling

Clients interact with services through the API gateway, which makes it more loosely coupled.

Aggregator

Some requests require several services, which makes increases in the chattiness of client with services. Aggregator can communicate with all services and return a response after aggregation to reduce extensive communication from the client to services.

Saga Pattern

This pattern helps in transaction management where local transaction in each service (saga) take place, and emit an event for next service to start transaction. If any of the transactions fail, a series of transactions that compensate for the previous transaction will be executed by saga to undo any changes made by local transactions that preceded this one.

Below are two means of implementing Sage pattern:

Choreography

In choreography, the point of control is not centralized, which means that each service will publish a message or event for other services by triggering local transaction.

Orchestration

Orchestration provides a way to control the saga participants (services) by telling each service about the local transaction they need to execute. On an event basis, the operations for saga and transactions are handled by the saga orchestrator. The state of an individual task is managed by saga, and in case of failure, it will execute the transaction to compensate for previous transactions.

Asynchronous Messaging

Some requests are compute-extensive and require longer times, which can exceed the timeout limit. For those requests, there must be an asynchronous mechanism in place using message broker services like Azure Service Bus Queue. This helps in processing a large message, and in responding to the requested service after completion.

Circuit Breaker

Some failures can be transient, but some are not. Tlatter system should not exhaust the resources. Instead, break the request flow there and return the exception back immediately. This pattern helps in a situation where the Retry pattern can cause a waste of time and resources, as retrying is not required at all. A timer is used to check whether the system that was failing is recovered enough to be used or not.

This pattern is different from the retry pattern because here the point is not to hope for a successful result by retrying, but rather to save resources from being used unnecessarily. A circuit breaker pattern can avoid the operations that are likely to fail.

This behaves as a proxy for any operation that has the chance to fail. The number of failures is monitored and used for decision if they exceed a specified threshold. There are three states that are similar to a circuit breaker in electronics, as follows:

Closed

The operation to be performed is invoked by a request. The failure count is maintained by proxy and incremented in case of unsuccessful operation. If the number of failures exceeds the threshold for a specified time, then Open is the new state that proxy enters. Here it also starts the timer, and after timeout, the state of proxy will change to Half-Open.

Open

The exception is returned immediately to the application after receiving the request.

Half-Open

Few requests, limited in number, are allowed to pass on to invoke an operation. Upon successful response from the operation, the state of proxy will change to Closed. If failure occurs again, then the proxy will go into an Open state and restart the timer.

Benefits

  • Smaller team sizes with different skill sets lead to the utilization of the best from each language and framework.
  • Faster and independent deployments where the real usage of continuous integration and deployment comes into action.
  • Testing each service is easy and less time-consuming, because services are domain-specific to their own data store.
  • Diverse technologies can contribute toward a complete solution. Upgrading from one technology to another is also trivial.
  • Change in the service will not affect the complete system, which results in high reliability.

Drawbacks

  • Infrastructure is very costly as different technologies have different testing methodologies, environments for each service, and deployments.
  • Debugging can become cumbersome due to different logs of each service and identification of bugs in the actual service.
  • Polyglot microservices have some side effects as well, where a company needs to maintain resources for each technology used for developing services.

Summary

Here I’ve discussed microservice architecture, along with comparing it with Monolithic architecture. I have briefly compared their characteristics for further understanding. Important design patterns were also briefly discussed, along with benefits and drawbacks of each architecture.