继上节分析2
-
soul的各种插件启动基本流程是通过自定义starter启动,然后内部做一系列的依赖注入。
-
上1节我们知道soul-bootstrap 引入上面这个starter,里面的启动配置类
ZookeeperSyncDataConfiguration
,创建了同步数据的syncDataService
类,再往spring容器注册了zkClient
。其实这里面还有个知识点:ObjectProvider Bean依赖查找注入
,然后实例化的zkclient有url、session超时时间和连接超时时间。
public ZkClient zkClient(final ZookeeperConfig zookeeperConfig) { return new ZkClient(zookeeperConfig.getUrl(), zookeeperConfig.getSessionTimeout(), zookeeperConfig.getConnectionTimeout()); }
-
上面这三个参数,就是上文分析中的 boot-strap的application-local.yml配置的。
zookeeper: url: localhost:2181 sessionTimeout: 5000 connectionTimeout: 2000
-
ZookeeperSyncDataService初始化一个缓存管理器,全量给需要关注的节点增加watch机制,每次触发数据变动,就先watch 然后在处理事件。
public ZookeeperSyncDataService(final ZkClient zkClient, final PluginDataSubscriber pluginDataSubscriber, final List<MetaDataSubscriber> metaDataSubscribers, final List<AuthDataSubscriber> authDataSubscribers) { this.zkClient = zkClient; this.pluginDataSubscriber = pluginDataSubscriber; this.metaDataSubscribers = metaDataSubscribers; this.authDataSubscribers = authDataSubscribers; watcherData(); watchAppAuth(); watchMetaData(); }
-
将需要关注的节点绑定
watcher
事件触发之后,处理的方法subscribePluginDataChanges
。private void watcherPlugin(final String pluginName) { String pluginPath = ZkPathConstants.buildPluginPath(pluginName); if (!zkClient.exists(pluginPath)) { zkClient.createPersistent(pluginPath, true); } cachePluginData(zkClient.readData(pluginPath)); subscribePluginDataChanges(pluginPath, pluginName); }
-
监听到数据变动后处理
private void subscribePluginDataChanges(final String pluginPath, final String pluginName) { zkClient.subscribeDataChanges(pluginPath, new IZkDataListener() { @Override public void handleDataChange(final String dataPath, final Object data) { Optional.ofNullable(data) .ifPresent(d -> Optional.ofNullable(pluginDataSubscriber).ifPresent(e -> e.onSubscribe((PluginData) d))); } @Override public void handleDataDeleted(final String dataPath) { final PluginData data = new PluginData(); data.setName(pluginName); Optional.ofNullable(pluginDataSubscriber).ifPresent(e -> e.unSubscribe(data)); } }); }
-
soul-admin数据初始化全量更新,在
DataSyncConfiguration
类的内部类zk监听ZookeeperListener
@Bean @ConditionalOnMissingBean(ZookeeperDataInit.class) public ZookeeperDataInit zookeeperDataInit(final ZkClient zkClient, final SyncDataService syncDataService) { return new ZookeeperDataInit(zkClient, syncDataService); } public class ZookeeperDataInit implements CommandLineRunner { ...... @Override public void run(final String... args) { String pluginPath = ZkPathConstants.PLUGIN_PARENT; String authPath = ZkPathConstants.APP_AUTH_PARENT; String metaDataPath = ZkPathConstants.META_DATA; if (!zkClient.exists(pluginPath) && !zkClient.exists(authPath) && !zkClient.exists(metaDataPath)) { syncDataService.syncAll(DataEventTypeEnum.REFRESH); } } }
-
SyncDataServiceImpl#syncAll 方法, 发送了五种类型数据事件,看这里
ApplicationEventPublisher
发布了一个订阅DataChangedEvent
,这边有一套spring的事件通知机制:这个DataChangedEvent
继承了ApplicationEvent
,ApplicationEvent (记录事件源和数据)和ApplicationListener
(事件监听者)配套使用的,DataChangedEventDispatcher
(事件分发器)实现了ApplicationListener
,就找到了DataChangedListener
接口,再找到实现类ZookeeperDataChangedListener
@Override public boolean syncAll(final DataEventTypeEnum type) { 。。。。。。 eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.RULE, type, ruleDataList)); metaDataService.syncData(); return true; }
小结:
后台通过 DataSyncConfiguration 配置类去注入 zk监听器为 Spring Bean (内部类ZookeeperListener
),admin 主要通过ApplicationEvent 发送数据变动事件,然后通过具体通信插件将数据告知网关端,网关通过订阅模式将信息告知对应关心数据的通信协议插件。