What is the default load-balancing algorithm in Spring Cloud LoadBalancer, and how do RoundRobin and Random differ and get configured?
answer
- default = RoundRobinLoadBalancer (AtomicInteger % size)
- Random = uniform pick, de-correlates clients
- no property switch — override ReactorLoadBalancer bean
- @LoadBalancerClient(configuration=...) per service
- config class OUTSIDE main @ComponentScan
basics
~20 sThe default is RoundRobinLoadBalancer, which cycles instances in order using an atomic counter. RandomLoadBalancer picks a random instance each time. You switch by defining a ReactorLoadBalancer bean in a per-client configuration class referenced via @LoadBalancerClient.
solid answer
~40 sSCLB's default ReactorLoadBalancer is RoundRobinLoadBalancer: it keeps an AtomicInteger position and, per request, does position++ mod instanceCount, so requests spread evenly and predictably. RandomLoadBalancer instead chooses a uniformly random instance each call — useful to avoid synchronized stepping across many clients, but with slightly less even short-term distribution. Both implement ReactorLoadBalancer<ServiceInstance> and pull instances from a ServiceInstanceListSupplier. To change the algorithm you don't edit a property; you provide a custom @Bean ReactorLoadBalancer<ServiceInstance> returning a RandomLoadBalancer, placed in a plain configuration class that is NOT component-scanned by the main app, and attach it with @LoadBalancerClient(value="order-service", configuration=Cfg.class) — or @LoadBalancerClients(defaultConfiguration=...) to apply globally. Placement matters: if the config is picked up by the main @ComponentScan it leaks to every client.
code
java · 18 lines// Plain config class — deliberately NOT on the main @ComponentScan path.
public class RandomLbConfig {
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
Environment env,
LoadBalancerClientFactory factory) {
String serviceId = env.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
factory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class),
serviceId);
}
}
// Attach it to one service (or use @LoadBalancerClients(defaultConfiguration=...) for all).
@Configuration
@LoadBalancerClient(value = "order-service", configuration = RandomLbConfig.class)
class LbClientConfig { }go deeper
Know round-robin is default and random is an alternative.
Explain the AtomicInteger mechanic and that switching means overriding a bean via @LoadBalancerClient.
Discuss synchronized-stepping motivation for random and the per-service child-context config isolation.
Reason about weighting/zone strategies at the supplier layer vs the load-balancer, and correlated-load failure modes.
**The choosing strategy is the ReactorLoadBalancer.** SCLB abstracts the pick-an-instance decision behind `ReactorLoadBalancer<ServiceInstance>` (a specialization of `ReactiveLoadBalancer<ServiceInstance>`), whose core method is `Publisher<Response<ServiceInstance>> choose(Request request)`. **Default: RoundRobinLoadBalancer.** Out of the box SCLB registers `RoundRobinLoadBalancer`. It holds an `AtomicInteger` seed/position and per call computes `position = (previous + 1)`; the chosen index is `position % instances.size()`. Effect: instances are visited in strict rotation, giving very even distribution for a single client. The counter is per load-balancer (per service, per client JVM), so two different client apps rotate independently. **Alternative: RandomLoadBalancer.** Picks a uniformly random index each request. Trade-offs vs round-robin: - Random avoids *synchronized stepping* — when many identical clients start together, round-robin counters can march in lockstep and hammer the same instance at the same tick; random de-correlates them. - Round-robin gives smoother even distribution over short windows; random only evens out over many requests and can briefly cluster. **How to switch — configuration, not a property.** There is no `spring.cloud.loadbalancer.algorithm=random` flag. You override the bean: 1. Write a **plain class** (not `@Configuration` on the main scan path) exposing `@Bean ReactorLoadBalancer<ServiceInstance>` that returns a `RandomLoadBalancer`. 2. Attach it to a service with `@LoadBalancerClient(value = "order-service", configuration = CustomLbConfig.class)`, or to all services via `@LoadBalancerClients(defaultConfiguration = CustomLbConfig.class)`. The reason it must be a `RandomLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> supplierProvider, String serviceId)` is that each per-service child context injects that service's supplier lazily. **Critical gotcha — config placement.** `LoadBalancerClientFactory` builds an **isolated child ApplicationContext per service id**. Your custom config is imported into that child context only. If you instead annotate it with `@Configuration` and let the main application's `@ComponentScan` pick it up, the bean lands in the parent context and silently becomes the default for **every** service — usually not intended. So keep custom LB config classes in a package outside the main scan. **Other supplied strategies.** Beyond round-robin/random, SCLB offers behaviors layered via the `ServiceInstanceListSupplier` (zone preference, same-instance preference, hint-based, weighted via `WeightedServiceInstanceListSupplier`). Those change *which instances are eligible/weighted*, while the `ReactorLoadBalancer` chooses among them. Weighting is often done at the supplier level, not by a distinct load-balancer class. **When to use which.** Default round-robin is fine for most cases. Prefer random when you have many homogeneous clients starting simultaneously and want to avoid correlated load spikes, or when instances are behind their own queues where perfect evenness doesn't matter.
- Why can placing the custom LB config in a component-scanned package cause bugs?LoadBalancerClientFactory creates a child context per service. A config meant for one service, if caught by the main @ComponentScan, lands in the parent context and becomes the default for every service — overriding balancing globally by accident.
- Is there a property to select round-robin vs random?No. The algorithm is chosen by which ReactorLoadBalancer bean is present. You override it in a per-client configuration class; properties only tune things like caching, retries, and health checks.
saying these in an interview costs you the question
- Claiming you set the algorithm via a spring.cloud.loadbalancer property
- Putting the custom config in the main scan and not realizing it applies globally
- Saying random gives more even distribution than round-robin
- Thinking the round-robin counter is shared across client instances