Spring cloud learning 6: Ribbon load balancing

Keywords: Load Balance Spring Cloud ribbon

1, Concept: ribbon


2, ribbon utility

3, Realize

3.1 client configuration: spring cloud-consumer-dept-80 uses Ribbon

Step 1: first, add two dependencies to the 80 project

<!--Ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
<!--Import Ribbon Import at the same time erueka,Because it wants to find out where the service comes from-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

Step 2: configure: create a configuration class ConfigBean

@Bean
@LoadBalanced  //Ribbon, as long as this annotation is added, the RestTemplate becomes load balancing
public RestTemplate getRestTemplate() {
    return new RestTemplate();
}

Because our consumer client uses RestTemplate to read the service, we let RestTemplate realize load balancing. We only need to add an annotation @ LoadBalanced

Step 3: configure yml

server:
  port: 80

#Eureka configuration
eureka:
  client:
    register-with-eureka: false #Do not register yourself with eureka
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

Step 4: configure the main class: deptconsumer_ eighty

//After the integration of Ribbon and Eureka, the client can call directly without caring about the IP address and port number
@SpringBootApplication
//@EnableEurekaClient / / automatically register with Eureka after the service is started
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}

Step 5: write DeptConsumerController

Finally, another problem is that our RestTemplate implements load balancing, so how to reflect it? Now we just add a comment on it, which is certainly not good. We also need to change the request path of RestTemplate to make it automatically select, rather than write it dead. The address should be a variable and accessed through the service name; Not Eureka name

//private static final String REST_URL_PREFIX = "http://localhost:8001";
//When using Ribbon for load balancing, it should not be written or dead. The address should be a variable and accessed through the service name
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";


Finally, start 7001, 7002 and 7003 projects, and then start 8001 project. After 8001 project is registered in three of them, start 80 projects

Then visit http://localhost/consumer/dept/list You can see the normal return results. Of course, you can't see load balancing here, so you will configure multiple service providers and multiple databases to test the effect of load balancing.

3.2 load balancing using Ribbon

Step 1: create two other databases: db02 and db03



Step 2: create two other service providers: 8002 and 8003

Directly create two sub model s, and then copy all files of 8001 (provide the same service), which are the same, and then change the configuration file

pom.xml dependency

The port number of application.yml, the corresponding database, and instance ID, for example: instance ID: springcloud-provider-dept8002

Note: do not change the following service ID

spring:
  application:
    name: springcloud-provider-dept  # The consistency of three service names is the premise

Then, start

springcloud-config-eureka-7001
springcloud-config-eureka-7002
springcloud-config-eureka-7003
springcloud-provider-dept-8001
springcloud-provider-dept-8002
springcloud-provider-dept-8003
springcloud-consumer-dept-80

Then visit http://localhost/consumer/dept/list , access the database several times. The query data has not changed, but the database has changed



Step 3: Ribbon custom equalization algorithm

You will find that polling means that each service comes in turn, which is also the default algorithm of Ribbon
There is a very important interface: IRule, which is basically implemented by all equalization algorithms

There are so many equalization algorithms, because the default is polling algorithm, that is, roundrobin rule. How do we use other algorithms?

Just register the Bean in the config class of the 80 project

//IRule
//Roundrobin rule: polling
//RandomRule: random
//Availability filtering rule: it will filter out the tripped and failed services ~, and poll the rest
//RetryRule: the service will be obtained according to the polling first. If the service acquisition fails, it will be retried within the specified time
@Bean
public IRule myRule() {
    return new RandomRule(); //The default is polling. Now we use random polling
}

Then start the 80 project and visit http://localhost/consumer/dept/list , visit the database several times and find that there is no rule to follow every time

Optimize previous step

We should learn to customize the load balancing algorithm. In order to reflect that we have used the custom load balancing algorithm, we should build the package in the same level directory of the main startup class (official suggestion)

Comment out the Bean just written in ConfigBean. Let's imitate its algorithm and write our own algorithm

Step 1: write a configuration class


In the main class configuration, in order to scan the configuration class

Step 2: write a custom method

public class KuangRandomRule extends AbstractLoadBalancerRule {

    //Visit each machine 5 times and change to the next service (3 in total)
    //total = 0, default = 0. If = 5, we point to the next service node
    //index = 0, default = 0, if total=5, then index+1,

    private int total = 0; //Number of calls
    private int currentIndex = 0; //Who is currently providing services

    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(); //Access to living services
            List<Server> allList = lb.getAllServers();  //Access to all services

            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }

            //=============================================================

            if (total < 5) {
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= serverCount) {
                    currentIndex = 0;
                }
            }
            server = upList.get(currentIndex);
            //=============================================================
            if (server == null) {
                Thread.yield();
                continue;
            }

            if (server.isAlive()) {
                return (server);
            }
            server = null;
            Thread.yield();
        }

        return server;

    }

    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

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

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }
}

Modify a custom configuration class

@Configuration
public class WuRule {

    @Bean
    public IRule myRule() {
        return new KuangRandomRule(); //The default is polling. Now try to use your own custom
    }
}

Then restart the 80 project to access http://localhost/consumer/dept/list , visit more times, and you can find that the accessed services are switched every 5 times

Posted by [-_-] on Wed, 10 Nov 2021 00:37:59 -0800