Implementing Round Robin Load Balancing in Spring Boot Microservices

Round Robin Load Balancing is a method of distributing client requests across multiple servers in a sequential manner. It ensures that each server handles an equal number of requests over time. This approach can be particularly useful for evenly distributing the load and avoiding overburdening a single server, which can lead to better performance and reliability of web applications.

Load Balancing

Load balancing is a method of distributing incoming network traffic across multiple servers. It ensures that no server is redundant, thereby improving overall system performance and reliability. Load balancing helps maximize resources, reduces response time, and prevents overloading any one unit.

Round Robin Load Balancing

Round-robin is a simple load-balancing algorithm that distributes client requests to a group of servers in a round-robin sequence. When the request is received, it is forwarded to the next server in the list. Once the last server in the list is found, the algorithm returns to the first server and the process continues.

Working of Round Robin Load Balancing

  • The Server List: The load balancer can maintains the list of the available servers.
  • Request Distribution: Each incoming requests is forwarded to next server in the list.
  • Circular Order: After the last server in list has received the request then the next request is sent to the first server in the list and so on.

Advantages of Round Robin Load Balancing

  • Simplicity: This algorithm can easy to implement and understand.
  • Fairness: It can ensures the even distribution of the requests across all the servers.
  • Efficiency: It can suitable for the environments with equally powerful servers and uniform request loads.

Implementing Round Robin Load Balancing in Spring Boot

In Spring Boot application, we will use the Spring Cloud LoadBalancer to implement the Round Robin Load Balancing. Spring Cloud LoadBalancer provides the abstraction for the client-side load balancing and it allows us to the distribute requests across the multiple instances of the service.

Key Components:

  • Service Instances: Two or more instances of the service running on the different ports.
  • Load Balancer Configuration: It can be configuration to enable the Round Robin Load Balancing.
  • ServiceInstanceListSupplier: It can custom the supplier to the provide the list of service instances.

Create the Service-1

Step 1: Create a new Spring Boot project using Spring Initializr and add the required dependencies as mentioned below,

  • Spring Web
  • Spring DevTools
  • Lombok

After this step, the project structure will be like below:


Step 2: Open the application.properties file and add the below properties for server port in the project.

spring.application.name=spring-service1
server.port=8081


Step 3: Open the main class and write the below code for the simple endpoint of the Application.

Java
package org.example.springservice1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class SpringService1Application {

    @RestController
    class Service1Controller {
        @GetMapping("/endpoint")
        public String endpoint() {
            return "Service 1 - Instance 1";
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringService1Application.class, args);
    }

}


pom.xml:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.example</groupId>
    <artifactId>spring-service1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-service1</name>
    <description>spring-service1</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


Step 4: Run the Application

Now, we will run the application then it will be start port at 8081.


Create the Service-2

Step 1: Create a new Spring Boot project using Spring Initializr and add the below dependencies,

  • Spring Web
  • Spring DevTools
  • Lombok

After project creation done, the folder structure will be like below.


Step 2: Open the application.properties file and add the configuration for the server port.

spring.application.name=spring-service2
server.port=8082


Step 3: Open the main class and add the below for the simple endpoint of the Application.

Java
package org.example.springservice2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class SpringService2Application {

    @RestController
    class Service2Controller {
        @GetMapping("/endpoint")
        public String endpoint() {
            return "Service 1 - Instance 2";
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringService2Application.class, args);
    }

}


pom.xml:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.example</groupId>
    <artifactId>spring-service2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-service2</name>
    <description>spring-service2</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


Step 4: Run the Application

Now, we will run the application and it will start at port 8082.


Create the Round Robin Load Balancing

Step 1: Create a new Spring Boot project using Spring Initializr and add the below dependencies,

  • Spring Web
  • Spring Cloud LoadBalancing
  • Lombok
  • Spring DevTools

Once the project is created, the folder structure will be like below.


Step 2: Application Configuration

Open the application.properties file and rename it into application.yml, then add the configuration for the load balancer instances of the application.

