上一篇(soul网关数据同步之websocket同步方式探究)我们分析了soul网关的websocket同步方式,准备一鼓作气,把三种数据同步方式都了解一遍,本篇我们探讨zookeeper admin端同步方式。
数据同步方式配置
在官网介绍中有说明,admin和bootstrap必须配置成一样的同步方式,才可以正常进行数据同步,这里我们修改admin的yml配置如下(注意缩进格式,否则可能导致zookeeper监听其不能初始化):
soul:
database:
dialect: mysql
init_script: "META-INF/schema.sql"
sync:
websocket:
enabled: false
zookeeper:
url: localhost:2181
sessionTimeout: 5000
connectionTimeout: 2000
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
调试分析
- 启动admin和bootstrap,生成如下的zookeeper结点:
这里有三个子节点,我们以元数据结点metaData为例进行进一步分析。 - 根据上一篇分析websocket经验(后面可以通过打断点来验证),直接定位到DataSyncConfiguration这个数据同步配置类中,在这里可以看到一个ZookeeperListener内部静态类,admin启动时,在这里初始化了一个ZookeeperDataChangedListener实例并注入spring容器,在ZookeeperDataChangedListener监听器实现了DataChangedListener接口,该接口各方法如下:
public interface DataChangedListener {
/**
* invoke this method when AppAuth was received.
*
* @param changed the changed
* @param eventType the event type
*/
default void onAppAuthChanged(List<AppAuthData> changed, DataEventTypeEnum eventType) {
}
/**
* invoke this method when Plugin was received.
*
* @param changed the changed
* @param eventType the event type
*/
default void onPluginChanged(List<PluginData> changed, DataEventTypeEnum eventType) {
}
/**
* invoke this method when Selector was received.
*
* @param changed the changed
* @param eventType the event type
*/
default void onSelectorChanged(List<SelectorData> changed, DataEventTypeEnum eventType) {
}
/**
* On meta data changed.
*
* @param changed the changed
* @param eventType the event type
*/
default void onMetaDataChanged(List<MetaData> changed, DataEventTypeEnum eventType) {
}
/**
* invoke this method when Rule was received.
*
* @param changed the changed
* @param eventType the event type
*/
default void onRuleChanged(List<RuleData> changed, DataEventTypeEnum eventType) {
}
}
- 分别用来处理元数据、插件、选择器等各种配置数据的变化,在ZookeeperDataChangedListener类中,元数据变化的处理函数如下,可以看到,在元数据新增、更新和删除时,都会对zookeeper结点进行相应的操作,并且进行的是增量操作(通过调试可以看出)。
public void onMetaDataChanged(final List<MetaData> changed, final DataEventTypeEnum eventType) {
for (MetaData data : changed) {
final String metaDataPath = ZkPathConstants.buildMetaDataPath(URLEncoder.encode(data.getPath(), "UTF-8"));
// delete
if (eventType == DataEventTypeEnum.DELETE) {
deleteZkPath(metaDataPath);
continue;
}
// create or update
upsertZkNode(metaDataPath, data);
}
}
- 上面步骤我们是根据代码逻辑进行正向推测,接下来通过前端修改元数据配置来直接验证。
- 进入前端元数据管理界面,选择一个元数据,点击
批量启用或禁用
按钮,发现浏览器发出如下请求:
- 请求的url是http://127.0.0.1:9095/meta-data/batchEnabled,根据这个url,搜索到对应的controller接口,位于MetaDataController类中,具体如下:
public SoulAdminResult batchEnabled(@RequestBody final BatchCommonDTO batchCommonDTO) {
final String result = metaDataService.enabled(batchCommonDTO.getIds(), batchCommonDTO.getEnabled());
if (StringUtils.isNoneBlank(result)) {
return SoulAdminResult.error(result);
}
return SoulAdminResult.success(SoulResultMessage.ENABLE_SUCCESS);
}
在这个api入口打断点,可以跟踪到前端请求进入MetaDataServiceImpl类的enabled函数,具体如下:
public String enabled(final List<String> ids, final Boolean enabled) {
List<MetaData> metaDataList = Lists.newArrayList();
for (String id : ids) {
MetaDataDO metaDataDO = metaDataMapper.selectById(id);
if (Objects.isNull(metaDataDO)) {
return AdminConstants.ID_NOT_EXIST;
}
metaDataDO.setEnabled(enabled);
metaDataMapper.updateEnable(metaDataDO);
metaDataList.add(MetaDataTransfer.INSTANCE.mapToData(metaDataDO));
}
// publish change event.
eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.META_DATA, DataEventTypeEnum.UPDATE,
metaDataList));
return StringUtils.EMPTY;
}
在这里我们看到了熟悉的eventPublisher,eventPublisher将元数据变化事件通告出去。
- 同websocket事件监听一样,zookeeper事件监听也在DataChangedEventDispatcher类中,在DataChangedEventDispatcher类的onApplicationEvent函数中打断点调试,发现断点进入ZookeeperDataChangedListener类的onMetaDataChanged,对应的代码就是上述第三点所列的,在这里更新了zookeeper结点。
结语
本篇探讨了soul网关admin端的zookeeper数据同步逻辑,boostrap端将在下文继续探讨。