How do I configure Spring load balancing strategy to use the instance that is currently having least traffic?

472 views Asked by At

I'm using spring cloud load balancer as a client side load balancer in a spring microservice project. I know by default Spring load balancer uses round robin strategy. But for my use case Least connections strategy is best suited. Where the instance handling least number of connections get the request routed to it. After digging through docs I have found @LoadBalancerClient annotation lets you canfigure the routing algorithm. So, I did this:

@Configuration
@LoadBalancerClient(configuration = BalancerConfig.class)
public class RestConfig {
    @Bean
    @LoadBalanced
    RestTemplate restClient(RestTemplateBuilder builder) {
        return builder.build();
    }
}  

For the class BalancerConfig.java I have:

@Configuration
public class BalancerConfig {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
         // currently selects an instance randomly of a given service.
        // but I want to switch it to use the instance that is currently having least 
       // traffic
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

Please tell me is it even possible with Spring application gateway?

1

There are 1 answers

2
DingHao On

If you want all clients to use a custom policy, you just only need to define a ReactorLoadBalancer bean as below

@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                        LoadBalancerClientFactory loadBalancerClientFactory) {
    String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
    return new RandomLoadBalancer(loadBalancerClientFactory
            .getLazyProvider(name, ServiceInstanceListSupplier.class),
            name);
}

But if you want to customize a different policy for each client,you need to do like this

public class RestConfig {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

Configure two routes

spring.cloud.gateway.routes[0].id=web
spring.cloud.gateway.routes[0].uri=lb://web
spring.cloud.gateway.routes[0].predicates[0]=Path=/web/**
spring.cloud.gateway.routes[1].id=reactive-web
spring.cloud.gateway.routes[1].uri=lb://reactive-web
spring.cloud.gateway.routes[1].predicates[0]=Path=/reactive/**

Run GateWayApplication

@LoadBalancerClient(value = "reactive-web",configuration = RestConfig .class)
@SpringBootApplication
public class GateWayApplication {

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

}

In this way, the first route uses RoundRobinLoadBalancer, and the second route uses RandomLoadBalancer.