1. Background
Spring Cloud Ribbon is a client load balancing tool based on HTTP and TCP, which is implemented based on Netflix Ribbon. Through the encapsulation of Spring Cloud, we can easily automatically convert service-oriented REST template requests into client-side load balanced service calls. Although Spring Cloud Ribbon is just a tool class framework, it does not need to be deployed independently like service registry, configuration center and API gateway, but it exists in almost every micro service and infrastructure built by Spring Cloud. Because the calls between micro services and the request forwarding of API gateway are actually implemented through the Ribbon, including Feign, which we will introduce later. It is also a tool based on the Ribbon. Therefore, the understanding and use of Spring Cloud Ribbon is very important for us to use Spring Cloud to build microservices.
ribbon has been built into many micro service frameworks.
Spring Cloud Hoxton.M2 is the first to integrate the new loadbalancer implementation to replace the Ribbon version.
Spring Cloud Hoxton.M2 is the first release containing both blocking and non-blocking load balancer client implementations as an alternative to Netflix Ribbon which has entered maintenance mode.
Origin of spring cloud loadbalancer
- In 2017, spring began to try to develop a new project spring cloud loadbalancer instead of ribbon. The project is hosted in
Spring cloud incubator
(to mention more, most top projects such as spring cloud and Alibaba have been hatched since then, representing the development direction of spring cloud) - After N months of non maintenance, when I thought spring would give up this project, I suddenly marked it as an archive and migrated it to spring cloud Commons
- Release 2.2 Version 0.m2
2. How to use spring cloud loadbalancer
This is based on the latest Hoxton M2 version can only be used, so configure the spring agent maven Library:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.M2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencyManagement>
Join the Nacos client and use 2.1 In version 0, pay special attention to excluding ribbon dependencies, otherwise the loadbalancer is invalid.
Take spring cloud starter Alibaba Nacos discovery as an example. ribbon dependency has been built in, so it needs to be excluded:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </exclusion> </exclusions> </dependency>
Add the loadbalancer pom coordinates and inherit the spring cloud version number:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency>
The configuration is the same as that of the ribbon, @ LoadBalanced flag:
@Configuration public class LbConfiguration { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } } @GetMapping("/demo") public String doOtherStuff() { return restTemplate.getForObject("http://big-provider-server/demo", String.class); }
3. Source code analysis
The core class is BlockingLoadBalancerClient
The current version only provides the implementation of BlockingLoadBalancerClient. Please pay attention to the Chinese notes
// Note that the deletion retains only the core code public class BlockingLoadBalancerClient implements LoadBalancerClient { @Override public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException { // Query available instances by service name ServiceInstance serviceInstance = choose(serviceId); return execute(serviceId, serviceInstance, request); } @Override public ServiceInstance choose(String serviceId) { // Get load balancing policy ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory .getInstance(serviceId); // Execute load balancing policy to obtain instances Response<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose()) .block(); return loadBalancerResponse.getServer(); } }
Implementation of loadBalancer load balancing strategy:
At present, there is only one roundrobin loadbalancer polling method to select the server
public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer { public Mono<Response<ServiceInstance>> choose(Request request) { ServiceInstanceSupplier supplier = this.serviceInstanceSupplier.getIfAvailable(); return supplier.get().collectList().map(instances -> { if (instances.isEmpty()) { log.warn("No servers available for service: " + this.serviceId); return new EmptyResponse(); } // TODO: enforce order? int pos = Math.abs(this.position.incrementAndGet()); ServiceInstance instance = instances.get(pos % instances.size()); return new DefaultResponse(instance); }); } }
4. Comparison with ribbon
Default load balancing comparison
The ribbon provides the default load balancing policy in 7. Common policies are covered. Generally, we use the ZoneAvoidanceRule to judge the performance of the server area and the availability of the server, and select the server
Configuration richness
- Currently, spring cloud loadbalancer only supports the configuration of retry operation
- ribbon supports timeout, lazy load processing, retry and its integration with hystrix advanced properties
5. Conclusion
Honest and practical ribbon