Ribbon 基础学习

目录

Ribbon 是什么?

如何使用Ribbon?

1. 引入依赖

2. 加注解(RestTemplate整合Ribbon)

3. 编码

Ribbon 是由哪些组件构成?

Ribbon  内置的负载规则有哪些?

  Ribbon 如何细力度配置负载规则?

代码配置

配置属性方式

两种方式对比

Ribbon 如何开启全局配置?

 Ribbon 如何开启饥饿加载?

 Ribbon 如何基于Nacos 的权重实现负载规则?

 Ribbon 如何有些调用同一机房的集群服务?

总结: 

 


 

Ribbon 是什么?

Ribbon 是Netflix 提供的开源客户端负载均衡器,他提供了多种负载均衡规则;

如何使用Ribbon?

1. 引入依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

2. 加注解(RestTemplate整合Ribbon)

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return  new RestTemplate();
    }

3. 编码

 将RestTemplate 调用接口中的ip端口,替换成注册在nacos服务上的服务名称
    eg:
        http://alibaba-nacos/config/get   -- alibaba-nacos 是被调用方注册在nacos 上的服务名

Ribbon 是由哪些组件构成?

接口作用默认值
IclientConfig读取配置DefaultClientConfigImpl
IRule负载均衡规则,选择实例ZoneAvoidanceRule
IPing筛选掉ping不通的实例DumyPing(该类什么不干,认为每个实例都可用,都能ping通)
ServerList交给Ribbon的实例列表Ribbon:ConfigurationBasedServerList
Spring Cloud Alibaba:NacosServerList
ServerListFilter过滤掉不符合条件的实例ZonePreferenceServerListFilter
ILoadBalancerRibbon的入口ZoneAwareLoadBalancer
ServerListUpdater更新交给Ribbon的List的策略PollingServerListUpdater

Ribbon  内置的负载规则有哪些?

规则名称特点
AvailabilityFilteringRule过滤掉一直连接失败的被标记为circuit tripped(电路跳闸)的后端Service,并过滤掉那些高并发的后端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 如何细力度配置负载规则?

Ribbon 规则配置支持代码配置和配置属性方式配置,两种方式各有利弊。详情如下

代码配置

	/**
	* name  被调用接口nacos服务名称
	* configuration ribbion 负责规则实现类
	*/
	@Configuration
    @RibbonClient(name = "alibaba-nacos",configuration = RibbonRuleConfig.class)
    public class RibbonConfig {

    }

 

@Configuration
public class RibbonRuleConfig {

    @Bean
    public IRule getRandomRule(){
        return  new RoundRobinRule();
    }
}

 注意: RibbonRuleConfig 放置的位置需要是spring boot 启动类外的包内,否则会导致父子上下文重叠,从而引发问题;如果Ribbon 配置过程中发生了父子上下文重叠,会产生什么问题呢?
答案是如果RibbonRuleConfig配置在Spring boot 启动类同一个包内,那么这个Ribbon 负载规则 不在是针对服务的,而是一个全局的配置项了。到时候访问其他服务的接口也会调用RibbonRuleConfig 定义的负载规则,无法达到自定义细粒度Ribbon 负载规则配置了


关于父子上下文重叠其他问题可以参考https://blog.csdn.net/hhcccchh/article/details/104022770

配置属性方式

alibaba-nacos:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule

其中 alibaba-nacos 是待调用服务nacos 服务名
NFLoadBalancerRuleClassName 指定的是负责规则类

两种方式对比

代码配置:
优点: 基于代码配置,更加灵活
缺点: 编写时需要注意父子上下文重叠问题,并且每次更改发布需要重新打包部署
配置文件:
优点: 配置直观,修改无需重新部署
缺点: 极端条件下,没有代码配置灵活。但是99% 的情况其实是可以通过配置属性方式来实现的

Ribbon 如何开启全局配置?

