Microservices with Spring Boot & Spring Cloud- part2

VineetaVineeta
6 min read

In this article, we will cover communication methods between microservices, service discovery and registry using Spring Cloud Netflix, API gateway using Spring Cloud Gateway, Spring Config Server configuration, distributed tracing, and circuit breakers.

To understand microservices, please refer to my previous article in this microservices series.

Microservices Communication

In a microservices architecture, we divide the application based on business requirements and need a way for the microservices to communicate with each other.

Here are some methods to enable microservices communication:

  1. Rest Template

  2. Web Client

  3. Spring Cloud Open Feign

Service Discovery

An application is composed of multiple microservices, with potentially multiple instances of each microservice running on different hosts and ports. To avoid hardcoding or maintaining a list of these services in the client or other microservices, a service registry server is used.

There should be a mechanism where we only need to configure the microservice ID so that one microservice can directly communicate with another without worrying about the hostname and port of the microservice instances it wants to connect to. The service registry server will handle configuring the appropriate request.

At any point in time, due to technical issues, services or microservices can go down, and because of scaling configurations, other instances might be spawned. Therefore, we need an automatic service registration and discovery mechanism. This is where the service registry server comes into play, keeping track of all the microservices and their instances in one place. The service registry will track all the microservices and their instances, and we can use this service registry. To implement this service registry, we use Spring Cloud Netflix Eureka Server.

API Gateway

API Gateway is essentially a bridge between the client and backend microservices. When the client wants to access resources from microservices, it sends the request to the API Gateway, which then routes the request to the appropriate microservice. The client does not interact directly with any of the microservices, so it is not tightly coupled with them. The API Gateway forwards the request to the correct microservice based on predefined rules or URL patterns.

The API Gateway is also used for security. Implementing security on each microservice is difficult and complicated, so the API Gateway provides centralized security and handles cross-cutting concerns like security, monitoring, and rate limiting. It hides all the microservice internals, so the client only needs to authenticate with the API Gateway and not with every microservice. The API Gateway can be implemented using Cloud-provided Spring Cloud Gateway on top of Spring WebFlux.

Config Server

Config server provides the configuration values for all microservices, allowing us to externalize all the configuration files in a central place. The problem with normal application configuration is that it is tightly coupled, meaning if we need to update the configuration file of a microservice, we have to restart the microservice and all its instances after the configuration update.

For the config server implementation, we use Spring Cloud Config Server to externalize the configuration files in a central repository, such as a Git repository. This way, we don't need to update each microservice individually; we can make changes in the Git repository, and they will be reflected in the respective microservice.

We should add the config client dependency to microservices so that whenever we start these microservices, the config client dependency will load the configuration files from the config server.

Distributed Tracing

Since the entire application is divided into multiple microservices, when a client sends a request, it may span over multiple microservices, making it difficult for developers to understand the trace or identify where an issue occurs. The challenge in microservice architecture is the ability to debug issues. Distributed tracing is used to trace the complete request from start to end and to track down why a certain microservice is taking too much time to process the request.

To trace client requests that hit multiple microservices, we implement the distributed tracing pattern using Spring Cloud Sleuth and Zipkin.

Distributed tracing appends IDs to every HTTP request made:

  1. Trace ID is common across the request. For example, when a client makes an HTTP request to the API Gateway, which internally routes that request to a microservice, and that service internally calls another microservice, the trace ID will remain the same throughout the entire flow.

  2. Span ID is unique to each microservice component. For example, when a client makes an HTTP request to the API Gateway, which internally routes that request to a microservice, and that service internally calls another microservice, the span ID will remain the same within each microservice.

Below is the format used by Spring Cloud Sleuth for providing trace information: <APP_NAME><TRACE_ID><SPAN_ID>

Circuit Breaker Pattern

When a client sends a request, it may span multiple microservices, forming a cascading chain, and an issue with one microservice can break this chain. The advantage of this pattern is that it reduces the number of calls if any service goes down, thus avoiding the waste of resources to fulfill the request.

To avoid cascading failures, the following patterns can be implemented:

1. Circuit breaker

In the case of circuit breaker patterns, they prevent microservice three from continuously sending requests to microservice four when it is down, saving resources and avoiding unnecessary calls between microservices.

2. Retry

In the case of a retry mechanism, if any microservice in the chain is temporarily down, the retry mechanism will attempt to call the other microservice multiple times. For example, if we configure the retry count as three, the microservice will retry sending the request to the other microservice three times.

3. Rate limiting.

In the case of the rate limiting pattern, it will limit the number of calls from one microservice to another microservice.

Circuit Breaker pattern working

There are 3 states in circuit breaker pattern:

  1. Open - Failure Rate Threshold is maintained. For example, if there are two microservices, m1 and m2, and m2 goes down, if m1's 2 calls succeed and 3 calls fail, and the initial threshold is 50%, the failure rate exceeds the threshold, so the circuit breaker will move into the open state, meaning it will fail whenever it reaches the threshold.

  2. Closed - The circuit breaker will allow all requests to flow from one microservice to another, indicating that the interacting services are up and running.

  3. Half Open - Time limit is maintained, and the circuit breaker will remain in the open state for that time limit (waitDurationInOpenState). For example, if the time limit is 5 seconds, it will stay in the open state for 5 seconds. After that, it will move to the half-open state with a limited number of calls(permittedNumberOfCallsInHalfOpenState), such as 5. In this case, microservices can make 5 calls while the circuit breaker is in the half-open state. After these calls, it will either move to the closed state or back to the open state, depending on the response. If the service gets a successful response, the circuit moves from the half-open state to the closed state. Otherwise, if there is a failure response, the circuit breaker state will move back to the open state. The circuit breaker will stay in the open state for 5 seconds, then automatically move to the half-open state, allowing 5 calls. Depending on the microservice response, the circuit breaker state will move from half-open to closed, and in case of failure, it will move from half-open back to open.

In the later part of this series, we'll explore asynchronous communication using message brokers like RabbitMQ and Kafka. Refer to the articles below.

0
Subscribe to my newsletter

Read articles from Vineeta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vineeta
Vineeta

Experienced Software Engineer with 4+ years of expertise, specializing in cutting-edge technologies.