soul网关源码分析之soul-gateway缓存刷新

soul网关源码分析之soul-gateway缓存刷新

目标

  • soul-gateway本地缓存刷新
  • 总结

概述

    上篇讲了soul-admin与soul-gateway通过websocket的方式进行数据的同步,本篇将详细介绍soul-gateway如果将内存中的缓存刷新的。

架构图

    从架构图中能够看出,数据变更会通过pull模式或者push模式到soul-web模块,上篇文档提到了soul-web模块负责接收代理请求,各种filter,实际上soul-web的另一个功能就是订阅DataChangedEvent分发的同步事件,soul-web模块会处理缓存数据的更新,但是在我们构建soul网关的时候,似乎并没有引入soul-web依赖,检查网关项目依赖包的时候的确发现了soul-web模块,这是由于我们soul-spring-boot-starter-gateway,这个包中引入了soul-web,并且我们查看这个包的spring.factories内容是provides: soul-web,意思就是告诉spring要扫描这个模块的配置。

在这里插入图片描述

soul-web之缓存数据刷新

  • SoulConfiguration

    soul-web模块为该模块的配置类,配置类中配置了plugin数据变化订阅者PluginDataSubscriber,从源码中可以看出CommonPluginDataSubscriber就是实际的plugin缓存变化的处理类

    @Bean
    public PluginDataSubscriber pluginDataSubscriber(final ObjectProvider<List<PluginDataHandler>> pluginDataHandlerList) {
        return new CommonPluginDataSubscriber(pluginDataHandlerList.getIfAvailable(Collections::emptyList));
    }
  • PluginDataSubscriber

    PluginDataSubscriber是一个接口,定义了对插件,选择器,规则的数据变化订阅,取消订阅,clean所有缓存,根据key clean缓存的方法,分别是:onSubscribe,unSubscribe,refreshPluginDataAll,refreshPluginDataSelf,onSelectorSubscribe,unSelectorSubscribe,refreshSelectorDataAll,refreshSelectorDataSelf,onRuleSubscribe,unRuleSubscribe,refreshRuleDataAll,refreshRuleDataSelf;这些方法实现的逻辑对应都是相同的,代码很简单,不做过多说明。

  • CommonPluginDataSubscriber

    该类实现了PluginDataSubscriber接口的全部方法,该类的核心方法是subscribeDataHandler,订阅数据的处理逻辑全在这个方法中,该方法的逻辑是先校验数据是否为空,接着判断数据的类型,数据类型有插件数据,选择器数据,规则数据,每一个条件分之中的数据处理流程都是一样的,比如插件数据,分为UPDATEDELETE两种操作类型UPDATE类型首先会cachePluginData更新缓存,然后会根据pluginData.getName()获取插件数据的处理器,然后调用处理器的handlerPlugin方法处理数据,拿divide插件举例,我进到DividePluginDataHandler处理器,发现该处理并没有重写handlerPlugin方法,接着到PluginDataHandler接口中发现handlerPlugin是一个default方法,并且是个空方法,就是说操作类型是UPDATE更新缓存后就完成了逻辑。

    接下来,我们看一下操作类型DELETE处理逻辑,处理逻辑是PLUGIN_MAP.remove(data.getName()),根据数据name从缓存中移除了插件,并且调用处理器的removePlugin方法,查看代码这也是一个空的default方法。

    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));
                }
            } else if (data instanceof SelectorData) {
                SelectorData selectorData = (SelectorData) data;
                if (dataType == DataEventTypeEnum.UPDATE) {
                    BaseDataCache.getInstance().cacheSelectData(selectorData);
                    Optional.ofNullable(handlerMap.get(selectorData.getPluginName())).ifPresent(handler -> handler.handlerSelector(selectorData));
                } else if (dataType == DataEventTypeEnum.DELETE) {
                    BaseDataCache.getInstance().removeSelectData(selectorData);
                    Optional.ofNullable(handlerMap.get(selectorData.getPluginName())).ifPresent(handler -> handler.removeSelector(selectorData));
                }
            } else if (data instanceof RuleData) {
                RuleData ruleData = (RuleData) data;
                if (dataType == DataEventTypeEnum.UPDATE) {
                    BaseDataCache.getInstance().cacheRuleData(ruleData);
                    Optional.ofNullable(handlerMap.get(ruleData.getPluginName())).ifPresent(handler -> handler.handlerRule(ruleData));
                } else if (dataType == DataEventTypeEnum.DELETE) {
                    BaseDataCache.getInstance().removeRuleData(ruleData);
                    Optional.ofNullable(handlerMap.get(ruleData.getPluginName())).ifPresent(handler -> handler.removeRule(ruleData));
                }
            }
        });
    }

总结

    至此,soul网关的缓存刷新详细流程也分析完了,选择器和规则缓存的刷新和插件数据的刷新是一样的,soul网关每次更新数据都是将整个插件的完整数据从soul-admin发送/订阅到soul网关,soul网关执行put到map中,替换原来的缓存。

猜你喜欢

转载自blog.csdn.net/qq_31279701/article/details/112795685