Soul网关源码分析-请求从浏览器端如何通过soul转发到后台

在上一篇中,我分析了接入soul的springBoot应用,是如何在启动时将拦截规则同步到soul-admin的,那么在这一讲中,我们一起从源码的角度来看看一个web请求,是如何经过soul转发到后台的。

还是跟上一讲一样,我先把代码跟踪结果发出来,再来看看我是如何一步步得出这个结论的,通过跟踪代码梳理出来的流程如下图所示:
web请求转发
上图中标了红色字体的表示还存在疑问的,但是只是细节的问题,大体的流程是明确的,下面来讲讲我在分析这个流程时的思路:
首先来看看这次用来测试的URL地址,如下:

http://localhost:9195/http/test/findByUserId?userId=3

这个URL要达到的目标是将请求转发到soul-example-http这个后台应用,根据之前我们讲过的内容,可以知道这个9195端口是soul核心模块soul-bootstrap模块提供给我们访问的端口,然后我们这次soul-example-http应用的contextPath和appName都是http,所以真正和业务相关的是test/findByUserId?userId=3这一段

那么只看这个URL,该从哪里开始分析soul的源码呢,还是按照之前的思路,在没有任何思路的情况下,发起这个请求,看看soul-bootstrap模块的日志打印了什么内容,因为按我的预期,这个请求的URL是要经过soul转发处理的,而soul-bootstrap作为soul的核心模块,它的日志输出信息就很关键,可以看到输出的日志内容如下:

2021-01-19 02:14:09.606  INFO 65884 --- [work-threads-19] o.d.soul.plugin.base.AbstractSoulPlugin  : divide selector success match , selector name :/http
2021-01-19 02:14:09.607  INFO 65884 --- [work-threads-19] o.d.soul.plugin.base.AbstractSoulPlugin  : divide selector success match , selector name :/http/test/**
2021-01-19 02:14:09.610  INFO 65884 --- [work-threads-19] o.d.s.plugin.httpclient.WebClientPlugin  : The request urlPath is http://192.168.137.1:8188/test/findByUserId?userId=3, retryTimes is 0

通过观察日志,发现打印的内容中有两个重要的类,分别是WebClientPlugin和AbstractSoulPlugin,先看看WebClientPlugin这个类,可以看到"The request urlPath"这个日志信息是在execute这个方法中打印的,如下图所示:
WebClientPlugin
再看看这个AbstractSoulPlugin类,"selector success match"日志信息是在这里打印的,如下图所示:
AbstractSoulPlugin
我们现在可以确定的是,请求经过soul转发处理后,肯定是先后调了AbstractSoulPlugin和WebClientPlugin的,但是这两个类看起来都不像是入口类,从命名来看,都是插件类,那入口类是哪个呢,我尝试通过ctrl+鼠标点击的方式查看WebClientPlugin类的execute方法都有谁在调用,试图通过这种方式找出上层调用方代码,从而找出入口代码,查找结果如下图所示:
WebClientPlugin2
图中展示有很多地方都调用到了WebClientPlugin这个类的execute方法,但是仔细一看,几乎全部都是junit的单元测试类,只有SoulWebHandler这个类不是单元测试类,从命名来看,结合以前学习springMVC的经验,XXXHandler就像是控制器,我们打开这个类调用处看看,如下图:
SoulWebHandler
从图中可以看到调用处的代码是在对很多个插件在做遍历,挨个调用对应插件的execute方法,这里看起来就有点像是入口类的意思了,这里还是带有一定程度的猜想,我接着再看看这个SoulWebHandler类和soul核心模块soul-bootstrap的关系,SoulWebHandler这个类是在soul-web中的,也就是需要研究下soul-web和soul-bootstrap之间的关系。

为了找出这两个模块之间的关系,我又去看了soul-bootstrap的代码,发现除了启动类SoulBootstrapApplication之外,没有看到任何和soul-web相关的代码,然后再看看pom.xml配置文件,除了加载了一堆插件的starter外,看到一个soul-spring-boot-starter-gateway,感觉这里应该就是突破口了,然后再去找soul-spring-boot-starter-gateway这个模块到底做了什么,看到这个模块其实啥也没有,只有一个spring.provides,里面的内容是:

provides: soul-web

谜底揭开了,就是通过soul-spring-boot-starter-gateway跟soul-web产生关系的!再看看soul-spring-boot-starter-gateway模块的pom.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Licensed to the Apache Software Foundation (ASF) under one or more
  ~ contributor license agreements.  See the NOTICE file distributed with
  ~ this work for additional information regarding copyright ownership.
  ~ The ASF licenses this file to You under the Apache License, Version 2.0
  ~ (the "License"); you may not use this file except in compliance with
  ~ the License.  You may obtain a copy of the License at
  ~
  ~     http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>soul-spring-boot-starter</artifactId>
        <groupId>org.dromara</groupId>
        <version>2.2.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <artifactId>soul-spring-boot-starter-gateway</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-web</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>

</project>

可以看到,soul-spring-boot-starter-gateway这个模块做的事情就是加在了soul-web模块,OK,到这里已经证明了我们上面的猜想,入口程序是soul-web模块的SoulWebHandler类,然后请求分别调用了AbstractSoulPlugin和WebClientPlugin这两个类处理,后来我在debug的过程中发现,负载均衡相关的额处理主要是用到了DividePlugin这个类,通过打断点一步步跟踪调试,基本上梳理出来的流程就是文章开头所述的流程。

总结:
最后还是要总结一下,今晚总算搞清楚了请求在发送到soul之后,是如何处理并转发到后台应用服务的,今晚在debug过程中首次看到了响应式编程相关的WebClient,回头好好研究一下,后续争取写一篇文章记录一下响应式编程相关的知识,今晚源码分析就到这里了,也总算达到目标了,不过图中标红字的细节还是有些没完全捋清楚,明天再研究,此外,明天还计划分析一下soul对接DUBBO的处理。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页