soul从入门到放弃7--浅析请求转发路径

一、前戏

本篇文章,将梳理soul作为网关的核心功能,请求处理、转发、响应的整个过程。

二、责任链

通过前几篇的源码学习,知道了soul的请求相关处理的多个模块,是基于责任链模式。以达到插件式热插拔,高内聚低耦合易扩展的特性。

  • 责任链模式的概念

多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

soul的职责链是通过数组实现的,而非链表。为了便于后文的理解,此处放一个code demo。

public interface IHandler {
  boolean handle();
}

public class HandlerA implements IHandler {
  @Override
  public boolean handle() {
    boolean handled = false;
    //...
    return handled;
  }
}

public class HandlerB implements IHandler {
  @Override
  public boolean handle() {
    boolean handled = false;
    //...
    return handled;
  }
}

public class HandlerChain {
  private List handlers = new ArrayList<>();

  public void addHandler(IHandler handler) {
    this.handlers.add(handler);
  }

  public void handle() {
    for (IHandler handler : handlers) {
      boolean handled = handler.handle();
      if (handled) {
        break;
      }
    }
  }
}

// 使用举例
public class Application {
  public static void main(String[] args) {
    HandlerChain chain = new HandlerChain();
    chain.addHandler(new HandlerA());
    chain.addHandler(new HandlerB());
    chain.handle();
  • soul中的责任链如何构建?

在SoulConfiguration(soul-web)中soulWebHandler方法


image.png

通过ObjectProvider加载所有SoulPlugin的实现类,并按照order进行排序,确定责任链的执行顺序。

  • 责任链的调用 -- DefaultSoulPluginChain
public Mono execute(final ServerWebExchange exchange) {
    return Mono.defer(() -> {
        if (this.index < plugins.size()) {
            // 获取当前需要执行的 SoulPlugin 插件,同时index++
            SoulPlugin plugin = plugins.get(this.index++);
            //如果插件需要跳过,则直接递归调用本身,相当于调用下一个插件
            Boolean skip = plugin.skip(exchange);
            if (skip) {
                return this.execute(exchange);
            }
            //exchange 和 插件链本身(this)做为方法参数
            return plugin.execute(exchange, this);
        }
        return Mono.empty();
    });
}

plugins中包含当前需要执行的所有插件,通过递增偏移量index,取出插件。如果插件需要跳过,则递归调用execute方法,不跳过执行当前插件的execute方法。

把当前调用链实例this作为传参数,在AbstractSoulPlugin##doExecute或其实现类中***Plugin##doExecute中调用chain.execute,从而继续执行下一个插件。

@Override
protected Mono doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
    // some code
    return chain.execute(exchange);
}

SoulWebHandler中总共有17个调用链,调用顺序如下

GlobalPlugin

SignPlugin

WafPlugin

RateLimiterPlugin

HystrixPlugin

Resilience4JPlugin

DividePlugin

WebClientPlugin

WebSocketPlugin

BodyParamPlugin

BodyParamPlugin

SofaPlugin

AlibabaDubboPlugin

MonitorPlugin

WebClientResponsePlugin

SofaResponsePlugin

DubboResponsePlugin

  • skip与enabled

AbstractSoulPlugin##execut,根据admin-soul设置插件的启用/停用,动态判断

image.png

****Plugin##skip,用于判断当前强求是否属于当前插件职责范围内,静态判断

image.png
  • Mono.defer(() )

异步非阻塞的响应式编程,保证了soul能用对高并发

科普贴:https://zhuanlan.zhihu.com/p/92460075

三、请求转发路径探索

责任链调用,其实是请求链路的中后处理过程。下面debug调试下,梳理整条完整路径

1.SoulWebHandler#execute挂上断点,postman发起一下请求,通过调用栈向上查找


image.png

2.来到DefaultWebFilterChain,继续挂上断点,postman发起一下请求

image.png

3.深挖调用栈我们来到熟悉的netty的处理类

image.png

image.png

梳理下前半段接收请求的流程

HttpServerOperations : netty的请求入口

TcpServerBind

HttpServerHandle

ReactorHttpHandlerAdapter :生成response和request

ReactiveWebServerApplicationContext

HttpWebHandlerAdapter :ServerWebExchange

exchange 的生成

ExceptionHandlingWebHandler

WebHandlerDecorator

FilteringWebHandler

DefaultWebFilterChain

SoulWebHandler :plugins调用链

整体调用链如下:


image.png

四、小结

  • 从整个调用链中部责任链切入,先捋清下游责任链的调用关系。再追加断点调试打法,一点点的向上搜寻,最终完成描绘出整条链路
  • 后续文章将对17个插件,逐个分析
  • 日拱一卒,每天进步一点点

你可能感兴趣的:(soul从入门到放弃7--浅析请求转发路径)