Ribbon是什么

Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端(消费者方)负载均衡算法。Ribbon客户端组件提供一系列完善的配置项,如,连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中列出loadBalancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。
Ribbon - 图1

RestTemplate在访问服务的时候加入负载均衡

  1. @Bean
  2. @LoadBalanced //加上该注解就会集成负载均衡
  3. public RestTemplate rt() {
  4. return new RestTemplate();
  5. }
//负载均衡访问:
String value = rt.getForObject("http://注册到nacos的服务名/user/findUser", String.class);
  1. 负载均衡是什么?有什么意义?
  2. cloud里面谁来做负载均衡(LoadBlancedClient)

    Ribbon内置的负载均衡策略

    | 规则名称 | 特点 | | :—- | :—- | | AvailabilityFilteringRule | 过滤掉一直连接失败的被标记为circuit tripped的后端Server,并过滤掉那些高并发的后端Server或则使用一个AvailabilityPredicate来包含过滤Server的逻辑,其实就是检查status里面记录的各个Server的运行状态 | | BestAvailableRule | 选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过 | | RandomRule | 随机选择一个Server | | RetryRule | 对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的Server | | RoundRobinRule | 轮询选择,轮询index,选择index对应位置的Server | | WeightedResponseTimeRule | 根据响应时间加权,响应时间越长,权重越小,被选中的可能性越低 | | ZoneAvoidanceRule | 符合判断Server所Zone的性能和Server的可用性选择Server,在没有Zone的环境下,类似于轮询(RoundRobinRule) |

Ribbon的配置接口(了解)

接口 配置 默认值
IClientConfig 读取配置 DefaultClientConfigImpl
IRule 负载均衡规则,选择实例 ZoneAvoidanceRule
IPing 筛选掉ping不通的实例 DummyPing
ServerList 交给Ribbon的实例列表 Ribbon:ConfigurationBasedServerList
Spring Cloud Alibaba:NacosServerList
ServerListFilter 过滤掉不符合条件的实例 ZonePreferenceServerListFilter
ILoadBalancer Ribbon的入口 ZoneAwareLoadBalancer
ServerListUpdater 更新交给Ribbon的List的策略 PollingServerListUpdater

Ribbon基础配置

Ribbon有两种配置方式,一是java代码配置,一种是属性配置。
代码配置如下:

@Configuration
public class RibbonConfig {
  //添加负载均衡策略对象
  @Bean
  public IRule createIRule() {
    return new WeightRule();
  }
}

把上面的配置类用到主配置上面:

@Configuration
//全局配置
@RibbonClients(defaultConfiguration = RibbonConfig.class)
//局部配置
//@RibbonClient(value = "服务名",configuration = RibbonConfig.class)
public class BaseConfig {
}

属性配置如下:

<clientName>.ribbon: 
  NFLoadBalancerClassName: ILoadBalancer实现类
  NFLoadBalancerRuleClassName: IRule实现类
  NFLoadBalancerPingClassName: IPing实现类
  NIWSServerListClassName: ServerList实现类
  NIWSServerListFilterClassName: ServerListFilter实现类

自定义Ribbon的负载均衡规则

自定义类实现IRule接口或则继承AbstractLoadBalancerRule

public class WeightRule extends AbstractLoadBalancerRule {
        //自身信息对象
        @Autowired
        private NacosDiscoveryProperties nacosDiscoveryProperties;
        //nacos服务管理对象
        @Autowired
        private NacosServiceManager nsm;
        @Override
        public Server choose(Object key) {
            //获取需要访问的服务名
            BaseLoadBalancer ilb = (BaseLoadBalancer)this.getLoadBalancer();
            String name = ilb.getName();
            //获取自身的clusterName
            String clusterName = nacosDiscoveryProperties.getClusterName();
            //获取nacos服务发现对象
            NamingService ns = nsm.getNamingService(nacosDiscoveryProperties.getNacosProperties());
            try {
                //获取所有的需要访问的服务节点
                List<Instance> insts =  ns.getAllInstances(name);
                //过滤出相同集群的节点
                List<Instance> clusterInstances = insts.stream().filter(x -> {
                    if(StringUtils.isNotEmpty(clusterName) && StringUtils.isNotEmpty(x.getClusterName())) {
                        if(clusterName.equals(x.getClusterName())) return true;
                    }
                    return false;
                }).collect(Collectors.toList());
                insts = clusterInstances != null && clusterInstances.size() > 0 ? clusterInstances:insts;
                //通过权重算法获取该服务的一个实例
                Instance instance = MyBalancer.getHostByRandomWeight(insts);
                return new NacosServer(instance);
            } catch (NacosException e) {
                e.printStackTrace();
                return null;
            }
        }
        @Override
        public void initWithNiwsConfig(IClientConfig clientConfig) {
        }
        //拉取权重调用算法
        static class MyBalancer extends Balancer {
          public static Instance getHostByRandomWeight(List<Instance> hosts) {
                 return Balancer.getHostByRandomWeight(hosts);
          }
        }
}