Spring Cloud learning notes -- 05 Ribbon load balancing service call

catalogue

Introduction to Ribbon

RestTemplate: Official Website Link

Ribbon core component IRule

Ribbon load balancing algorithm

A load balancing algorithm

Introduction to Ribbon

Spring Cloud Ribbon It is a set of client load balancing tools based on Netflix Ribbon. In short, Ribbon It is an open source project released by Netflix. Its main function is to provide software load balancing algorithm and service invocation on the client. Ribbon client component provides a series of perfect configuration items, such as connection timeout, Retry, etc. Simply put, list all the machines behind the load balancer (LB) in the configuration file. The ribbon will automatically help you connect these machines based on certain rules (such as simple polling, random connection, etc.). It is easy for us to use the ribbon to implement a custom load balancing algorithm.

Load Balance:

Simply put, the user's requests are evenly distributed to multiple services, so as to achieve the HA (high availability) of the system. Common load balancing include software Ngnix, LVS, hardware F5, etc.

Ribbon local load balancing client VS Nginx server load balancing difference:

Nginx is server load balancing. All requests from the client will be handed over to nginx, and then nginx will forward the requests. That is, load balancing is realized by the server.

Ribbon local load balancing, when calling the micro service interface, will obtain the registration information service list in the registry and cache it to the JVM local, so as to realize the RPC remote service call technology locally.

Centralized load balancing: an independent LB facility (which can be hardware, such as F5, or software, such as Nginx) is used between the service consumer and the service provider, and the facility is responsible for forwarding the access request to the service provider through some policy;

Program load balancing: integrate LB logic into the consumer. The consumer knows which addresses are available from the service registry, and then selects an appropriate server from these addresses. Ribbon belongs to in-process lb, which is just a class library integrated into the consumer process, through which the consumer obtains the address of the service provider.

Ribbon is actually a client component of soft load balancing. It can be used in combination with other clients requiring requests. The combination with eureka is just one example.

Ribbon # works in two steps

Step 1: first select Eureka server, which gives priority to servers with less load in the same region;

The second step is to select an address from the service registration list obtained from the server according to the policy specified by the user. The Ribbon provides a variety of strategies, such as polling, random and weighting according to the response time.

The main function of Ribbon is load balancing + RestTemplate call

Eureka contains Ribbon

Ribbon's {Maven coordinates

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-ribbon</artifactId>
</dependency>

RestTemplate: Official website link

The Module adopted by Eureka above is adopted here:

cloud-provider-payment8001
cloud-provider-payment8002
cloud-consumer-order80
cloud-eureka-server7001
cloud-eureka-server7002

In the controller code of cloud-consumer-order80, modify it to the following code

@RestController
@Slf4j
public class OrderController {

//    The stand-alone version is as follows
//    public static final String PAYMENT_URL = "http://localhost:8001";

    // Using microservices
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);

//        return restTemplate.postForEntity(PAYMENT_URL+"/payment/create", payment, CommonResult.class).getBody();
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
        return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
    }

    @GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPayment2(@PathVariable("id") Long id) {
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id,
                CommonResult.class);

        if(entity.getStatusCode().is2xxSuccessful()){
            log.info(entity.getStatusCode().toString());
            return entity.getBody();
        }else{
            return new CommonResult<>(444, "operation failed");
        }
    }
}

getForObject: the returned object is the object converted from the data in the response body, which can be basically understood as JSON

getForEntity: the returned object is ResponseEntity object, which contains some important information, including response header, response status code, response body, etc.

Ribbon core component IRule

IRule: select a service to access from the service list according to a specific algorithm

com.netflix.loadbalancer.RoundRobinRulepolling
com.netflix.loadbalancer.RandomRulerandom
com.netflix.loadbalancer.RetryRuleFirst obtain the service according to the roundrobin rule policy. If the service acquisition fails, it will be retried within the specified time
WeightedResponseTimeRule For the extension of roundrobin rule, the faster the response speed, the greater the instance selection weight, and the easier it is to be selected
BestAvailableRule The service in the circuit breaker tripping state due to multiple access faults will be filtered out first, and then a service with the least concurrency will be selected
AvailabilityFilteringRule First filter out the fault instances, and then select the instances with smaller concurrency
ZoneAvoidanceRuleThe default rule is to judge the performance of the region where the server is located and the availability of the server, and select the server

