springboot+Ribbon realizes load balancing + and how to implement a hand-written load balancing algorithm

springboot+Ribbon realizes load balancing
Ribbon official website address https://github.com/Netflix/ribbon/wiki/Getting-Started
Although Ribbon is now in the maintenance phase, it is still a potential tool because many projects are still using it.
Ribbon is an in-process load balancing tool, which is different from ngnix, which is a centralized load balancer.
Here is an example: ngnix is ​​a gate for us to enter the school, and Ribbon is equivalent to the class we go to after entering the school.
Ribbon uses the polling algorithm by default, load balancing + RestTemplate call, as long as Ribbon is used in conjunction with RestTemplate. If you want to achieve load balancing, you only need to configure the annotation @LoadBalanced in the client's RestTemplate class to implement the polling algorithm

@Configuration
public class ApplicationContextConfig {
    @Bean
    //Load balancing using round robin @LoadBalanced
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

Summary: Ribbon is actually a client component of soft load balancing. It can be used in combination with other clients that require requests, and the combination with eureka is just one example.
Ribbon is available by default in the new spring-cloud-starter-netflix-eureka-client, so there is no need to add pom

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

Ribbon also exists by default in spring-cloud-starter-consul-discovery

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

Ribbon also exists by default in spring-cloud-starter-zookeeper-discovery

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>

If there are other default Ribbon s in the future, it will be updated again
What other load balancing algorithms does Ribbon come up with by default?

com.netflix.loadbalancer.RoundRobinRule polling

com.netflix.loadbalancer.RandomRule random

com.netflix.loadbalancer.RetryRule first follow RoundRobinRule The strategy to obtain the service, if the service fails to be obtained, it will retry within the specified time

WeightedResponseTimeRule right RoundRobinRule The expansion of the instance, the faster the response speed, the greater the selection weight, the easier it is to be selected

BestAvailableRule Services that are in a circuit breaker tripped state due to multiple access failures are filtered first, and then the one with the least concurrency is selected

AvailabilityFilteringRule First filter out faulty instances, and then select instances with less concurrency

ZoneAvoidanceRule Default rules, compound judgment server performance in the area and server Availability of select servers

These algorithms can be customized to implement Ribbon's load balancing by replacing polling

Here's how to replace the default polling algorithm
What needs special attention here is not to put the implementation configuration class of other algorithms under the package that can be scanned by @ComponentScan. If it is placed under the package that can be scanned, then the configuration class of this Ribbon we customize will be used by Ribbon. client-side sharing, so that the custom effect will not be achieved.
For example, the package that @ComponentScan can scan is com.cn.ribbon, then when we customize the configuration class, we can at least get the last time of the com.cn.ribbon1 path or simply write a different path.
The producer will no longer repeat the new creation. Please see https://blog.csdn.net/qq_39990869/article/details/108795140

Consumers need to modify
Here I will post the modified part and see the link above if you need other content
Create a new path that is not scanned by @ComponentScan and then create a new configuration class MySelfRule under this path

@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule(){
        
        return new RandomRule();//defined as random
         }
         }

Then add the annotation @RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class) to the startup class
This means that a custom load balancing algorithm is used instead of the default round-robin algorithm.

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain.class,args);
    }
}

Start the project running interface and you can see random access.

Write a simple load balancing algorithm
Server polling load balancing principle

Structure tree of various algorithms of Ribbon

Write a simple polling algorithm
Add a method to get the current port number in the producer's controller

@GetMapping(value = "/payment/lb")public String getPaymentLB(){    return serverPort;} 

The consumer side first removes the ApplicationContextBean @LoadBalanced
Write a LoadBalancer interface

public interface LoadBalancer {     
//Collect the total number of machines that can provide services on the server and put them in the list    
ServiceInstance instances(List<ServiceInstance> serviceInstances);} 

Implement LoadBalancer interface

@Component
public class MyLB implements LoadBalancer {   
 private AtomicInteger atomicInteger = new AtomicInteger(0);    //coordinate   
  private final int getAndIncrement(){      
    int current; 
           int next;   
                do { 
                           current = this.atomicInteger.get();    
                                   next = current >= 2147483647 ? 0 : current + 1;   
                                        }while (!this.atomicInteger.compareAndSet(current,next));  //The first parameter is the expected value, the second parameter is the modified value is     
                                           System.out.println("*******number of visits next: "+next);        return next;    }   
                                            @Override 
                                               public ServiceInstance instances(List<ServiceInstance> serviceInstances) { 
                                                //get a list of machines     
                                                  int index = getAndIncrement() %serviceInstances.size(); 
                                                  //Get the subscript position of the server     
                                                     return serviceInstances.get(index);    }} 

controller class

@GetMapping(value = "/consumer/payment/lb")   
  public String getPaymentLB(){     
     List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");      
       if (instances == null || instances.size() <= 0){     
              return null;     
                 }        
                 ServiceInstance serviceInstance = loadBalancer.instances(instances);      
                   URI uri = serviceInstance.getUri();    
              return restTemplate.getForObject(uri+"/payment/lb",String.class);    } 

Tags: Algorithm Distribution ribbon

Posted by flash-genie on Sat, 14 May 2022 19:52:48 +0300