undefined## Client Side Load Balancer: Ribbon {#client-side-load-balancer-ribbon}
Ribbon is a client side load balancer which gives you a lot of control over the behaviour of HTTP and TCP clients. Feign already uses Ribbon, so if you are using @FeignClient
then this section also applies.
A central concept in Ribbon is that of the named client. Each load balancer is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer (e.g. using the @FeignClient
annotation). Spring Cloud creates a new ensemble as an ApplicationContext
on demand for each named client using RibbonClientConfiguration
. This contains (amongst other things) an ILoadBalancer
, a RestClient
, and a ServerListFilter
.
Customizing the Ribbon Client
You can configure some bits of a Ribbon client using external properties in <client>.ribbon.*
, which is no different than using the Netflix APIs natively, except that you can use Spring Boot configuration files. The native options can be inspected as static fields in CommonClientConfigKey
(part of ribbon-core).
Spring Cloud also lets you take full control of the client by declaring additional configuration (on top of the RibbonClientConfiguration
) using @RibbonClient
. Example:
@Configuration
@RibbonClient(name = "foo", configuration = FooConfiguration.class)
public class TestConfiguration {
}
In this case the client is composed from the components already in RibbonClientConfiguration
together with any in FooConfiguration
(where the latter generally will override the former).
Warning | The FooConfiguration has to be @Configuration but take care that it is not in a @ComponentScan for the main application context, otherwise it will be shared by all the @RibbonClients . If you use @ComponentScan (or @SpringBootApplication ) you need to take steps to avoid it being included (for instance put it in a separate, non-overlapping package, or specify the packages to scan explicitly in the @ComponentScan ). |
---|---|
Spring Cloud Netflix provides the following beans by default for ribbon (BeanType
beanName: ClassName
):
IClientConfig
ribbonClientConfig:DefaultClientConfigImpl
IRule
ribbonRule:ZoneAvoidanceRule
IPing
ribbonPing:NoOpPing
ServerList<Server> ribbonServerList:
ConfigurationBasedServerList`ServerListFilter<Server>
ribbonServerListFilter:ZonePreferenceServerListFilter
ILoadBalancer
ribbonLoadBalancer:ZoneAwareLoadBalancer
Creating a bean of one of those type and placing it in a @RibbonClient
configuration (such as FooConfiguration
above) allows you to override each one of the beans described. Example:
@Configuration
public class FooConfiguration {
@Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
}
This replaces the NoOpPing
with PingUrl
.
Using Ribbon with Eureka
When Eureka is used in conjunction with Ribbon the ribbonServerList
is overridden with an extension of DiscoveryEnabledNIWSServerList
which populates the list of servers from Eureka. It also replaces the IPing
interface with NIWSDiscoveryPing
which delegates to Eureka to determine if a server is up. The ServerList
that is installed by default is a DomainExtractingServerList
and the purpose of this is to make physical metadata available to the load balancer without using AWS AMI metadata (which is what Netflix relies on). By default the server list will be constructed with "zone" information as provided in the instance metadata (so on the client set eureka.instance.metadataMap.zone
), and if that is missing it can use the domain name from the server hostname as a proxy for zone (if the flag approximateZoneFromDomain
is set). Once the zone information is available it can be used in a ServerListFilter
(by default it will be used to locate a server in the same zone as the client because the default is a ZonePreferenceServerListFilter
).
Example: How to Use Ribbon Without Eureka
Eureka is a convenient way to abstract the discovery of remote servers so you don’t have to hard code their URLs in clients, but if you prefer not to use it, Ribbon and Feign are still quite amenable. Suppose you have declared a @RibbonClient
for "stores", and Eureka is not in use (and not even on the classpath). The Ribbon client defaults to a configured server list, and you can supply the configuration like this
application.yml
stores: ribbon: listOfServers: example.com,google.com
Example: Disable Eureka use in Ribbon
Setting the property ribbon.eureka.enabled = false
will explicitly disable the use of Eureka in Ribbon.
application.yml
ribbon: eureka: enabled: false
Using the Ribbon API Directly
You can also use the LoadBalancerClient
directly. Example:
public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer;
public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}