Search code examples
spring-bootspring-cloudspring-cloud-gateway

How to load balance requests to all application pods when using Spring Cloud Gateway


I've deployed an application in Kubernetes with two pods. If I directly invoke its Kubernetes service (http://app:8080) it will balance the requests between those two pods using round robin.

The actual runtime contains a Spring Cloud Gateway pod in front of the application, configured this way:

    @Bean
    fun customRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
        logger.info("Gateway configuration: {}", gatewayConfigurationProperties)
        var routes = builder.routes()
        gatewayConfigurationProperties.routes.forEach { service ->
            routes = routes.route(service.key) { r ->
                r.path("${service.value.contextPath}/**")
                    .filters { filters ->
                        filters.requestRateLimiter { rateLimiterConfig ->
                            rateLimiterConfig.rateLimiter = RedisRateLimiter(1000, 1000)
                        }
                    }                  
                    .uri(service.value.uri)
            }
        }
        return routes.build()
    }

gateway:
  routes:
    app:
      uri: http://app:8080
      context-path: /app

I was expecting the gateway to distribute the load between the two pods, however it sticks with one of them

    -----------------------                 ------------ 
--->| spring-cloud-gateway |---calls-----> | app-pod-1 |
    -----------------------           X     ------------
                                      |
                                      |     ------------
                                      ---> | app-pod-2 |
                                            ------------ 

How can I make the gateway balance the requests using round robin?

I tried prefixing the service url with lb:// (uri: lb://app:8080) but I get a 503 error.


Solution

  • In order to make Spring Cloud Gateway distribute the load and not stick to one pod I had to:

    1. Use lb:// instead of http:// in the gateway URIs.
    2. Add the following dependencies:
    implementation("org.springframework.cloud:spring-cloud-loadbalancer")
    implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-fabric8")
    

    With this, SCG will apply a round robin load balance.