Soul网关源码阅读(十)—— 数据同步之Http
概要
上一篇介绍了websocket的数据同步流程,这一篇我们来研究一下基于http协议的数据同步方式。
来看看soul网关是如何通过http拉进行数据同步的。
图解
- 开启soul网关http的配置
-
查看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();
}
-
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),保证方法是同步的。
-
拉去全量配置
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); }
-
同步增量的配置逻辑
为每个服务器启动 一个线程,使用线程池启动一个while循环的任务去获取增量配置
HttpLongPollingTask任务获取服务运行状态,如果正在运行,则有执行三次doLongPolling逻辑,即重拾。
doLongPolling没有什么特殊的,就是通过http请求到admin去获取配置,并缓存到本地。
如果配置没有更新则休眠30秒种,并且进行下一次重拾,如果有配置更新立马会进行下一次doLongPolling。
所以之类的逻辑是拉去配置,如果有更新立马返回再拉,如果没有更新休息30秒再拉。