Apache-shenYu源码阅读05-请求处理概览

502 阅读3分钟

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网络客户端插件
WebSocketPluginwebsocket插件
BodyParamPlugin身体参数插件 感觉也是个全局插件 有待追踪
AlibabaDubboPlugindubbo插件 从这个可以猜测出 alibaba和apche在soul上进行调用dubbo的泛化接口应该走的是同一插件
MonitorPlugin监控插件
WebClientResponsePlugin客户端返回插件
DubboResponsePlugindubbo返回插件

可以从上述看出 插件链式调用是整个soul的核心

由于代理的http服务是在divide插件上进行操作的,可以判断在整个处理流程中一定会走divide插件的处理流程。

接下来debug整个插件请求流程

我在skip处打上了断点发现了一次代理http的请求 居然走了两轮链式调用,百思不得其解,第一轮的链式调用全走完了,第二轮的链式调用在divide插件处直接返回。

本篇文章20200120点到为止 明日继续,响应式编程看起来好难受呀....各种调用各种飞。


优雅的分隔线 2020121

在昨天的笔记中,整体逻辑梳理的有点绕了,今天特意把整体涉及到插件的相关类都大体梳理了一下,如下图所示。 明天接着介绍,今天点到为止。