灵魂网关第二节源码分析
2023-09-13 04:30:07
从事件总线出发,分析网关数据变化到zookeeper同步机制
上一篇,通过soul-admin启动过程为入口,分析了soul-admin 启动就会同步 plugin、selector、rule、metaData 等网关数据到 zookeeper,数据变化会发布 DataChangedEvent事件,监听事件将数据同步至zookeeper。
这一篇将进一步剖析 soul 的核心源码,分析事件发布和消费的细节。
事件发布
@EventListener
public void onApplicationEvent(ZookeeperDataChangedEvent event) {
//RuleEvent涉及的选择器和断言为非持久化节点,需要重新查询数据库
if (event.getEventType() == DataEventType.Rule) {
reloadRuleData();
}
//插件数据使用持久节点,无需处理
}
主要的代码逻辑在 @EventListener 注解,该注解作用于 onApplicationEvent 方法。
当发生 ZookeeperDataChangedEvent 事件时,onApplicationEvent 方法就会被触发。这个方法首先会判断事件的类型,如果是 DataEventType.Rule 类型,则会调用 reloadRuleData() 方法重新加载规则数据。如果是 DataEventType.Plugin 类型,则什么都不做,因为插件数据使用的是持久节点,无需重新加载。
在分析事件发布时,可知事件源是 DefaultZookeeperClient 的 setDataAndEvent 方法,该方法使用了两个关键技术:
- ZooKeeper 的 Watcher 监听机制: 当事件触发时,就会回调 DefaultZookeeperClient 里的 createTargetChild 方法,并将事件类型和事件数据传给 DefaultZookeeperClient。
- 事件总线 Spring ApplicationEvent:在 DefaultZookeeperClient 中,会发布 ZookeeperDataChangedEvent 事件。
事件消费
分析到这里,事件发布的细节已经清楚了,但是事件的消费过程还不明确,事件发布的最终目的就是让事件被消费,事件数据也需要被使用。
继续探究,在 netty-http-server 项目的 MetricsHandler 类中发现了这样的代码:
@EventListener
public void onApplicationEvent(ZookeeperDataChangedEvent event) {
if (Objects.equals(event.getEventType(), DataEventType.Selector)) {
//selector 发生改变
this.selectorManager.refreshAllSelectors();
//log.info("Selector发生改变:{}", event.getEventType());
}
}
该代码也是通过 @EventListener 注解触发 onApplicationEvent 方法,同样也是在收到事件之后进行相关的操作,但是该代码中有个关键的类:SelectorManager。
SelectorManager 是一个单例类,它维护着所有的 Selector,当 Selector 发生变化时,就会调用 SelectorManager 的 refreshAllSelectors() 方法,该方法会重新加载所有的 Selector。
事件总线
事件总线是一个发布-订阅模式,发布者发布事件,订阅者订阅事件,当事件发布时,订阅者就会收到事件。
在本文中,DefaultZookeeperClient 是事件发布者,SelectorManager 是事件订阅者。当 DefaultZookeeperClient 发布 ZookeeperDataChangedEvent 事件时,SelectorManager 就会收到事件,并执行相应的操作。
事件总线的使用非常广泛,除了本文中提到的场景,还可以用于其他场景,例如:
- 分布式系统中的事件通知
- 微服务之间的通信
- 前端和后端之间的通信
总结
本文分析了 Soul 网关中事件发布和消费的细节,了解了事件总线的使用方式。