美文网首页Spring cloud
SpringCloud-Ribbon-03设计原理

SpringCloud-Ribbon-03设计原理

作者: 小亮__ | 来源:发表于2019-06-24 07:22 被阅读11次

    Ribbon的核心是基于LoadBalancer负载均衡器来实现的,Ribbon通过ILoadBalancer接口对外提供统一的选择服务器(Server)的功能基础接口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();
    }
    

    其中LoadBalancer内部有如下图的模块组成:


    LoadBalancer模块图

    ServerList模块

    主要是负责维护server列表(新增,更新,删除),接口如下:

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

    实现方式分以下两类,并可以通过<service-name>.ribbon.NIWSServerListClassName,来配置具体的实现方式

    • 基于配置文件:通过配置文件,静态地配置服务器列表,可以使用netflix archaius框架动态监控配置文件的变化,来更新ServerList 信息,通过以下配置开启
      <service name>.ribbon.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList
      
    • 基于服务发现:结合服务发现组件如consul或eureka,实现动态更新服务列表,通过以下配置开启
       <service name>.ribbon.NIWSServerListClassName=com.netflix.loadbalancer.DiscoveryEnabledNIWSServerList
      

    ServerListUpdater模块

    负责在运行时,动态的更新服务状态的方式,可以通过配置<service-name>.ribbon.ServerListUpdaterClassName设置,当前有如下两种实现方式:

    • 基于定时任务的拉取
      <service-name>.ribbon.ServerListUpdaterClassName=com.netflix.loadbalancer.PollingServerListUpdater
      
    • 基于Eureka服务事件通知
      <service-name>.ribbon.ServerListUpdaterClassName=com.netflix.loadbalancer.EurekaNotificationServerListUpdater
      

    ribbon在默认情况下,会采用基于配置的服务列表维护,定时任务按时拉取服务列表的方式,频率为30s.

    ServerListFilter模块

    ServerListFilter的职能很简单,传入一个服务实例列表,过滤出满足过滤条件的服务列表

    public interface ServerListFilter<T extends Server> {
        public List<T> getFilteredListOfServers(List<T> servers);
    }
    

    ZoneAffinityServerListFilterRibbon:Ribbon 的默认ServerListFilter实现,采取了区域优先的过滤策略,与其相关的配置如下

    # 是否开启区域优先,默认false
    <service-name>.ribbon.EnableZoneAffinity=false
    # 是否采取区域排他性,即只返回和当前Zone一致的服务实例
    <service-name>.ribbon.EnableZoneExclusivity=false
    

    ZonePreferenceServerListFilter:继承 ZoneAffinityServerListFilter,在其上增加了扩展,在其返回结果的基础上,再过滤出和本地服务相同区域(zone)的服务列表。
    ServerListSubsetFilter:继承 ZoneAffinityServerListFilter,这个过滤器作用于当Server数量列表特别庞大时(比如有上百个Server实例),这时,长时间保持Http链接也不太合适,可以适当地保留部分服务,舍弃其中一些服务,这样可使释放没必要的链接。

    ServerStats模块

    ServerStats中记录这server的状态信息,如下

    # 当前服务所属的可用区
    zone
    #总请求数量,client每次调用,数量会递增
    totalRequests
    #活动请求计数时间窗
    activeRequestsCountTimeout
    #连续连接失败计数
    successiveConnectionFailureCount
    #连接失败阈值通过属性
    connectionFailureThreshold
    #断路器超时因子
    circuitTrippedTimeoutFactor
    #最大断路器超时秒数
    maxCircuitTrippedTimeout
    #最后连接时间
    lastAccessedTimestamp
    #最后连接失败时间
    lastConnectionFailedTimestamp
    # 首次连接时间
    firstConnectionTimestamp
    ....等其他信息
    

    断路器:当有某个服务存在多个实例时,在请求的过程中,负载均衡器会统计每次请求的情况(请求相应时间,是否发生网络异常等),当出现了请求出现累计重试时,负载均衡器会标识当前服务实例,设置当前服务实例的断路的时间区间,在此区间内,当请求过来时,负载均衡器会将此服务实例从可用服务实例列表中暂时剔除,优先选择其他服务实例,可以通过以下参数设置断路器信息

    # 连续连接失败计数
    successiveConnectionFailureCount
    #连接失败阈值,默认3超过则熔断
    connectionFailureThreshold
    #断路器超时因子
    circuitTrippedTimeoutFactor
    #最大断路器超时秒数
    maxCircuitTrippedTimeout
    ....等其他信息
    

    IPing ,IPingStrategy 接口

    IPing用来检测Server是否可用,ILoadBalancer的实现类维护一个Timer每隔10s检测一次Server的可用状态,其核心方法有:

    public interface IPing {
        //检测服务是否存活
        public boolean isAlive(Server server);
    }
    
    /**
    * 定义Ping服务状态是否有效的策略,是序列化顺序Ping,还是并行的方式Ping,在此过程中,应当保证相互不受影响
     */
    public interface IPingStrategy {
        boolean[] pingServers(IPing ping, Server[] servers);
    }
    

    默认情况下,负载均衡器内部会创建一个周期性定时任务,检查server是否存活,相关配置参数如下

    # Ping定时任务周期,默认30s
    <service-name>.ribbon.NFLoadBalancerPingInterval=30
    #Ping超时时间,默认2s
    <service-name>.ribbon.NFLoadBalancerMaxTotalPingTime=2
    # IPing实现类,Spring Cloud集成下的IPing实现:NIWSDiscoveryPing,
    # 其使用Eureka作为服务注册和发现,则校验服务是否可用,则通过监听Eureka 服务更新来更新Ribbon的Server状态
    <service-name>.ribbon.NFLoadBalancerPingClassName=
    

    IRule 接口

    IRule是负载均衡策略的抽象,ILoadBalancer通过调用IRule的choose()方法返回Server,其核心方法如下:

    public interface IRule{
       // 从负载均衡器中选择一个实例
        public Server choose(Object key);
        // 设置ILoadBalancer 
        public void setLoadBalancer(ILoadBalancer lb);
        public ILoadBalancer getLoadBalancer();    
    }
    

    以下是具体实现类,我们也可以自定义自己的负载均衡策略


    相关文章

      网友评论

        本文标题:SpringCloud-Ribbon-03设计原理

        本文链接:https://www.haomeiwen.com/subject/mrsiqctx.html