微服务7:Ribbon负载规则和轮询算法

71 阅读3分钟

负载规则

1. IRule接口:

Spring Cloud Ribbon 提供了一个 IRule 接口,该接口主要用来定义负载均衡策略,它有 7 个默认实现类,每一个实现类都是一种负载均衡策略:

序号实现类负载均衡策略
1RoundRobinRule按照线性轮询策略,即按照一定的顺序依次选取服务实例
2RandomRule随机选取一个服务实例
3RetryRule按照 RoundRobinRule(轮询)的策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试(重试时获取服务的策略还是 RoundRobinRule 中定义的策略),如果超过指定时间依然没获取到服务实例则返回 null 。
4WeightedResponseTimeRuleWeightedResponseTimeRule 是 RoundRobinRule 的一个子类,它对 RoundRobinRule 的功能进行了扩展。 根据平均响应时间,来计算所有服务实例的权重,响应时间越短的服务实例权重越高,被选中的概率越大。刚启动时,如果统计信息不足,则使用线性轮询策略,等信息足够时,再切换到 WeightedResponseTimeRule。
5BestAvailableRule继承自 ClientConfigEnabledRoundRobinRule。先过滤点故障或失效的服务实例,然后再选择并发量最小的服务实例。
6AvailabilityFilteringRule先过滤掉故障或失效的服务实例,然后再选择并发量较小的服务实例。
7ZoneAvoidanceRule默认的负载均衡策略,综合判断服务所在区域(zone)的性能和服务(server)的可用性,来选择服务实例。在没有区域的环境下,该策略与轮询(RandomRule)策略类似。

2. 规则切换:

  • Spring Cloud 2020.0之后 Netflix 彻底删除掉了除Eureka外的所有组件,其中包括了Ribbon组件,现有环境事2020.0.05故无法使用,但是官方对其提供Spring Cloud Loadbalancer(关于Spring Cloud Loadbalancer,在spring-cloud-commons中。)的替代方案,此处作一演示,后期会被更为推荐的OpenFeign替代

netflix组件替代方案表

    • 在RibbonRestconfig.java中引入官方提供的负载均衡随机策略代码
package com.zhigong.orders.config;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestTemplate;

/**
 * @author TL
 * @create 2022-04-02 12:13
 * @Description Ribbon负载均衡的RestTemplate配置
 */
@Configuration
public class RibbonRestConfig {


    /**
     * 负载均衡实例
     *
     * @return
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }


    /**
     * Spring Cloud 2020.0.0版本后的负载均衡策略修改为随机方式 https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#switching-between-the-load-balancing-algorithms
     *
     * @param environment
     * @param loadBalancerClientFactory
     * @return
     */
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }

}
    • 消费者主启动类加入自定义配置引入注解@LoadBalancerClients(defaultConfiguration = {RibbonRestConfig.class})
  • Spring Cloud 2020.0之前,引入Ribbon依赖之后进行下述操作

    • 方式一:application.properties中配置参数userservice.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
    • 方式二:使用Java代码自定义Ribbon配置,使用IRule接口实现
package com.zhigong.orders.config;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestTemplate;

/**
 * @author TL
 * @create 2022-04-02 12:13
 * @Description Ribbon负载均衡的RestTemplate配置
 */
@Configuration
public class RibbonRestConfig {


    /**
     * 负载均衡实例
     *
     * @return
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }


    @Bean
    public IRule myRule() {
        // RandomRule 为随机策略
        return  new RandomRule();
    }

}

轮询算法:

负载均衡轮询算法:rest接口第几次请求数%服务器集群总数 = 实际调用服务器位置下标(每次服务启动后rest接口计数从1开始)