Soul网关源码分析-0期(预热)

启动 soul-admin成功后, 启动soul-bootstrap

soul-admin下打印几行信息

2021-01-13 23:00:42.047  INFO 16544 --- [0.0-9095-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-01-13 23:00:42.047  INFO 16544 --- [0.0-9095-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-01-13 23:00:42.113  INFO 16544 --- [0.0-9095-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 65 ms
2021-01-13 23:00:42.267  INFO 16544 --- [0.0-9095-exec-1] o.d.s.a.l.websocket.WebsocketCollector   : websocket on open successful....

说明网关与配置后台建立websocket通信, soul-admin 的 WebsocketCollector 打印出关键信息

@Slf4j
@ServerEndpoint("/websocket")
public class WebsocketCollector {

    private static final Set<Session> SESSION_SET = new CopyOnWriteArraySet<>();

    private static Session session;

    /**
     * On open.
     *
     * @param session the session
     */
    @OnOpen
    public void onOpen(final Session session) {
        log.info("websocket on open successful....");
        SESSION_SET.add(session);
    }
    ...
}

初步判断, 配置的同步, 默认下是借由websocket协议完成.

再继续看soul-bootstrap这边, 由WebsocketSyncDataConfigurationWebsocketSyncDataService 完成websocket协议建立, 之后也可能借此进行配置通信, 先暂时标记, 以后研究配置同步时继续钻研.

2021-01-13 23:00:41.679  INFO 21212 --- [           main] b.s.s.d.w.WebsocketSyncDataConfiguration : you use websocket sync soul data.......
2021-01-13 23:00:42.244  INFO 21212 --- [           main] o.d.s.p.s.d.w.WebsocketSyncDataService   : websocket connection is successful.....

由于网关已经启动, 端口是9195, 随便在网址上访问下 localhost:9195 , 返回

{
    code: -107,
    message: "Can not find selector, please check your configuration!",
    data: null
}

这时网关打印出日志

2021-01-13 23:06:49.346 ERROR 21212 --- [-work-threads-1] o.d.soul.plugin.base.utils.CheckUtils    : can not match selector data: divide

关键类CheckUtils 作为提供selector的工具类, 追溯调用它的方法为 AbstractSoulPluginhandleSelectorIsNull

private Mono<Void> handleSelectorIsNull(final String pluginName, final ServerWebExchange exchange, final SoulPluginChain chain) {
    if (PluginEnum.WAF.getName().equals(pluginName)) {
        return doExecute(exchange, chain, null, null);
    }
    return CheckUtils.checkSelector(pluginName, exchange, chain);
}

WAF? 看着像匹配并执行防火墙类的插件的实现方法 (doExecute()被继承类实现, 模板方法 ), 然后获得selector, 这里的selector是啥不明白, 暂放一边, 继续向上查看调用, 发现是该类的execute()方法调用的.

@Override
public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
    String pluginName = named();
    final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
    if (pluginData != null && pluginData.getEnabled()) {
        final Collection<SelectorData> selectors = BaseDataCache.getInstance().obtainSelectorData(pluginName);
        if (CollectionUtils.isEmpty(selectors)) {
            return handleSelectorIsNull(pluginName, exchange, chain);
        }
        final SelectorData selectorData = matchSelector(exchange, selectors);
        if (Objects.isNull(selectorData)) {
            return handleSelectorIsNull(pluginName, exchange, chain);
        }
        selectorLog(selectorData, pluginName);
        final List<RuleData> rules = BaseDataCache.getInstance().obtainRuleData(selectorData.getId());
        if (CollectionUtils.isEmpty(rules)) {
            return handleRuleIsNull(pluginName, exchange, chain);
        }
        RuleData rule;
        if (selectorData.getType() == SelectorTypeEnum.FULL_FLOW.getCode()) {
            //get last
            rule = rules.get(rules.size() - 1);
        } else {
            rule = matchRule(exchange, rules);
        }
        if (Objects.isNull(rule)) {
            return handleRuleIsNull(pluginName, exchange, chain);
        }
        ruleLog(rule, pluginName);
        return doExecute(exchange, chain, selectorData, rule);
    }
    return chain.execute(exchange);
}

execute方法在我看来, 就是所有插件的祖宗级入口, 方法由接口 SoulPlugin 定义, 这个接口应该是祖宗类, 这个方法应该是重点, 暂时也不研究, 在研究插件时, 看这里.

再看下AbstractSoulPlugin 被哪些插件类继承了, 看到个熟悉的影子 DividePlugin , 和刚刚日志打印的 can not match selector data: divide有关系, 盲猜刚刚日志打印时, AbstractSoulPlugin的实现类是它, 开始debug, 先直接D在CheckUtils打印那行

public static Mono<Void> checkSelector(final String pluginName, final ServerWebExchange exchange, final SoulPluginChain chain) {
    if (PluginEnum.DIVIDE.getName().equals(pluginName)
        || PluginEnum.DUBBO.getName().equals(pluginName)
        || PluginEnum.SPRING_CLOUD.getName().equals(pluginName)) {
        log.error("can not match selector data: {}", pluginName);
        Object error = SoulResultWrap.error(SoulResultEnum.CANNOT_FIND_SELECTOR.getCode(), SoulResultEnum.CANNOT_FIND_SELECTOR.getMsg(), null);
        return WebFluxResultUtils.result(exchange, error);
    }
    return chain.execute(exchange);
}

对着线程栈向上追两个调用, 到AbstractSoulPlugin这层, 发现实际的实现类确实是 DividePlugin , 那它的具体 doExecute() 的实现, 就是去处理得到的 Selector 了. 暂时不看, 该睡觉了…

明天将一个http服务跑起来, 看看有什么关键类在作用, 以及最重要的网关server和client如何工作

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值