soul网关的配置数据同步由三种方式,前面我们已经介绍了websocket同步和zookeeper同步方式,本文继续探究最后一种同步方式——http长轮询。
启动前
网关启动前,需要修改admin和bootstrap的配置,将两者的数据同步方式都改成http,具体如下(依旧注意缩进问题):
- admin端yml配置修改
soul:
database:
dialect: mysql
init_script: "META-INF/schema.sql"
init_enable: true
sync:
websocket:
enabled: false
# zookeeper:
# url: localhost:2181
# sessionTimeout: 5000
# connectionTimeout: 2000
http:
enabled: true
- bootstrap端yml配置修改
soul:
file:
enabled: true
corss:
enabled: true
dubbo :
parameter: multi
sync:
# websocket :
# urls: ws://localhost:9095/websocket
# zookeeper:
# url: localhost:2181
# sessionTimeout: 5000
# connectionTimeout: 2000
http:
url : http://localhost:9095
网关启动
分别启动admin和bootstrap,接着启动alibaba dubbo example进行测试,调用dubbo接口,调用成功,一切看起来都比较顺利,接下来直接对代码进行分析。
代码分析
- admin初始化
http同步的初始化配置类也在DataSyncConfiguration类中,相关代码如下:
@Configuration
@ConditionalOnProperty(name = "soul.sync.http.enabled", havingValue = "true")
@EnableConfigurationProperties(HttpSyncProperties.class)
static class HttpLongPollingListener {
@Bean
@ConditionalOnMissingBean(HttpLongPollingDataChangedListener.class)
public HttpLongPollingDataChangedListener httpLongPollingDataChangedListener(final HttpSyncProperties httpSyncProperties) {
return new HttpLongPollingDataChangedListener(httpSyncProperties);
}
}
这里初始化一个长轮询监听器bean(HttpLongPollingDataChangedListener),HttpLongPollingDataChangedListener的构造函数如下:
public HttpLongPollingDataChangedListener(final HttpSyncProperties httpSyncProperties) {
this.clients = new ArrayBlockingQueue<>(1024);
this.scheduler = new ScheduledThreadPoolExecutor(1,
SoulThreadFactory.create("long-polling", true));
this.httpSyncProperties = httpSyncProperties;
}
HttpLongPollingDataChangedListener构造函数初始化一个阻塞队列(队列用于保存bootstrap端的长连接请求),以及初始化一个线程池,用来处理长连接。
-
admin端处理bootstrap端的rest接口在ConfigController类中,总共有两个接口,/fetch接口用于获取最新配置数据,/listener接口用于请求建立长连接。
-
bootstrap端初始化
bootstrap端初始化配置类为HttpSyncDataConfiguration,在这里会初始化一个HttpSyncDataService类的同步服务,初始化时,会向admin端同步一次全量的配置:
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.
//异步开启长连接监听,serverList是不同的admin地址,可能有多个
this.serverList.forEach(server -> this.executor.execute(new HttpLongPollingTask(server)));
} else {
log.info("soul http long polling was started, executor=[{}]", executor);
}
}
代码继续往下跟踪会发现,最后就是调用admin端的fetch接口来获取配置。
总结
本文仅简单介绍了http长连接的配置,启动一级初始化等过程,以及soul长连接同步的大体机制,其实在具体的实现上,有一些细的点还可以说明一下,今天时间关系,先讲这么多。