Soul 请求处理概览
环境准备
- 启用soul-admin服务,soul-bootstrap服务
- 运行soul-examples下的http示例,将http示例接入soul网关
请求流程追踪
页面请求被代理的地址
- 页面请求被代理地址
- 查看控制台
o.d.soul.plugin.base.AbstractSoulPlugin : divide selector success match , selector name :/http
o.d.soul.plugin.base.AbstractSoulPlugin : divide selector success match , selector name :/http/test/**
o.d.s.plugin.httpclient.WebClientPlugin : The request urlPath is http://127.0.0.1:8189/test/findByUserId?userId=10, retryTimes is 0
发现在WebClientPlugin类中有对应日志输出,再该处打上断点再次进行调试,最终追溯如下图:
在此可以方法,调用方在DefaultSoulPluginChain的excute方法
- 在DefaultSoulPluginChain的excute方法中打上断点,再次查看是哪个地方进行了调用,最终找到调用方为SoulWebHandler的handle方法
@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)));
}
在handle方法中明显可以看到执行了刚在所追踪的excute方法,后续还执行了doOnsuccess方法,根据MetricsTrackerFacade相关代码可以发现,doOnSuccess主要是为了记录执行成功后统计的一些指标,这里不做过多赘述,可在后期进行指标模块相关追溯时在进行详细讨论。
Mono 是响应式编程中的东西,鉴于本人暂不熟悉,此处不做过多探讨
追踪DefaultSoulPluginChain的excute方法具体作用
我们大体梳理一下首先请求访问了handle方法(当然前置还有很多处理,这里后期进行追踪),在handle方法中又调用了DefaultSoulPluginChain的excute方法,接下来追踪一下excute方法具体做了哪些事情。
public Mono<Void> execute(final ServerWebExchange exchange) {
return Mono.defer(() -> {
if (this.index < plugins.size()) {
SoulPlugin plugin = plugins.get(this.index++);
Boolean skip = plugin.skip(exchange);
//是否跳过
if (skip) {
//再此处可以理解成 continue;
return this.execute(exchange);
}
return plugin.execute(exchange, this);
}
return Mono.empty();
});
}
在这里我们发现了这里又是一个响应式编程的示例,但在此处我们可以直接看其内部的代码逻辑
- 首先是从plugins集合获取对应的插件信息
plugins集合从哪里来的呢?通过追溯可以得知是从SoulConfiguration-->SoulWebHandler-->DefaultSoulPluginChain的属性值中,这里不做详细介绍
- 其次执行各个插件子类的plugin.skip(exchange)方法,来判断该插件是否执行插件的具体逻辑
- 打断点 查看插件集合,如下图

可以发现 一共注入到list中14个插件集合,通过名称大体可以区分 如表所示
| 插件名称 | 作用 |
|---|---|
| GlobePlugin | 根据名称推测 全局插件 暂不清楚作用 |
| SignPlugin | 鉴权插件 |
| WafPlugin | 控制访问插件 |
| HystrixPlugin | 熔断插件?? 有待追踪 |
| ResiliencePlugin | 弹性插件?? 有待追踪 |
| DividePlugin | 划分插件? |
| WebClientPlugin | 网络客户端插件 |
| WebSocketPlugin | websocket插件 |
| BodyParamPlugin | 身体参数插件 感觉也是个全局插件 有待追踪 |
| AlibabaDubboPlugin | dubbo插件 从这个可以猜测出 alibaba和apche在soul上进行调用dubbo的泛化接口应该走的是同一插件 |
| MonitorPlugin | 监控插件 |
| WebClientResponsePlugin | 客户端返回插件 |
| DubboResponsePlugin | dubbo返回插件 |
可以从上述看出 插件链式调用是整个soul的核心
由于代理的http服务是在divide插件上进行操作的,可以判断在整个处理流程中一定会走divide插件的处理流程。
接下来debug整个插件请求流程
我在skip处打上了断点发现了一次代理http的请求 居然走了两轮链式调用,百思不得其解,第一轮的链式调用全走完了,第二轮的链式调用在divide插件处直接返回。
本篇文章20200120点到为止 明日继续,响应式编程看起来好难受呀....各种调用各种飞。
优雅的分隔线 2020121
在昨天的笔记中,整体逻辑梳理的有点绕了,今天特意把整体涉及到插件的相关类都大体梳理了一下,如下图所示。
明天接着介绍,今天点到为止。