启动 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这边, 由WebsocketSyncDataConfiguration
与WebsocketSyncDataService
完成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的工具类, 追溯调用它的方法为 AbstractSoulPlugin
的 handleSelectorIsNull
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如何工作