ribbon 配置 动态更新_Ribbon架构剖析

本文深入剖析Ribbon的架构,重点介绍了负载均衡管理器及其核心接口,包括服务实例的添加、选择策略、心跳检测和动态更新等功能。详细探讨了不同负载均衡策略如线性轮询、最小请求数、随机选择等,并揭示了如何通过EurekaClient从注册中心获取服务列表并进行动态更新。同时,文章还提到了服务实例的健康检查和过滤机制,为理解Ribbon在微服务中的作用提供了全面的视角。
摘要由CSDN通过智能技术生成

ca6f161f3214722afd2f55c4d671d4a5.png

8aba9891905ddbf3edf4144245790302.png

在学习Ribbon之前,先看一下这张图,这张图完美的把Ribbon的基础架构给描述出来了

这张图的核心是负载均衡管理器,围绕着它的是外面的这5大功能点,咱们就从核心开始看然后再带出来其他的功能

首先看一下负载均衡器的核心接口ILoadBalancer

public interface ILoadBalancer {
    public void addServers(List<Server> newServers);
    public Server chooseServer(Object key);
    public void markServerDown(Server server);
    public List<Server> getReachableServers();
    public List<Server> getAllServers();
}

这个接口中保护了一个基本的负载均衡器所必须的所有功能:

  1. addServers(List)向负载均衡器中添加服务实例
  1. chooseServer(Object)根据负载均衡策略,从负载均衡器中挑选出一个服务实例
  1. markServerDown(Server)下线负载均衡器中的某个具体实例
  1. getReachableServers()返回当前可正常服务的实例列表
  1. getAllServers()返回所有的服务实例列表

接着来看一下这个接口的UML图

991f8450564200da93ec9addf89bec22.png

首先看AbstractLoadBalancer这个类,这个类是ILoadBalancer接口的抽象类实现。在这个抽象类中定义了一个表示服务实例状态的枚举的同时还新增了两个抽象方法:

   public enum ServerGroup{
        ALL,
        STATUS_UP,
        STATUS_NOT_UP
    }
    public abstract List<Server> getServerList(ServerGroup serverGroup);
    public abstract LoadBalancerStats getLoadBalancerStats();
  1. getServerList(ServerGroup):根据分组类型来返回不同的服务实例列表。
  1. getLoadBalancerStats():返回LoadBalancerStatus对象,这个LoadBalancerStats对象是用来存储负载均衡器中各个服务实例当前的属性和统计信息的

AbstractLoadBalancer共有两个实现类,右侧的NoOpLoadBalancer是一个空的实现类,这里可以忽略不计。这里接着继续看BaseLoadBalancer

BaseLoadBalancer是负载均衡器的基础实现类,这个类对于接口ILoadBalancer的所有方法都给予了基础的实现,除此之外还保护了很多重要的对象

两个存储当前服务实例对象的列表,一个是包含所有服务、一个是包含正常服务

@Monitor(name = PREFIX + "AllServerList", type = DataSourceType.INFORMATIONAL)
    protected volatile List<Server> allServerList = Collections
            .synchronizedList(new ArrayList<Server>());
    @Monitor(name = PREFIX + "UpServerList", type = DataSourceType.INFORMATIONAL)
    protected volatile List<Server> upServerList = Collections
            .synchronizedList(new ArrayList<Server>());

存储负载系统器各服务实例属性和统计信息的对象

    protected LoadBalancerStats lbStats;

心跳检测对象

    protected IPing ping = null;

IPing是用来向服务发起心跳检测的,通过心跳检测来判断该服务是否可用。IPing的实现类有以下几种:

  1. PingUrl:使用HttpClient去get请求某个url,判断其是否alive
  1. PingConstant:固定返回某服务是否可用,默认返回true
  1. NoOpPing:没有任何操作,直接返回true
  1. DummyPing:同样是直接返回true
  1. NIWSDiscoveryPing:根据服务的实例对象InstanceInfoInstanceStatus去判断,如果为InstanceStatus.UP,则为可用

心跳检测策略对象IPingStrategy

    private final static SerialPingStrategy DEFAULT_PING_STRATEGY = new SerialPingStrategy();
    protected IPingStrategy pingStrategy = DEFAULT_PING_STRATEGY;

默认实现是线型轮询

负载均衡策略对象

    private final static IRule DEFAULT_RULE = new RoundRobinRule();
    protected IRule rule = DEFAULT_RULE;

IRule是在选择实例的时候的负载均衡策略对象,默认使用的是RoundRobinRule线性轮询

除此之外的实现为:

  1. BestAvailableRule:选择最小请求数
  1. RandomRule:随机选择
  1. RetryRule:轮询重试
  1. WeightedResponseTimeRule:根据响应时间分配权重
  1. ZoneAvoidanceRule:根据服务的分区可用性轮询

现在继续看BaseLoadBalancer的子类DynamicServerListLoadBalancer

这个类对基础负载均衡器做了扩展。扩展的功能如下:

  1. 服务实例运行期间的动态更新
  1. 服务实例的过滤

服务列表

public interface ServerList<T extends Server> {
    /**
     * 获取初始化的服务列表
     */
    public List<T> getInitialListOfServers();
    
    /**
     * 获取更新后的服务列表
     */
    public List<T> getUpdatedListOfServers();   

}

DynamicServerListLoadBalancer中默认使用的服务列表实现类是DomainExtractingServerList,只不过该服务列表内部还定义了一个服务列表,这个服务列表的实现类则是DiscoveryEnabledNIWSServerList

这个最终的服务列表的数据来源则主要依靠EurekaClient从注册中心获取

服务列表更新

这个接口定义了一系列的对服务列表的更新操作

public interface ServerListUpdater {
    //内部接口
    public interface UpdateAction {
    //实现对服务列表的更新操作
        void doUpdate();
    }
    //启动服务更新器
    void start(UpdateAction updateAction);
    //停止服务更新器
    void stop();
    //返回最近的更新时间戳
    String getLastUpdate();
    //返回上一次更新到现在的时间间隔(ms)
    long getDurationSinceLastUpdateMs();
    //返回错过的更新周期数
    int getNumberMissedCycles();
    //返回核心线程数
    int getCoreThreads();
}

它的实现类有两个:

  1. PollingServerListUpdater:通过定时任务进行更新
  1. EurekaNotificationServerListUpdater:利用Eureka的事件监听器来更新

服务列表过滤器

public interface ServerListFilter<T extends Server> {

    public List<T> getFilteredListOfServers(List<T> servers);

}

该接口主要用于根据一些规则过滤传入的服务实例列表,该接口的实现类如下:

  1. ZoneAffinityServerListFilter:基于Eureka的分区规则对服务实例的过滤
  1. DefaultNIWSServerListFilterZoneAffinityServerListFilter的子类且没有做特殊的更新
  1. ServerListSubsetFilter:通过比较服务实例的通信失败数和并发连接数来剔除那些相对不够健康的实例
  1. ZonePreferenceServerListFilter:使用SpringCloud整合eureka和ribbon时默认使用的该过滤器。它实现了通过配置或eureka实例无数据的所属区域(Zone)来过滤出同区域的服务实例

ZoneAwareLoadBalancer则是对DynamicServerListLoadBalancer的扩展,它主要增加了区域过滤的功能

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值