Soul网关源码学习(7)- 代理转发流程概览2

前言

在前一篇文章《Soul网关源码学习(6)- 代理转发流程概览》中,我们学习了:

  • Soul 插件链在整个网关中扮演着至关重要的角色。
  • 学习了插件链的实现方式,即是如何传递执行。
  • 还了解了插件如何跳过执行。
    • 一种是通过调用插件的 skip 方法判断,这种类型插件一般是协议相关的插件,通过在 skip 方法中匹配协议是否符合。
    • 一种是模板方法 AbstractSoulPlugin#execute(ServerWebExchange, SoulPluginChain) 中的实现,通过判断插件在 Admin 控制台的配置状态来决定是否执行,实现的是插件开关的动态配置。比如:流量控制、熔断的打开关闭。
  • 除此之外要知道了:
    • 插件来自哪里:内置公有插件(比如:GlobalPlugin),Pom 依赖(Spring boot 的自动装配)。
    • 怎么样才会被执行:首先要被依赖加载,其次 skip 方法不能为真(比如协议不匹配),最后控制的配置要打开。
  • 最后,我们以 Http 代理转发流程为切入点,学习了代理转发的执行流程,知道了我们的请求到底是怎么进入网关的,最后又是从哪里出来的。

那接下来我们再来通过分析其他几个协议的执行流程,然后对比它们的异同,从而有点入面,最后能对 Soul 的代理转发流程有一个清晰的理解,为后面更加深入分析打下基础。

对比不同协议的代理转发流程

我们首先在网关服务的 Pom 文件中引入下面协议转发所需要的插件依赖,同时需要在 admin 页面中打开协议代理的相应插件,不了解的小伙伴可以去翻一下我前面的几篇文章,都有相应的配置介绍。

dobbu

我们和分析 Http 代理的时候一样,通过的 debug 跟踪的方式,方法和过程和 前一篇文章中分析 Http 代理流程几乎如出一辙,因此这里就直接贴 debug 结果了。
在这里插入图片描述

  • GlobalPlugin : 构造 SoulContext,SoulContext 是 Soul 网关层面的代理请求的一个上下文,里面有请求相关的信息,比如协议,请求方法等。
  • BodyParamPlugin:Http 的请求转换成 dubbo 泛化调用的字符串参数。
  • ApacheDubboPlugin:根据规则获取调用的目标服务,发起 rpc 请求,并且把返回结果传递到下一个插件。
    • 这里说的规则是 admin 中配置的调用规则,比如负载均衡权重。这个在前面文章《Soul网关源码学习(3)- Dubbo代理的配置和测试》中有说明,不了解的可以跳过去看一下。
    • soul 在代理流程中,除了 SoulContext 这个上下文外,大量的使用了 ServerWebExchange 的 Attribute 来进行传递,它可以通过键值对的形式进行存储,ServerWebExchange 会在访问入口处有spring 自动创建,然后在整个插件链中传递。Dubbo 的参数、结果包括SoulContext 等都是通过这种方式进行传递的。
  • DubboResponsePlugin:把 dubbo 返回的结果包装成 Http 常用的 restful 形式返回给客户端。

sofa

接着我们再来跟踪 Sofa 的代理转发流程,Sofa 和 Dubbo 的流程可以说几乎一模一样:
在这里插入图片描述

  • GlobalPlugin : 同上。
  • BodyParamPlugin:名字一样,但是这是 sofa 插件包下的类,功能上面 dubbo 的一样,Http 请求 适配成 sofa 调用参数。
  • SofaPlugin:根据配置的规则获取目标服务地址,发起 rpc 请求,并将返回结果传递给后面的插件进行处理。
  • SofaResponsePlugin: 把 Sofa 返回的结果包装成 restful 的形式返回给客户端。

spring cloud

最后我们来看一下Spring cloud:
在这里插入图片描述
从上面可以看出 Spring cloud 和普通的 Http 调用只有一个插件不一样(Http 的流程分析可以看上一篇文章)。这也不难理解,因为 Spring cloud 的 rpc 调用本来走的就是 Http 协议,唯一不一样的是在目标地址的选择上,也就是 SpringCloudPlugin 和 DividePlugin 插件的区别。

DividePlugin :普通的 Http 服务器,把接口上传到 soul amin,并且在上面进行代理规则的配置,本质上就是把 soul 控制台当作了一个注册中心,suol 对于负载均衡这些有着全部的控制器权.

SpringCloudPlugin : Spring Cloud 有着自己的微服务注册中心,这些注册中心上可能有着 Spring Cloud 自己的管理策略,Soul 是没有办法控制的,Soul 只能通过把自己注册为微服务集群的一部分,通过 Spring Cloud的机制去获取相应的服务主机,再配合自己的配置的规则进行过滤,最后得出目标地址。

//这是 SpringCloudPlugin 的 doExecute 方法
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
    
    
		...
		//上半部分,通过 soul 控制台配置的规则,选择出serverId
		//有可能没有,比如:soul 的规则可以根据接口不同进行过滤
        final SpringCloudSelectorHandle selectorHandle = GsonUtils.getInstance().fromJson(selector.getHandle(), SpringCloudSelectorHandle.class);
		//通过spring 的 ribbon 进行负载均衡
		//这里走的就是Spring cloud 自己的微服务管理策略
        final ServiceInstance serviceInstance = loadBalancer.choose(selectorHandle.getServiceId());
        if (Objects.isNull(serviceInstance)) {
    
    
            Object error = SoulResultWrap.error(SoulResultEnum.SPRINGCLOUD_SERVICEID_IS_ERROR.getCode(), SoulResultEnum.SPRINGCLOUD_SERVICEID_IS_ERROR.getMsg(), null);
            return WebFluxResultUtils.result(exchange, error);
        }
		...
		//构造出真正的访问地址,后面就和普通的 Http 访问一样了。
        String realURL = buildRealURL(uri.toASCIIString(), soulContext.getHttpMethod(), exchange.getRequest().getURI().getQuery());
        ...
        return chain.execute(exchange);
    }

不同协议的代理转发流程总结

在这里插入图片描述

通过上面的图片,我们就能很清晰地看到不同协议的代理转发流向,这对我们后面深入分析源码是有好处的。如果“代理转发”是主干,那么不同协议就是主干分叉出来的枝条,而协议的每一步处理流程(插件)就是关键节点,而这些节点周围又环绕着很多辅助功能节点(功能插件)。我们顺着主干,切换分支,然后接着深入关键节点,最后再了解周围的功能。因此,先有一个层次上的清晰了解还是很重要的。

总结

到目前为止,我们都是在从流程层次上去分析,没有深入到流程的具体步骤,就像读书一样,只观其大意肯定是不行的,那么接下来我们就从第一条分支,普通 Http 代理开始,对其每个步骤进行深入分析。

猜你喜欢

转载自blog.csdn.net/u012180773/article/details/112976328
今日推荐