概述
前几篇文章介绍了suol用websocket、http长轮询的方式同步数据,今天我们来看看zookeeper同步数据是如何实现的。使用websocket同步数据时,在soul-admin服务端有负责监听数据变化事件的HttpLongPollingDataChangedListener
以及负责接收soul网关连接的WebsocketCollector
,在soul服务端有实现SyncDataService
的WebsocketSyncDataService
,负责实现当接收到配置变化。下面我们来对应看看zookeeper这几部分是如何实现的。
网关端
在soul网关端如果要开启zookeeper同步数据的方式需要做如下配置:
1 | soul: |
与websocket和http长轮询不同的是,它需要配置一个和admin公用的zookeeper集群地址。网关端的ZookeeperSyncDataService
代码如下,代码值选取了pluginData和selectorData的更新,其他的appAuth、rule、metaData数据的更新大同小异略过
1 | public class ZookeeperSyncDataService implements SyncDataService, AutoCloseable { |
总体来说soul在zookeeper中主要的目录结构是:/soul/plugin/\${pluginName}、 /soul/selector/\${pluginName}/xxx、 /soul/rule/\${pluginName}/xxx、 /soul/selector/\${pluginName}/xxx、 /soul/auth/xxx、 /soul/metaData/xxx。启动时都会先从对应目录下找数据,然后发给对应数据的订阅者。然后soul主要关注最底层目录数据的变更和删除事件,在父级目录关注子目录变更达到关注新数据增加事件。当触发相应事件后借助对应数据的订阅者触发配置数据更新操作。
admin端
admin端主要是将变更的数据更新到zookeeper对应的目录下。它主要有2个类同样一个是实现DataChangedListener
的ZookeeperDataChangedListener
以及在启动时运行的初始化数据的ZookeeperDataInit
。首先说ZookeeperDataInit它继承了CommandLineRunner,在spring boot应用中,我们可以在程序启动之前spring容器启动好之后用它执行任务执行任何任务。源码如下
1 | public class ZookeeperDataInit implements CommandLineRunner { |
ZookeeperDataInit干的一件事就是启动时看看zookeeper里面有没有历史数据,如果没有数据则发送全量数据刷新事件,这是ZookeeperDataChangedListener
就会接到所有类型数据的刷新时间并作出响应,下面我们看下它的源码,由于大同小异所以以Plugin数据为例做介绍:
1 | public class ZookeeperDataChangedListener implements DataChangedListener { |
admin主要负责数据变更时向zk写或删数据,逻辑简单清晰。
总结
整体来说zk同步数据逻辑非常清晰,这也可以看出zk非常适合干这样的工作的,在集群环境下同步meta信息。从中我学到了如果向监控数据新增可以在父节点关注子节点的变化,其他情况可以关注某个目录下数据的修改或删除。