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.
In order to make Spring Cloud Gateway distribute the load and not stick to one pod I had to:
lb://
instead of http://
in the gateway URIs.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.