【你好Ribbon】十二:Ribbon负载均衡五大组件之服务列表更新器-ServerListUpdater

前言

我们知道Ribbon的负载均衡功能 最主要的功能就是对服务器列表的维护,我们前面也说到 ServerList 用来提供一个服务器的列表、ServerListFilter 用来过滤服务列表,今天我们再来看一个更服务列表有关的组件 ServerListUpdater

ServerListUpdater继承关系

在这里插入图片描述
ServerListUpdater 在Ribbon中只有两个实现。其中EurekaNotificationServerListUpdater 和Eureka有关 此处不作介绍。
我们即可认为PollingServerListUpdater 在这里是默认且唯一对ServerListUpdater的实现。

ServerListUpdater接口方法介绍

    public interface UpdateAction {
        void doUpdate();
    }
    void start(UpdateAction updateAction);
    void stop();
    String getLastUpdate();
    long getDurationSinceLastUpdateMs();
    int getNumberMissedCycles();
    int getCoreThreads();
  • UpdateAction: 内部接口 一般会以函数接口的方式来使用。具体更新的动作,所以从这里可以看出 ServerListUpdater 它只是相当于一个调度器 维护了调度器的策略而已。而真正的调度的执行的动作是UpdateAction
  • start: 使用具体的调度策略 开启一个调度任务。
  • stop:停止服务列表更新器运行
  • getLastUpdate: 获取最后一次更新时间
  • getDurationSinceLastUpdateMs: 自上次更新以来的毫秒数
  • getNumberMissedCycles:错过更新周期的数量
  • getCoreThreads: 核心线程数量

PollingServerListUpdater

PollingServerListUpdater是现阶段唯一对ServerListUpdater的实现。既然是调度器 那么核心就是对线程池的实现设置等操作。

单例线程池的创建

PollingServerListUpdater创建单例的方式是通过内部类静态域的加载的方式来创建。

private static class LazyHolder {
        private final static String CORE_THREAD = "DynamicServerListLoadBalancer.ThreadPoolSize";
        private final static DynamicIntProperty poolSizeProp = new DynamicIntProperty(CORE_THREAD, 2);
        private static Thread _shutdownThread;
        static ScheduledThreadPoolExecutor _serverListRefreshExecutor = null;
        static {
            int coreSize = poolSizeProp.get();
            ThreadFactory factory = (new ThreadFactoryBuilder())
                    .setNameFormat("PollingServerListUpdater-%d")
                    .setDaemon(true)
                    .build();
            _serverListRefreshExecutor = new ScheduledThreadPoolExecutor(coreSize, factory);
            poolSizeProp.addCallback(new Runnable() {
                @Override
                public void run() {
                    _serverListRefreshExecutor.setCorePoolSize(poolSizeProp.get());
                }

            });
            _shutdownThread = new Thread(new Runnable() {
                public void run() {
                    logger.info("Shutting down the Executor Pool for PollingServerListUpdater");
                    shutdownExecutorPool();
                }
            });
            Runtime.getRuntime().addShutdownHook(_shutdownThread);
        }

        private static void shutdownExecutorPool() {
            if (_serverListRefreshExecutor != null) {
                _serverListRefreshExecutor.shutdown();

                if (_shutdownThread != null) {
                    try {
                        Runtime.getRuntime().removeShutdownHook(_shutdownThread);
                    } catch (IllegalStateException ise) {
                    }
                }

            }
        }
    }
  • DynamicServerListLoadBalancer.ThreadPoolSize 配置调度器核心线程数量,默认2个。并且支持动态的更新核心线程数

成员属性

	private static long LISTOFSERVERS_CACHE_UPDATE_DELAY = 1000; 
    private static int LISTOFSERVERS_CACHE_REPEAT_INTERVAL = 30 * 1000; 
	private final AtomicBoolean isActive = new AtomicBoolean(false);
    private volatile long lastUpdated = System.currentTimeMillis();
    private final long initialDelayMs;
    private final long refreshIntervalMs;
    private volatile ScheduledFuture<?> scheduledFuture;
  • isActive:当前调度器任务是否是活跃状态中 只有调用start()方法才会使调度器变成活跃状态。
  • lastUpdated:任务调用执行一次updateAction.doUpdate()后记录该
  • initialDelayMs: 默认值是LISTOFSERVERS_CACHE_UPDATE_DELAY也就是延迟1000ms开始执行
  • refreshIntervalMs:默认值是LISTOFSERVERS_CACHE_REPEAT_INTERVAL也就是30s执行一次,可以通过<clientName>.ribbon.ServerListRefreshInterval 来配置刷新时间。
  • scheduledFuture 调度结果

start方法

 @Override
    public synchronized void start(final UpdateAction updateAction) {
        if (isActive.compareAndSet(false, true)) {
            final Runnable wrapperRunnable = new Runnable() {
                @Override
                public void run() {
                    if (!isActive.get()) {
                        if (scheduledFuture != null) {
                            scheduledFuture.cancel(true);
                        }
                        return;
                    }
                    try {
                        updateAction.doUpdate();
                        lastUpdated = System.currentTimeMillis();
                    } catch (Exception e) {
                        logger.warn("Failed one update cycle", e);
                    }
                }
            };
            scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(
                    wrapperRunnable,
                    initialDelayMs,
                    refreshIntervalMs,
                    TimeUnit.MILLISECONDS
            );
        } else {
            logger.info("Already active, no-op");
        }
    }

上面的方法很简单,就是启动一个任务调度器 但是条件是isActive为false的时候才能启动。

其他的方法就不单独介绍了,整体来说 ServerListUpdater 还是比较简单的。主要的更新逻辑还是在UpdateAction中来实现的。

总结

服务列表的更新策略 和Archaius的动态配置的调度策略有点类似 可以对比 AbstractPollingScheduler。一般来说ServerListUpdater是和ServerListServerListFilter组件来搭配使用。
到目前为止,Ribbon的五大组件都简单的介绍了一遍IPingIRuleServerListServerListFilterServerListUpdater。Ribbon的LoadBalance就是对这些基础组件的组合协调。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值