How to replace the default load balancing algorithm:

1. Modify cloud-consumer-order80

2. Pay attention to the configuration details:

The official document clearly gives a warning: this custom configuration class cannot be placed under the current package and sub package scanned by @ Componentcan, otherwise our custom configuration class will be shared by all Ribbon clients and the purpose of special customization will not be achieved.

3. Create a new package and its contained classes: com atyixuan. rule. MySelfRule

The MySelfRule class is defined as follows:

@Configuration
public class MySelfRule {
    @Bean
    public IRule rule(){
        return new RandomRule();
    }
}

4. Add @ RibbonClient annotation on the main startup class

@EnableEurekaClient
@SpringBootApplication

// Use your own defined IRule configuration class
// CLOUD-PAYMENT-SERVICE indicates the service to be accessed
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
    }
}

5. Test: http://localhost/consumer/payment/get/31

Ribbon load balancing algorithm

Load balancing algorithm: the number of requests of the rest interface% the total number of server clusters = the subscript of the actual calling server location. The rest interface counts from 1 after each service restart

List<ServiceInstance> iinstances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

For example: List [0] instances = 127.0.0.1:8002
       List [1] instances = 127.0.0.1:8001
8001 + 8002 are combined into clusters. There are 2 machines in total, and the total number of clusters is 2. According to the principle of polling algorithm:


When the total number of requests is 1: 1% 2 = 1 and the corresponding subscript position is 1, the service address obtained is 127.0.0.1:8001

When the total request digit is 2: 2% 2 = 0 and the corresponding subscript position is 0, the service address is 127.0.0.1:8002

When the total request digit is 3: 3% 2 = 1 and the corresponding subscript position is 1, the service address is 127.0.0.1:8001

When the total request digit is 4: 4% 2 = 0 and the corresponding subscript position is 0, the service address is 127.0.0.1:8002

And so on

A load balancing algorithm

1. Start the eureka-server7001 and cloud eureka-server7002} service registries first

2. Add in the controller of cloud provider payment8001 and cloud provider payment8002

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

3. Transformation of cloud-consumer-order80

3.1. Comment out the default load balancing comment

@Configuration
public class ApplicationContextConfig {
    @Bean
//    @LoadBalanced / / start load balancing
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

3.2. Create self-defined load balancing interface and its implementation class, com atyixuan. springcloud. lb. loadbalancer, we want the implementation class of the interface to be scanned automatically, so we put the lb package under the package of the main startup class.

public interface LoadBalancer {
    ServiceInstance instance(List<ServiceInstance> serviceInstances);
}
@Component
public class MyLB implements LoadBalancer {

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public final int getAndIncrement() {
        int current;
        int next;

        // Spin lock
        do {
            current = this.atomicInteger.get();
            next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        } while (!this.atomicInteger.compareAndSet(current, next));
        System.out.println("*********** The first " + next + " Several visits");
        return next;
    }

    @Override
    public ServiceInstance instance(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

4. Modify OrderController

@RestController
@Slf4j
public class OrderController {

//    The stand-alone version is as follows
//    public static final String PAYMENT_URL = "http://localhost:8001";

    // Using microservices
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private LoadBalancer loadBalancer;

    @Resource
    private DiscoveryClient discoveryClient;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);

//        return restTemplate.postForEntity(PAYMENT_URL+"/payment/create", payment, CommonResult.class).getBody();
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
        return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
    }

    @GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPayment2(@PathVariable("id") Long id) {
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id,
                CommonResult.class);

        if(entity.getStatusCode().is2xxSuccessful()){
            log.info(entity.getStatusCode().toString());
            return entity.getBody();
        }else{
            return new CommonResult<>(444, "operation failed");
        }
    }

    @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.instance(instances);
        URI uri = serviceInstance.getUri();
        return restTemplate.getForObject(uri+"/payment/lb", String.class);
    }
}

5. Test: http://localhost/consumer/payment/lb

Keywords: Load Balance Spring Cloud ribbon

Added by tomjung09 on Sun, 23 Jan 2022 22:07:08 +0200