Soul网关源码阅读(十)—— 数据同步之Http

16 篇文章 1 订阅

Soul网关源码阅读(十)—— 数据同步之Http

概要

上一篇介绍了websocket的数据同步流程,这一篇我们来研究一下基于http协议的数据同步方式。

来看看soul网关是如何通过http拉进行数据同步的。

图解

  1. 开启soul网关http的配置

在这里插入图片描述

  1. 查看HttpSyncDataService的逻辑

    构造函数初始化了同步的处理类,http配置,一个okHttpClient,就开启start方法,核心在start方法

public HttpSyncDataService(final HttpConfig httpConfig, final PluginDataSubscriber pluginDataSubscriber,
                           final List<MetaDataSubscriber> metaDataSubscribers, final List<AuthDataSubscriber> authDataSubscribers) {
    this.factory = new DataRefreshFactory(pluginDataSubscriber, metaDataSubscribers, authDataSubscribers);
    this.httpConfig = httpConfig;
    this.serverList = Lists.newArrayList(Splitter.on(",").split(httpConfig.getUrl()));
    this.httpClient = createRestTemplate();
    this.start();
}
  1. start方法

     private void start() {
            // It could be initialized multiple times, so you need to control that.
            if (RUNNING.compareAndSet(false, true)) {
                // fetch all group configs.
                this.fetchGroupConfig(ConfigGroupEnum.values());
                int threadSize = serverList.size();
                this.executor = new ThreadPoolExecutor(threadSize, threadSize, 60L, TimeUnit.SECONDS,
                        new LinkedBlockingQueue<>(),
                        SoulThreadFactory.create("http-long-polling", true));
                // start long polling, each server creates a thread to listen for changes.
                this.serverList.forEach(server -> this.executor.execute(new HttpLongPollingTask(server)));
            } else {
                log.info("soul http long polling was started, executor=[{}]", executor);
            }
        }
    

    RUNNING.compareAndSet(false, true) 使用了一个原子方法来进行判断,解释就是:

    如果没有启动(false),则更新成启动(true),保证方法是同步的。

  2. 拉去全量配置

    private void doFetchGroupConfig(final String server, final ConfigGroupEnum... groups) {
            StringBuilder params = new StringBuilder();
            for (ConfigGroupEnum groupKey : groups) {
                params.append("groupKeys").append("=").append(groupKey.name()).append("&");
            }
            String url = server + "/configs/fetch?" + StringUtils.removeEnd(params.toString(), "&");
            log.info("request configs: [{}]", url);
            String json = null;
            try {
                json = this.httpClient.getForObject(url, String.class);
            } catch (RestClientException e) {
                String message = String.format("fetch config fail from server[%s], %s", url, e.getMessage());
                log.warn(message);
                throw new SoulException(message, e);
            }
            // update local cache
            boolean updated = this.updateCacheWithJson(json);
            if (updated) {
                log.info("get latest configs: [{}]", json);
                return;
            }
            // not updated. it is likely that the current config server has not been updated yet. wait a moment.
            log.info("The config of the server[{}] has not been updated or is out of date. Wait for 30s to listen for changes again.", server);
            ThreadUtils.sleep(TimeUnit.SECONDS, 30);
        }
    
  3. 同步增量的配置逻辑

    为每个服务器启动 一个线程,使用线程池启动一个while循环的任务去获取增量配置

    在这里插入图片描述

    HttpLongPollingTask任务获取服务运行状态,如果正在运行,则有执行三次doLongPolling逻辑,即重拾。

    在这里插入图片描述

    doLongPolling没有什么特殊的,就是通过http请求到admin去获取配置,并缓存到本地。

    如果配置没有更新则休眠30秒种,并且进行下一次重拾,如果有配置更新立马会进行下一次doLongPolling。

    所以之类的逻辑是拉去配置,如果有更新立马返回再拉,如果没有更新休息30秒再拉。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值