使用 nacos 进行数据同步时,首先 soul-admin 的 application.yml 文件配置使用 nacos 同步
sync:
# websocket:
# enabled: true
# zookeeper:
# url: localhost:2181
# sessionTimeout: 5000
# connectionTimeout: 2000
# http:
# enabled: true
nacos:
url: localhost:8848
namespace: 1c10d748-af86-43b9-8265-75f487d20c6c
# acm:
# enabled: false
# endpoint: acm.aliyun.com
# namespace:
# accessKey:
# secretKey:
soul-bootstrap application-local.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
nacos:
url: localhost:8848
namespace: 1c10d748-af86-43b9-8265-75f487d20c6c
# acm:
# enabled: false
# endpoint: acm.aliyun.com
# namespace:
# accessKey:
# secretKey:
最最重要的是 soul-bootstrap 的 pom.xml 文件,需要引入 nacos 同步的 starter
<!--soul data sync start use nacos-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-spring-boot-starter-sync-data-nacos</artifactId>
<version>${project.version}</version>
</dependency>
接着启动本地 nacos 服务,启动完 soul-admin,soul-bootstrap 后,最新版本,第一次启动,数据可以同步到 nacos的后台,此时登录 nacos 后端,就有了我们需要的数据。如果你还是没有数据,先去 nacos 后台命名空间那里新建一个命名空间再启动项目,名字就是 yml 文件配置的 namespace。
启动 soul-admin时,NacosDataChangedListener 创建了 configService ,作为服务端。
当启动 soul-bootstrap 时,会加载 NacosSyncDataService 类,这里会执行下面的 start 方法。
这一块代码确实很难懂,就以第一行为例,updatePluginMap方法还是需要参数的,我一开始没看懂是哪里传参的,后来加上断点,debug的时候,才搞懂流程。首先去执行 watcherData 方法,新建一个 listener(就可以监听到 soul-admin的数据变化),下面的 oc.change 就是去执行 updatePluginMap 方法,参数是从 getConfigAndSignListener(dataId, listener) 获取的,从nacos 配置中心拿数据,当然一开始是空的,默认是 ‘{}’,updatePluginMap 这个方法就是拿这个数据去同步到内存中了。
public void start() {
watcherData(PLUGIN_DATA_ID, this::updatePluginMap);
watcherData(SELECTOR_DATA_ID, this::updateSelectorMap);
watcherData(RULE_DATA_ID, this::updateRuleMap);
watcherData(META_DATA_ID, this::updateMetaDataMap);
watcherData(AUTH_DATA_ID, this::updateAuthMap);
}
protected void watcherData(final String dataId, final OnChange oc) {
Listener listener = new Listener() {
//接收 soul-admin 的数据变化
@Override
public void receiveConfigInfo(final String configInfo) {
oc.change(configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
};
//执行 updatePluginMap 方法,getConfigAndSignListener(dataId, listener) 从配置中心获取数据
oc.change(getConfigAndSignListener(dataId, listener));
LISTENERS.computeIfAbsent(dataId, key -> new ArrayList<>()).add(listener);
}
protected void updatePluginMap(final String configInfo) {
try {
// Fix bug #656(https://github.com/dromara/soul/issues/656)
List<PluginData> pluginDataList = new ArrayList<>(GsonUtils.getInstance().toObjectMap(configInfo, PluginData.class).values());
pluginDataList.forEach(pluginData -> Optional.ofNullable(pluginDataSubscriber).ifPresent(subscriber -> {
//数据更新到内存
subscriber.unSubscribe(pluginData);
subscriber.onSubscribe(pluginData);
}));
} catch (JsonParseException e) {
log.error("sync plugin data have error:", e);
}
}
有数据变动,soul-admin 把数据发布出去,NacosCacheHandler 的 watcherData 的 listener 接收到数据变更, 具体流程就是在 updatePluginMap 这类方法执行的了。
@SneakyThrows
//soul-admin 数据变更,发布到 nacos。
private void publishConfig(final String dataId, final Object data) {
configService.publishConfig(dataId, GROUP, GsonUtils.getInstance().toJson(data));
}