Soul源码解析(10)-Soul网关数据同步设计思想

一、目标

​ 数据同步是Soul网关非常重要的一块内容,之前我们一起了解了Soul网关四种数据同步方式的运作原理,本节我们就从整体的层面来看一下Soul数据同步的思想,算是对之前学习内容的一个总结。

二、内容

2.1 背景

​ Soul网关目前支持四种数据同步方式:webSocket、zookeeper、http长轮询、nacos。Soul网关支持插件化配置、目前支持的插件有13个。每个插件要处理的数据类型包括:AuthData、PluginData、SelectorData、RuleData、MetaData。每种数据类型又包括三种操作:update、delete、refresh。这样一组合下来,它的组合方式是非常多的,13 x 4 x 5 x 3,算下来有780种之多。如果不能厘清他们之间的关系,那代码的结构就会看起来非常乱,而且同时还要考虑可扩展的问题。

​ 我们在分析源码的过程中,可以看到Soul网关,这一块还是梳理的非常清楚的,这其中的设计思想和模式是非常值得我们学习的。接下来我们就从整体的角度来一起看一下Soul网关数据同步模块的设计。

在这里插入图片描述

2.2 接口设计

Soul在数据同步这一块,大体上有四类接口:

  • ApplicationEventPublisher -> EventPublisher 发出配置变更通知;

  • DataChangedEventDispatcher -> 根据配置的同步策略(http、weboscket、zookeeper),将配置发送给对应的事件处理器;

  • DataHandler接口 -> 事件处理器;

  • Subscriber接口 -> 事件订阅者接收数据;

    2.2.1 ApplicationEventPublisher

    这个接口是Spring里面的接口,是封装事件发布功能的接口,Soul网关通过接口里面的publishEvent方法来发布事件;

    2.2.3 DataChangedEventDispatcher

    事件转发器,将更改的事件转发到每个ConfigEventListener。DataChangedEventDispatcher 实现了Spring里面的ApplicationListener接口。数据通过DataChangedEvent类进行传递;

    public void onApplicationEvent(final DataChangedEvent event) {
            for (DataChangedListener listener : listeners) {
                switch (event.getGroupKey()) {
                    case APP_AUTH:
                        listener.onAppAuthChanged((List<AppAuthData>) event.getSource(), event.getEventType());
                        break;
                    case PLUGIN:
                        listener.onPluginChanged((List<PluginData>) event.getSource(), event.getEventType());
                        break;
                    case RULE:
                        listener.onRuleChanged((List<RuleData>) event.getSource(), event.getEventType());
                        break;
                    case SELECTOR:
                        listener.onSelectorChanged((List<SelectorData>) event.getSource(), event.getEventType());
                        break;
                    case META_DATA:
                        listener.onMetaDataChanged((List<MetaData>) event.getSource(), event.getEventType());
                        break;
                    default:
                        throw new IllegalStateException("Unexpected value: " + event.getGroupKey());
                }
            }
        }
    

    2.2.4 DataHandler

    这个是数据处理的接口,接口里面定义一个handle方法接口,参数是json格式的数据和eventType。AbstractDataHandler是一个抽象方法,实现了DataHandler接口,重写了接口里面的handle方法,同时他也定义了很多很多自己的方法。这里用到了模板设计模式,学习设计模式的同学可以参考一下这里的用法;

    在这里插入图片描述

2.2.5 Subscriber接口

事件订阅者接收数据。Subscriber接口有三类:

  • PluginDataSubscriber接口,主要处理插件相关的不同类型的数据;

    CommonPluginDataSubscriber类实现了PluginDataSubscriber接口,重写了接口里面的方法,自定义了subscribeDataHandler方法,这个方法是用来根据事件类型来调用不同类型的handler方法。

    private <T> void subscribeDataHandler(final T classData, final DataEventTypeEnum dataType) {
            Optional.ofNullable(classData).ifPresent(data -> {
                if (data instanceof PluginData) {
                    PluginData pluginData = (PluginData) data;
                    if (dataType == DataEventTypeEnum.UPDATE) {
                        BaseDataCache.getInstance().cachePluginData(pluginData);
                        Optional.ofNullable(handlerMap.get(pluginData.getName())).ifPresent(handler -> handler.handlerPlugin(pluginData));
                    } else if (dataType == DataEventTypeEnum.DELETE) {
                        BaseDataCache.getInstance().removePluginData(pluginData);
                        Optional.ofNullable(handlerMap.get(pluginData.getName())).ifPresent(handler -> handler.removePlugin(pluginData));
                    }
                } 
                //省略
                ...
                    }
                }
            });
        }
    
  • MetaDataSubscriber接口,主要处理原数据;

  • AuthDataSubscriber接口,主要处理用户及权限相关数据;

在这里插入图片描述

2.3 各数据同步中心

经过DataHandler和Subscribe接口的处理,数据到了各个数据同步中心进行处理

在这里插入图片描述

以soul-sync-data-websocket同步中心为例,看一下数据到了数据同步中心的处理

在这里插入图片描述

数据到达之后,调用onMessage方法,onMessage调用handleResult方法,找到websocketDataHandler,websocketDataHandler调用具体的处理类AbstractDataHandler,再根据DataEventType选择对应的类进行处理。

public void handle(final String json, final String eventType) {
        List<T> dataList = convert(json);
        if (CollectionUtils.isNotEmpty(dataList)) {
            DataEventTypeEnum eventTypeEnum = DataEventTypeEnum.acquireByName(eventType);
            switch (eventTypeEnum) {
                case REFRESH:
                case MYSELF:
                    doRefresh(dataList);
                    break;
                case UPDATE:
                case CREATE:
                    doUpdate(dataList);
                    break;
                case DELETE:
                    doDelete(dataList);
                    break;
                default:
                    break;
            }
        }
    }

三、总结

今天从整体上对Soul网关的数据同步进行了粗略的回顾,看懂总体再结合具体的实例去看一遍,整个结构和思路会更加清楚。这其中的设计思路、设计模式及代码的实现方式都值得我们去好好进一步深究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值