Soul 学习笔记---soul 数据同步的浅显分析(四)

当我们在 soul-admin 更改 selector 或者 rule 时,数据是怎么同步到网关内存中的呢。

我们知道 soul 网关有四种数据同步的方式,http 长轮询,websocketzookeepernacos,数据同步处理就是在这些 listener 里进行的,默认使用 websocket 同步。今天也主要是看 websocket 同步方式。

Soul 学习笔记---soul 数据同步的浅显分析(四)_第1张图片

以更新 selector 为例,执行过程是在 publishEvent 方法。

Soul 学习笔记---soul 数据同步的浅显分析(四)_第2张图片

这里使用 eventPublisher (也就是ApplicationEventPublisherspring 自带的一种事件发布机制) 发布一个 DataChangedEvent 事件。

DataChangedEventDispatcher 这个类实现了 ApplicationListener 接口,就可以接收到这个事件,收到事件后会执行 onApplicationEvent 方法,这里我们修改的是 SELECTOR,它就会去执行 listeneronSelectorChanged 方法,onSelectorChanged 方法会通过 websocket 向客户端发送消息,通知数据变更,客户端收到消息就把变更的数据更新到 JVM 内存中。

@Component
public class DataChangedEventDispatcher implements ApplicationListener, InitializingBean {

    private ApplicationContext applicationContext;

    private List listeners;

    public DataChangedEventDispatcher(final ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void onApplicationEvent(final DataChangedEvent event) {
        for (DataChangedListener listener : listeners) {
            switch (event.getGroupKey()) {
                case APP_AUTH:
                    listener.onAppAuthChanged((List) event.getSource(), event.getEventType());
                    break;
                case PLUGIN:
                    listener.onPluginChanged((List) event.getSource(), event.getEventType());
                    break;
                case RULE:
                    listener.onRuleChanged((List) event.getSource(), event.getEventType());
                    break;
                case SELECTOR:
                    listener.onSelectorChanged((List) event.getSource(), event.getEventType());
                    break;
                case META_DATA:
                    listener.onMetaDataChanged((List) event.getSource(), event.getEventType());
                    break;
                default:
                    throw new IllegalStateException("Unexpected value: " + event.getGroupKey());
            }
        }
    }

    @Override
    public void afterPropertiesSet() {
        Collection listenerBeans = applicationContext.getBeansOfType(DataChangedListener.class).values();
        this.listeners = Collections.unmodifiableList(new ArrayList<>(listenerBeans));
    }

}

debug 到这里时,listeners 是有值的,就是我们需要的 WebsocketDataChangedListener,那这个 listeners 的值怎么来的呢?这是在 soul-admin 启动时就已经赋值了,在 afterPropertiesSet 方法里赋值的。
Soul 学习笔记---soul 数据同步的浅显分析(四)_第3张图片

soul-adminapplication-local.yml 文件里配置了 soul.sync.websocket.enabled = true
Soul 学习笔记---soul 数据同步的浅显分析(四)_第4张图片这里满足了 @ConditionalOnProperty 条件,所以加载 DataSyncConfiguration 这个类时,就会把以下三个 bean 注册进来。

Soul 学习笔记---soul 数据同步的浅显分析(四)_第5张图片

DataChangedEventDispatcher 类还实现了 InitializingBean 接口,这个接口里只有一个 afterPropertiesSet 方法,那么启动项目时,这个类的构造函数初始化后,就会执行这个方法,拿到我们配置的数据同步 listenerlisteners就赋值成功啦。

看这段源码的时候,我遇到最大的问题就是想不通 DataChangedEventDispatcher 类的 listeners 是什么时候赋值的,我加了很多断点,但编辑 selector的时候,就是进不到 afterPropertiesSet 方法里的断点。虽然我也找到了 DataSyncConfiguration 这个类,看到了上图的那些代码,但当时就是想不明白。后来也不知道怎么了,我突然想到了 @ConditionalOnProperty 这个注解的作用,这个条件成立,就会把这个 bean 注册进来,也搜了下 InitializingBean 这个接口,才意识到启动 soul-admin 的时候,就已经给 listeners 赋值了。

就这很小的一个模块,我也学到了很多东西,@ConditionalOnProperty 这个注解虽然知道,但一直没用过,所以当时看到没反应过来,从这里我也学到了一个新用法。还有 spring 的事件发布机制,这个也很实用,代码里也可以用起来。

本来今天想把 websocket 如何发送接收也写了的,但光写这么多都花了两个多小时,就明天再写吧。

你可能感兴趣的:(java,websocket)