spring:
  application:
    name: loadbalancer-client

server:
  port: 8080

  cloud:
    loadbalancer:
      instances:
        service1:
          - uri: http://localhost:8081
          - uri: http://localhost:8082


Step 3: Create the DefaultServiceInstance class

Go to src > main > java > org.example.roundrobinbalancing > DefaultServiceInstance and put the below code.

Java
package org.example.roundrobinbalancing;

import org.springframework.cloud.client.ServiceInstance;

import java.net.URI;
import java.util.Collections;
import java.util.Map;

class DefaultServiceInstance implements ServiceInstance {

    private final String instanceId;
    private final String serviceId;
    private final URI uri;
    private final boolean secure;

    public DefaultServiceInstance(String instanceId, String serviceId, URI uri, boolean secure) {
        this.instanceId = instanceId;
        this.serviceId = serviceId;
        this.uri = uri;
        this.secure = secure;
    }

    @Override
    public String getInstanceId() {
        return instanceId;
    }

    @Override
    public String getServiceId() {
        return serviceId;
    }

    @Override
    public String getHost() {
        return uri.getHost();
    }

    @Override
    public int getPort() {
        return uri.getPort();
    }

    @Override
    public boolean isSecure() {
        return secure;
    }

    @Override
    public URI getUri() {
        return uri;
    }

    @Override
    public Map<String, String> getMetadata() {
        return Collections.emptyMap();
    }
}


Step 4: Create the CustomServiceInstanceListSupplier class

Go to src > main > java > org.example.roundrobinbalancing > CustomServiceInstanceListSupplier and put the below code.

Java
package org.example.roundrobinbalancing;


import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.net.URI;
import java.util.List;

@Component
public class CustomServiceInstanceListSupplier implements ServiceInstanceListSupplier {

    private final Environment environment;

    public CustomServiceInstanceListSupplier(Environment environment) {
        this.environment = environment;
    }


    public String getServiceId() {
        return "service1";
    }

    public Flux<List<ServiceInstance>> get() {
        return Flux.just(List.of(
                new DefaultServiceInstance("service1-1", "service1", URI.create("http://localhost:8081"), false),
                new DefaultServiceInstance("service1-2", "service1", URI.create("http://localhost:8082"), false)
        ));
    }
}


Step 5: Create the LoadBalancerConfiguration class

Go to src > main > java > org.example.roundrobinbalancing > LoadBalancerConfiguration and put the below code.

Java
package org.example.roundrobinbalancing;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestTemplate;

@Configuration
public class LoadBalancerConfiguration {

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


Step 6: Create the LoadBalancerController class

Go to src > main > java > org.example.roundrobinbalancing > LoadBalancerController and put the below code.

Java
package org.example.roundrobinbalancing;

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


@RestController
public class LoadBalancerController {

    @Autowired
    private RestTemplate restTemplate;


    @GetMapping("/consume")
    public String consumeService() {
        String serviceUrl = "http://service1/endpoint";
        return restTemplate.getForObject(serviceUrl, String.class);
    }
}


Step 7: Main Class(No Changes are required)

Go to src > main > java > org.example.roundrobinbalancing > RoundRobinBalancingApplication and put the below code.

Java
package org.example.roundrobinbalancing;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RoundRobinBalancingApplication {

    public static void main(String[] args) {
        SpringApplication.run(RoundRobinBalancingApplication.class, args);
    }

}


pom.xml:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.example</groupId>
    <artifactId>round-robin-balancing</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>round-robin-balancing</name>
    <description>round-robin-balancing</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>


Step 8: Run the Application

Now, we will run the application then it will start at port 8080.


Round Robin Load Balancing Endpoint Testing

GET http://localhost:8080/consume

It will start at service 1 – instance 1

Output:


Again send the request:

GET http://localhost:8080/consume

It will start at service 2 – instance 2.

Output:

By the following these steps, we will able to the configure and test the Round Robin Load Balancing implementation in Spring Boot.




Contact Us