Soul网关源码阅读09-使用http长轮询同步数据(02)

接着上一篇,继续解析一下 HttpLongPollingDataChangedListener 类。

  • org.dromara.soul.admin.listener.http.HttpLongPollingDataChangedListener

1、提供给网关测,负责长轮询调用。

// 执行http长轮询
public void doLongPolling(final HttpServletRequest request, final HttpServletResponse response) {
    ......
    // AsyncContext.settimeout() does not timeout properly, so you have to control it yourself
    asyncContext.setTimeout(0L);
    // block client's thread,执行一个线程任务
    scheduler.execute(new LongPollingClient(asyncContext, clientIp, HttpConstants.SERVER_MAX_HOLD_TIMEOUT));
}

2、创建并执行在给定延迟后启用的一次性操作,这里延迟60s

// 延迟执行
this.asyncTimeoutFuture = scheduler.schedule(() -> {
    clients.remove(LongPollingClient.this);
    List<ConfigGroupEnum> changedGroups = compareChangedGroup((HttpServletRequest) asyncContext.getRequest());
    sendResponse(changedGroups);
}, timeoutTime, TimeUnit.MILLISECONDS);

3、在类加载完成后,调用此方法执行定时任务,获取数据库中的数据刷新到缓存,初始化需要执行。

@Override
protected void afterInitialize() {
    long syncInterval = httpSyncProperties.getRefreshInterval().toMillis();
    // Periodically check the data for changes and update the cache
    // 检查数据库的数据变化,并更新至内存,这里的定时任务是5分钟执行一次
    scheduler.scheduleWithFixedDelay(() -> {
        log.info("http sync strategy refresh config start.");
        try {
            this.refreshLocalCache();
            log.info("http sync strategy refresh config success.");
        } catch (Exception e) {
            log.error("http sync strategy refresh config error!", e);
        }
    }, syncInterval, syncInterval, TimeUnit.MILLISECONDS);
    log.info("http sync strategy refresh interval: {}ms", syncInterval);
}
private void refreshLocalCache() {
    this.updateAppAuthCache();
    this.updatePluginCache();
    this.updateRuleCache();
    this.updateSelectorCache();
    this.updateMetaDataCache();
}

4、通过事件触发 afterAppAuthChanged 执行,来解析一下执行逻辑:

先看一下类的继承关系:
在这里插入图片描述

1)、后端更改插件信息后,会发布一个变更事件

2)、DataChangedListener 监听到事件后会执行 afterAppAuthChanged 方法

// org.dromara.soul.admin.service.impl.PluginServiceImpl
// 发布数据变更事件
eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.PLUGIN, eventType,
        Collections.singletonList(PluginTransfer.INSTANCE.mapToData(pluginDO))));

// 监听事件,执行此方法
@Override
protected void afterAppAuthChanged(final List<AppAuthData> changed, final DataEventTypeEnum eventType) {
    scheduler.execute(new DataChangeTask(ConfigGroupEnum.APP_AUTH));
}

5、事件变更的执行由DataChangeTask来执行,此类会通过创建线程来执行。根据 groupKey 从 BlockingQueue 阻塞队列中取出client,异步通知某个网关测client发生了数据变更。

/**
 * When a group's data changes, the thread is created to notify the client asynchronously.
 */
class DataChangeTask implements Runnable {
    ......
    DataChangeTask(final ConfigGroupEnum groupKey) {
        this.groupKey = groupKey;
    }
    @Override
    public void run() {
        for (Iterator<LongPollingClient> iter = clients.iterator(); iter.hasNext();) {
            LongPollingClient client = iter.next();
            iter.remove();
            client.sendResponse(Collections.singletonList(groupKey));
            log.info("send response with the changed group,ip={}, group={}, changeTime={}", client.ip, groupKey, changeTime);
        }
    }
}

6、总结一下 HttpLongPollingDataChangedListener 执行的一些功能

  • 1)、初始化,soul-admin 启动后会读取数据库网关数据同步值内存,例如:
afterInitialize() --> refreshLocalCache() --> updateAppAuthCache()
  • 2)、执行http长轮询处理

    • 1)阻塞 soul-bootstrap 长轮询调用,等待数据变更进行响应,否则超时返回。

    • 2)监听数据变更事件,收到变更事件后更新缓存并响应给 soul-bootstrap。

7、总结一下用到的技术点

  • ApplicationEventPublisher 、ApplicationListener
  • InitializingBean
  • ScheduledThreadPoolExecutor
  • ThreadPoolExecutor
  • ReentrantLock
  • AtomicBoolean
  • BlockingQueue
  • ConcurrentHashMap

官网:soul 数据同步原理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值