/**
*和 细力度配置相对比来说,Ribbon 的全局配置就是将@RibbonClient 替换成@RibbonClients ,细粒度皮*配置的Configuration 变成defaultConfiguration 
*
*/
@RibbonClients(defaultConfiguration = RibbonConfig.class)
public class RibbonConfig {


}

 Ribbon 如何开启饥饿加载?

Ribbion 默认是懒加载的方式,及服务第一调用的时候,才去加载。会导致第一次访问服务的时候速度缓慢.开启饥饿加载只需要在配置文件配置
开启饥饿加载配置方式:

ribbon:
  eager-load:
    enabled: true
    clients: alibaba-nacos

alibaba-nacos 是注册在nacos上的服务名称,多个之间用逗号分隔


 Ribbon 如何基于Nacos 的权重实现负载规则?

Nacos 权重配置的优点是可以基于服务器性能进行对服务器资源的在分配。且可以辅助我们达到服务器灰度下线的能力;实现如下

package com.springcloud.alibaba.consumer.nacosconfig;


import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClient;
import com.alibaba.cloud.nacos.ribbon.ExtendBalancer;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;

import java.util.List;

/**
 * 根据nacos client  进行设置nacos权重匹配规则
 */
@Slf4j
public class NacosWeightRandomV2Rule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Autowired
    private NacosServiceManager nacosServiceManager;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object o) {
        DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
        // 获取服务的名称
        String name = loadBalancer.getName();
        log.info("-----name:{}------",name);
        try {
            NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
            Instance instance = namingService.selectOneHealthyInstance(name);
            return new NacosServer(instance);
        } catch (NacosException e) {
            e.printStackTrace();
            return null;
        }

    }

}

配置文件添加对自定义负载规则的引用:

alibaba-nacos:
  ribbon:
    NFLoadBalancerRuleClassName: com.springcloud.alibaba.consumer.nacosconfig.NacosWeightRandomV2Rule 

 Ribbon 如何有些调用同一机房的集群服务?

更多情况下,为了容灾,我们会对集群进行异地部署。在使用的时候,为了性能,我们常常需要调用同一机房的服务

package com.springcloud.alibaba.consumer.nacosconfig;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.ribbon.ExtendBalancer;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author zj
 * @Date 2021/1/12 16:25
 * ribbon 同机房集群优先调用,同机房宕掉后会调用其他机房集群服务
 */
@Slf4j
public class NacosSameClusterWeightedRule extends AbstractLoadBalancerRule {
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Autowired
    private NacosServiceManager nacosServiceManager;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object o) {
        try {
            // 获取配置文件中的当前服务的集群名称
            String clusterName = nacosDiscoveryProperties.getClusterName();
            DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
            // 获取服务名称
            String name = loadBalancer.getName();
            NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());

            // 获取健康实例的所有服务
            List<Instance> instances = namingService.selectInstances(name, true);
            if (CollectionUtils.isEmpty(instances)){
                return  null;
            }

            // 进行筛选获取相同集群下的服务实例
            List<Instance> instancesToChoose = instances;
            if (!StringUtils.isEmpty(clusterName)){
                List<Instance> collect = instances.stream().filter(instance -> Objects.equals(clusterName, instance.getClusterName())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(collect)){
                    instancesToChoose = collect;
                }else{
                    log.info("跨机房调用");
                }
            }

            Instance hostByRandomWeight2 = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);
            return  new NacosServer(hostByRandomWeight2);
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return null;
    }
}

配置文件添加对自定义规则的引用

alibaba-nacos:
  ribbon:
    NFLoadBalancerRuleClassName: com.springcloud.alibaba.consumer.nacosconfig.NacosSameClusterWeightedRule

Ribbon 如何基于元数据的方式实现不同版本调用不同服务的能力?

参考: http://www.imooc.com/article/288674

总结: 

通过Ribbon 的基础学习,对于负载规则,我们又多了一个思路去实现。本章博文是基于对大目老师Spring cloud alibaba Ribbon 课程的一个记录和总结。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值