Ribbon load balancing

Posted May 27, 20203 min read

concept

Ribbon is client-based load balancing, which is different from nginx reverse proxy load balancing

Guide package

<!-Realize load balancing->
<dependency>
    <groupId> org.springframework.cloud </groupId>
    <artifactId> spring-cloud-starter-netflix-ribbon </artifactId>
</dependency>

Configuration

Since the load balancing of the ribbon is based on the consumer, the provider does not need to change

Consumer

Configuration class:

@Configuration
public class MainConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Start class:

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
    public static void main(String []args) {
        SpringApplication.run(ConsumerApplication.class);
    }
}

Modify the load balancing algorithm

The default is the polling algorithm

PROVIDER:# service id
  ribbon:
    NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule # round robin(load balancing algorithm class)

Write your own load balancing algorithm

Write your own load balancing algorithm because it should implement the IRule interface, and then modify the algorithm in the application configuration. This algorithm class does not need to be injected into the spring container
image.png
According to the calabash painting random algorithm(public class RandomRule extends AbstractLoadBalancerRule)

Algorithm

Special attention point:We directly implement IRule here, in order to obtain ILoadBalancer, we must write setLoadBalancer method, otherwise we can not get the service list

package com.roderick.config;

import com.netflix.loadbalancer. *;

import java.util.List;

/**
* Take turns to visit each service 5 times
* /
public class MyRule implements IRule {
private int count = 0;
private int currentIndex = 0;
private ILoadBalancer loadBalancer;

    public Server choose(ILoadBalancer lb, Object key) {
        if(lb == null) {
            return null;
        }
        Server server = null;

        while(server == null) {
            if(Thread.interrupted()) {
                return null;
            }
            List <Server> upList = lb.getReachableServers(); //List of available services
            List <Server> allList = lb.getAllServers(); //All service list

            int serverCount = allList.size();
            if(serverCount == 0) {
               /*
                 * No servers. End regardless of pass, because subsequent passes
                 * only get more restrictive.
                 * /
                return null;
            }

            if(count <5) {
                server = upList.get(currentIndex);
                count ++; //5
            } else {
                count = 0;
                currentIndex ++; //2
                if(currentIndex> = upList.size()) {//2
                    currentIndex = 0;
                }
                server = upList.get(currentIndex);
            }


            if(server == null) {
               /*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 * /
                Thread.yield();
                continue;
            }

            if(server.isAlive()) {
                return(server);
            }

            //Shouldn't actually happen .. but must be transient or a bug.
            server = null;
            Thread.yield();
        }
        return server;
    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }

    @Override
    public void setLoadBalancer(ILoadBalancer lb) {
        this.loadBalancer = lb; //Note that it needs to be set here, otherwise the service list cannot be obtained
    }

    @Override
    public ILoadBalancer getLoadBalancer() {
        return loadBalancer;
    }
}

Test

@SpringBootTest(classes = ConsumerApplication.class)
public class RibbonLoadBalanceTest {

    @Autowired
    LoadBalancerClient client;

    @Test
    public void loadBalance() {
        for(int i = 0; i <20; i ++) {
            ServiceInstance consumer = client.choose("PROVIDER");
            System.out.println(consumer.getPort());
        }
    }
}

image.png