What is Spring Cloud LoadBalancer and what does the @LoadBalanced annotation do?
answer
- client-side, replaces Ribbon
- @LoadBalanced = qualifier -> interceptor/filter
- host = logical service id, not DNS
- discovery -> pick instance -> rewrite URL
- spring-cloud-starter-loadbalancer
basics
~10 sSpring Cloud LoadBalancer is a client-side load balancer that replaced Netflix Ribbon. @LoadBalanced marks a RestTemplate or WebClient.Builder so URLs using a logical service name resolve to a real instance, spreading calls across instances.
solid answer
~40 sSpring Cloud LoadBalancer (SCLB) is Spring's built-in client-side load balancer, the successor to the now-removed Netflix Ribbon. It ships in spring-cloud-starter-loadbalancer and picks a target instance in the caller, not via a proxy. You annotate a RestTemplate or WebClient.Builder bean with @LoadBalanced. That tells Spring to attach a load-balancing interceptor/filter, so when you call http://order-service/orders/1, 'order-service' is treated as a logical service id (not a DNS host). SCLB asks the discovery client for instances of that service, picks one (round-robin by default), and rewrites the URL to that instance's host:port. This gives you client-side balancing plus resilience: if instances scale up/down, callers adapt without config changes. Without @LoadBalanced, the same URL fails because 'order-service' isn't a resolvable hostname.
code
java · 20 lines@Configuration
class AppConfig {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
class OrderClient {
private final RestTemplate rt;
OrderClient(RestTemplate rt) { this.rt = rt; }
Order fetch(long id) {
// "order-service" is a logical service id resolved by SCLB,
// NOT a DNS hostname. Without @LoadBalanced this throws UnknownHostException.
return rt.getForObject("http://order-service/orders/{id}", Order.class, id);
}
}go deeper
Know it's client-side, replaces Ribbon, and @LoadBalanced lets you call services by name.
Explain that the annotation adds an interceptor/filter and the host is a discovery service id.
Connect @LoadBalanced to LoadBalancerClientFactory, ServiceInstanceListSupplier, and discovery.
Discuss when client-side LB is the wrong choice (mesh/gateway already balancing) and the trade-offs of in-process balancing.
**The problem it solves.** In microservices, a service like `order-service` runs as many instances behind no single fixed address. A caller needs to (a) discover the current set of instances and (b) choose one per request. Spring Cloud LoadBalancer (SCLB) does both in the *client* process — hence *client-side* load balancing — rather than routing through a dedicated load-balancer/proxy. **Replacing Ribbon.** SCLB is the official replacement for **Netflix Ribbon**, which is deprecated and removed from current Spring Cloud. If you see `@RibbonClient`, `IRule`, or `ribbon.*` properties, that's the legacy world; the modern equivalents are `@LoadBalancerClient`, `ReactorLoadBalancer`, and `spring.cloud.loadbalancer.*`. **How @LoadBalanced wires in.** `@LoadBalanced` is a Spring `@Qualifier`. You put it on a bean: ```java @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } ``` SCLB's auto-configuration collects every `@LoadBalanced RestTemplate` and adds a `LoadBalancerInterceptor` (or `RetryLoadBalancerInterceptor` when retries are on) to it. For reactive clients you annotate a `WebClient.Builder`; SCLB adds a `ReactorLoadBalancerExchangeFilterFunction`. **What happens per request.** You call a URL whose host is a **logical service id**, e.g. `http://order-service/orders/1`. The interceptor/filter: 1. Extracts `order-service` as the service id. 2. Uses the `ReactiveLoadBalancer.Factory` (`LoadBalancerClientFactory`) to get that service's `ReactorLoadBalancer`. 3. The load balancer asks a `ServiceInstanceListSupplier` for the current instances (typically from a `DiscoveryClient` — Eureka, Consul, Kubernetes, etc.). 4. It picks one instance (default: round-robin). 5. The URL is rewritten to the chosen instance's real `host:port`, then the request proceeds. **Why the URL must use a service name.** `order-service` is not a DNS name; it's a key into discovery. Without `@LoadBalanced`, the plain `RestTemplate` tries to open a socket to host `order-service` and fails with UnknownHost. The annotation is what turns that pseudo-host into a discovery lookup. **Gotchas.** - You need `spring-cloud-starter-loadbalancer` on the classpath and usually a discovery client. In some starters (like the Eureka client) SCLB is pulled in transitively. - `@LoadBalanced` belongs on the *builder/template bean*, not on the calling method. - A non-annotated `RestTemplate` and a `@LoadBalanced` one can coexist; inject the one you need (use qualifiers). **When to use.** Any time a service calls another service by logical name and you want in-process balancing without a sidecar/proxy. If you already front everything with a service mesh (Istio/Linkerd) or an API gateway doing the balancing, client-side LB may be redundant.
- What happens if you forget @LoadBalanced but still call http://order-service/...?The plain RestTemplate/WebClient treats 'order-service' as a hostname and fails to resolve it (UnknownHostException), because nothing intercepts the request to translate the service id into a real instance.
- Is Spring Cloud LoadBalancer a server-side load balancer like nginx?No. It's client-side: the choosing logic runs inside the caller's JVM, per request. There's no separate proxy hop; the caller talks directly to the chosen instance.
saying these in an interview costs you the question
- Thinking @LoadBalanced makes it server-side / a proxy
- Believing 'order-service' is resolved by DNS rather than discovery
- Saying Ribbon is still the default (it's removed)
- Putting @LoadBalanced on the controller/method instead of the bean