【你好Ribbon】十四:Ribbon具有动态的服务列表能力的负载均衡器-DynamicServerListLoadBalancer

前言

上一篇文章探讨了最基础的负载均衡器BaseLoadBalancer,该负载均衡器提供了最基础的负载能力拥有IPingIRule两个主要的组件。但是BaseLoadBalancer有如下的缺点:

  • 服务列表无法做到动态化 例如注册了一个实例(新增一个配置) 它是无法感知的
  • 无法做到服务过滤,比如某些服务负载已经很高了 或者已经熔断了
  • 无法做到zone区域识别

DynamicServerListLoadBalancer介绍

DynamicServerListLoadBalancer负载均衡器在BaseLoadBalancer的基础上进一步集成了ServerListFilterServerListUpdaterServerList三大组件到此五大组件已经全部出现。所以DynamicServerListLoadBalancer具有如下能力:可定制服务列表(例如可指定从注册中心获取,可从配置文件中获取)、可动态获取服务列表(例如配置文件中配置的服务列表变更可自动获取,注册中心中新增一个服务负载均衡可自动获取),服务过滤能力(可对某些条件的服务器过滤)。

DynamicServerListLoadBalancer初始化

构造方法

  public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping,
                                         ServerList<T> serverList, ServerListFilter<T> filter,
                                         ServerListUpdater serverListUpdater) {
        super(clientConfig, rule, ping);
        this.serverListImpl = serverList;
        this.filter = filter;
        this.serverListUpdater = serverListUpdater;
        if (filter instanceof AbstractServerListFilter) {
            ((AbstractServerListFilter) filter).setLoadBalancerStats(getLoadBalancerStats());
        }
        restOfInit(clientConfig);
    }
  • super(clientConfig, rule, ping):调用父构造器对IPingIRule组件初始化以及设计Ping的间隔时间和最大的Ping时间。
  • 接着就是初始化三大组件(ServerListServerListUpdaterServerListFilter)
  • restOfInit() 最重要的就是通过ServerList获取初始化服务列表启动ServerListUpdater开始动态更新

restOfInit()

void restOfInit(IClientConfig clientConfig) {
   boolean primeConnection = this.isEnablePrimingConnections();
    this.setEnablePrimingConnections(false);
    enableAndInitLearnNewServersFeature();
    updateListOfServers();
    if (primeConnection && this.getPrimeConnections() != null) {
        this.getPrimeConnections()
                .primeConnections(getReachableServers());
    }
    this.setEnablePrimingConnections(primeConnection);
}

这个方法最重要的这两句代码:enableAndInitLearnNewServersFeature(); updateListOfServers();从名字不难看出他们的功能分别是 启用并且初始化学习新服务的功能和更新服务列表enableAndInitLearnNewServersFeature很简单 我们猜都能猜得到 肯定是调用ServerListUpdaterstart方法开启。看一下下面的实现:

   public void enableAndInitLearnNewServersFeature() {
        serverListUpdater.start(updateAction);
    }

可以把ServerListUpdater理解成一个定时器 具体要执行的逻辑需要我们通过UpdateAction指定过去。下面是DynamicServerListLoadBalancerServerListUpdater指定的执行逻辑。可以看到就是调用当前类的updateListOfServers()方法。和restOfInit()里面的部分逻辑是类似的。

  protected final ServerListUpdater.UpdateAction updateAction = new ServerListUpdater.UpdateAction() {
        @Override
        public void doUpdate() {
            updateListOfServers();
        }
    };

updateListOfServers() 更新服务列表

上面我们看到ServerListUpdater也是通过调用updateListOfServers()来实现动态更新服务器列表的。该方法很简单但是很重要,因为它集成了ServerListServerListFilter的操作。

  public void updateListOfServers() {
        List<T> servers = new ArrayList<T>();
        if (serverListImpl != null) {
            servers = serverListImpl.getUpdatedListOfServers();
            if (filter != null) {
                servers = filter.getFilteredListOfServers(servers);
            }
        }
        updateAllServerList(servers);
    }

先从ServerList中获取服务列表 然后通过ServerListFilter来过滤服务列表,最终把过滤之后的服务列表传递给updateAllServerList方法。

updateAllServerList()

 protected void updateAllServerList(List<T> ls) {
   if (serverListUpdateInProgress.compareAndSet(false, true)) {
       try {
           for (T s : ls) {
               s.setAlive(true);
           }
           setServersList(ls);
           super.forceQuickPing();
       } finally {
           serverListUpdateInProgress.set(false);
       }
   }
}

上述方法初始化Serveralive 默认为true。然后通过IPing来改变该值。上一篇文章中我们对Ping的过程做了一个简单的梳理,这里就不作赘述。【你好Ribbon】十二:Ribbon负载均衡器接口ILoadBalancer-最基础的负载均衡器BaseLoadBalancer

setServersList()

 @Override
public void setServersList(List lsrv) {
  //这个逻辑我们上一篇文章已经分析过 
   super.setServersList(lsrv);
   //除了设置服务列表之外 下面主要是构建区域服务列表 然后设置到负载均衡指标统计中
   List<T> serverList = (List<T>) lsrv;
   Map<String, List<Server>> serversInZones = new HashMap<String, List<Server>>();
   for (Server server : serverList) {
       getLoadBalancerStats().getSingleServerStat(server);
       String zone = server.getZone();
       if (zone != null) {
           zone = zone.toLowerCase();
           List<Server> servers = serversInZones.get(zone);
           if (servers == null) {
               servers = new ArrayList<Server>();
               serversInZones.put(zone, servers);
           }
           servers.add(server);
       }
   }
   setServerListForZones(serversInZones);
}
  • 设置负载均衡服务列表super.setServersList(lsrv);
  • 构造区域服务列表映射关系serversInZones将此对应关系设置进LoadBalancerStats

如何使用DynamicServerListLoadBalancer

配置config.peoperties如下:

coredy.ribbon.listOfServers=172.10.1.11,172.10.1.12

示例代码:

@Test
  public void test1(){
    IClientConfig config = DefaultClientConfigImpl.getClientConfigWithDefaultValues("coredy");
    IRule rule = new RoundRobinRule();
    IPing ping  = new DummyPing();
    ConfigurationBasedServerList serverList = new ConfigurationBasedServerList();
    serverList.initWithNiwsConfig(config);
    //使用默认值 1秒后开始执行 然后30s重复执行
    ServerListUpdater serverListUpdater = new PollingServerListUpdater();
    ILoadBalancer loadBalancer
        = new DynamicServerListLoadBalancer(config , rule , ping , serverList , null , serverListUpdater);
    while (true){
      Server server = loadBalancer.chooseServer(null);
      System.out.println(server);
      sleep(1000);
    }
  }

在程序运行的过程中向config.properties文件中增加一个server。

coredy.ribbon.listOfServers=172.10.1.11,172.10.1.12,172.10.1.13

增加完一定要recompile一次 否则不会加载。如下图右键config.peoperties
在这里插入图片描述

运行结果如下:
在这里插入图片描述

总结

DynamicServerListLoadBalancer 几乎具备了 负载均衡器该具备的所有的功能,它集成了Ribbon的五大负载均衡组件 所有也是一个应用比较多的一个负载均衡器。

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值