How to do client side load balancing in Spring Boot?

Let’s say you have created a set of microservices.

They communicate to each other through a service registry like Eureka.

One shortcoming in communicating through service registry is load balancing is not taken care of by default.

You need to take care of that through a client side load balancer or a service side load balancer.

Spring Cloud comes with its own Load Balancer. And it is shipped along with the spring-cloud-starter-netflix-eureka-client dependency which you add in your eureka client microservices.

So you don’t have to add any extra dependency:

You just need to use a smart “Rest Template” or a smart “Web Client” to make the HTTP calls to each other microservice.

Let’s see how to implement this.

Let’s take the examples introduced in this post.

I started a Eureka server “eurekaserver”

I started one instance of a eureka client “eureka-client” and two instances of another eureka client “eureka-client-2”.

All these three automatically got registered to the eureka server since they have “spring-cloud-starter-netflix-eureka-client” dependency in their pom.xml.

Now let’s call the REST API defined in eureka-client-2 from the REST API defined in eureka-client.

Here is the REST API for reference:

eureka-client-2:

package com.example.eureka.client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	@Autowired
	private Environment environment;
	
	@GetMapping("client2")
	public String client2() {
		
	    String serverPort = environment.getProperty("local.server.port");

		
		return "I am a REST API in client 2 running on port "+serverPort;
	}
}

To call the above REST API from eureka-client you need to use a smart “RestTemplate” or a smart “WebClient”.

A smart RestTemplate is aware of the multiple instances of the same application and uses load balancing algorithms to pick one instance.

All you have to do to achieve this is create a configuration class with a RestTemplate bean defined and annotate it with @LoadBalanced annotation.

Spring will automatically wire the required load balancing logic:

package com.example.eureka.client;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class Config {

	@LoadBalanced
	@Bean
	public RestTemplate restTemplate() {
	    return new RestTemplate();
	}
}

Now let’s use this rest template to call the REST API in eureka-client-2.

Here is the code:

package com.example.eureka.client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController

public class TestController {

	@Autowired
	private RestTemplate restTemplate;

	@GetMapping("/test")
	public String test() {

		String url = "http://eureka-client-2" + "/client2";

		String response = this.restTemplate.getForObject(url, String.class);

		return response;

	}
}

In this post we used “DiscoveryClient” class to get the instances from eureka service registry.

If two instances are running DiscoveryClient returns the two instances and you need to decide which instance to call.

Here though the smart Rest Template takes care of that.

Instead of passing the actual domain name of the microservice you have to pass the service name of the microservice you are calling while constructing the URL to be passed in the Rest Template.

“eureka-client-2” in the below URL just refers to the service id (configured in spring.application.name property in application.properties file of eureka-client-2 microservice):

String url = "http://eureka-client-2" + "/client2";

We have spinned up two instances of eureka-client-2 one on port 8082 and another on port 8086.

Let’s see which instance is fetched by the smart Rest Template:

The first time I hit eureka-client’s test API I got this:

And the second time:

Spring Cloud Load Balancer automatically distributed the load!

It served the first hit using the instance deployed on port 8082 and then using the instance deployed on port 8086!

That’s it!

Recommended:

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading