soul网关源码学习04-devide插件流程解析
目标:
- 梳理soul的插件是如何加载的。
- 梳理发送http请求的时候是如何调用插件链的。
- 解析divide插件执行过程。
一、加载插件
从前面的学习可以知道,整个网关项目的入口是soul-bootstrap模块,先看一下里面的代码,简单的三个类和两个配置文件,可以猜想应该是在pom文件引入了其他模块的starter。
打开pom.xml,可以看到引入了很多插件的starter,先看一下这个gateway的stater。(这里需要注意一下,需要用到的插件一定要在这里加上依赖,否则使用过程中会找不到插件)
进入soul-spring-boot-starter-gateway模块,可以看到这里仅仅是引入了soul-web模块。
进入soul-web模块,找到关键的配置类SoulConfiguration,打上断点。其实直接从启动的日志就可以找到这里,寻找入口一般都可以从启动的日志入手。
这里有个ObjectProvider的写法,第一次看到,查了一下资料,spring4.3之后的新特性,有延迟加载的作用。
/**
* A variant of {@link ObjectFactory} designed specifically for injection points,
* allowing for programmatic optionality and lenient not-unique handling.
*
* @author Juergen Hoeller
* @since 4.3
*/
public interface ObjectProvider<T> extends ObjectFactory<T> {
这里参数plugins的类型是List,可以包含若干个SoulPlugin实现类实例,项目启动的过程中会先实例化所有实现了SoulPlugin接口的类,前提是已经starter进去的类,例如WebClientPlugin,打上几个断点调试一下流程,如下图所示。
从加载的顺序可以看出确实延迟加载了,等所有的SoulPlugin实现类实例完成,开始实例化SoulWebHandler,把plugins作为参数传进去,然后把list拿出来,这里注意plugins是按照PluginEnum枚举类的code字段有小到大排序的,这个顺序也是后续整个插件调用链的顺序,然后返回一个SoulWebHandler实例。
进到SoulWebHandler类,执行构造方法,把拿到的所有plugins赋值给成员变量plugins。
二、调用插件
SoulWebHandler 这个类实现了WebHandler,可以进行Http请求处理,在每次http请求时,handle方法执行插件调用链,打上断点debug。问题来了,这个handle方法的exchange参数是怎么来的呢。
public final class SoulWebHandler implements WebHandler {
//省略
@Override
public Mono<Void> handle(@NonNull final ServerWebExchange exchange) {
MetricsTrackerFacade.getInstance().counterInc(MetricsLabelEnum.REQUEST_TOTAL.getName());
Optional<HistogramMetricsTrackerDelegate> startTimer = MetricsTrackerFacade.getInstance().histogramStartTimer(MetricsLabelEnum.REQUEST_LATENCY.getName());
return new DefaultSoulPluginChain(plugins).execute(exchange).subscribeOn(scheduler)
.doOnSuccess(t -> startTimer.ifPresent(time -> MetricsTrackerFacade.getInstance().histogramObserveDuration(time)));
}
}
发送一次http请求,debug看一下调用栈,netty的东西,看不太懂。
大概是找到了这里,可能就是接收请求的地方。
这里看了一下soul-bootstrap里面的一个netty的配置