Soul源码学习(二)——http服务调用详解

概述

我们知道soul网关支持多种协议的,其中http协议应该是最基本也是平时使用最多的协议。

开始实践之前,我们可以梳理一下网关的基本功能,需要考虑什么问题呢?

先梳理一下加入网关后的调用流程:

客户端http请求->网关->后端服务。

  1. 可以看到,网关是一个服务器,可以接受请求和转发请求。
  2. 经过网关的请求,需要对url进行解析,判断其是否满足转发到后端服务的条件
  3. 如果后端服务有多个,需要考虑负责均衡策略。
  4. 网关调用后端服务,那么必定要知道后端服务的地址,有两种方式
    • 将后端地址配置在网关服务中(如spring cloud gateway)
    • 网关服务主动去获取后端地址(soul网关的决策)
  5. 网关调用后端接口服务采用的方式,及RPC的方式。

带着以上思考,我们开始正式的实践操作吧。

实战练习

启动soul-admin和soul-bootstrap项目

上一篇我们了解了soul的架构,知道了admin和bootstrap的关系。

我们知道了网关服务(bootstrap)都是通过admin服务与后端服务交互信息的,这里admin服务起到一个配置信息中转的角色。后端服务通过向admin注册的方式,将自身的网关路由规则注册到admin,然后admin实时同步给soul网关,soul网关缓存下来。这样网关不需要配置后端服务的信息,也可以做到带有请求规则的转发。

启动soul-examples-http项目

  • 配置soul-admin的地址,以及需要注册的信息。
soul:
  http:
    adminUrl: http://localhost:9095 #admin的后台地址
    port: 8188 #端口号
    contextPath: /http #这里可以理解为本应用在网关的一个入口地址
    appName: http
    full: false #false自定义流量,需要配置规则,true为全流量。
  • 查看pom引用,特殊的可以看到引用了一个soul的mvc客户端。
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-spring-boot-starter-client-springmvc</artifactId>
            <version>${soul.version}</version>
        </dependency>

这样我们可以在项目中通过在接口上添加注解的方式,将接口注册到admin服务中去。

我们可以猜测@SoulSpringMvcClient注解的作用就是定义网关的规则,并注册到admin的配置中去。

    @PostMapping("/save")
    @SoulSpringMvcClient(path = "/save" , desc = "Save order")
    public OrderDTO save(@RequestBody final OrderDTO orderDTO) {
    
    
        orderDTO.setName("hello world save order");
        return orderDTO;
    }

  • 启动SoulTestHttpApplication项目,我们可以在控制台中看到以下日志信息:
    在这里插入图片描述

  • 登录admin控制台的插件列表,选择divide,可以查看刚刚SoulTestHttpApplication应用注册上来的信息。

通过比对可以发现,选择器的配置信息对应了我们SoulTestHttpApplication项目里application.yaml中的配置信息,而右边的规则列表则是由添加了 @SoulSpringMvcClient注解的接口生成注册的。

在这里插入图片描述

左边部分选择器列表,右边部分选择器规则列表,可以看到选择器和规则的是一对多的对应关系。

这里引出了我们插件最重要的两个核心概念:选择器规则

选择器

在这里插入图片描述
字段详解:

  • 名称:为你的选择器起一个容易分辨的名字
  • 类型:custom 是自定义流量,full 是全流量。自定义流量就是请求会走你下面的匹配方式与条件。全流量则不走。
  • 匹配方式:and 或者or 是指下面多个条件是按照and 还是or的方式来组合。
  • 条件:
    • uri:是指你根据uri的方式来筛选流量,match的方式支持模糊匹配(/**)
    • header:是指根据请求头里面的字段来筛选流量。
    • query: 是指根据uri的查询条件来进行筛选流量。
    • ip:是指根据你请求的真实ip,来筛选流量。
    • host:是指根据你请求的真实host,来筛选流量。
    • post:建议不要使用。
    • 条件匹配:
      • match : 模糊匹配,建议和uri条件搭配,支持 restful风格的匹配。(/test/**)
      • = : 前后值相等,才能匹配。
      • regEx : 正则匹配,表示前面一个值去匹配后面的正则表达式。
      • like :字符串模糊匹配。
  • 是否开启:打开才会生效
  • 打印日志:打开的时候,当匹配上的时候,会打印匹配日志。
  • 执行顺序:当多个选择器的时候,执行顺序小的优先执行。
  • 选择器建议 : 可以uri 条件, match 前缀 (/contextPath),进行第一道流量筛选。

规则

在这里插入图片描述

  • 当流量经过选择器匹配成功之后,会进入规则来进行最终的流量匹配。
  • 规则是对流量最终执行逻辑的确认。
  • 规则详解:
    • 名称:为你的规则起一个容易分辨的名字
    • 匹配方式:and 或者or 是指下面多个条件是按照and 还是or。
    • 条件:
      • uri:是指你根据uri的方式来筛选流量,match的方式支持模糊匹配(/**)
      • header:是指根据请求头里面的字段来筛选流量。
      • query: 是指根据uri的查询条件来进行筛选流量。
      • ip:是指根据你请求的真实ip,来筛选流量。
      • host:是指根据你请求的真实host,来筛选流量。
      • post:建议不要使用。
      • 条件匹配:
        • match : 模糊匹配,建议和uri条件搭配,支持 restful风格的匹配。(/test/**)
        • = : 前后值相等,才能匹配。
        • regEx : 正则匹配,表示前面一个值去匹配后面的正则表达式。
        • like :字符串模糊匹配。
    • 是否开启:打开才会生效。
    • 打印日志:打开的时候,当匹配上的时候,会打印匹配日志。
    • 执行顺序:当多个选择器的时候,执行顺序小的优先执行。
    • 处理:每个插件的规则处理不一样,具体的差有具体的处理,具体请查看每个对应插件的处理。
  • 上图表示:当 uri 等于 /http/order/save 的时候该规则被匹配,就会执行该规则中,负载策略是 random
  • 联合选择器,我们来表述一下 :当一个 请求的 uri/http/order/save, 会通过 random 的方式,转发到 1.1.1.1:8080
  • 规则建议: 可以uri 条件, match 最真实的uri路径,进行流量的最终筛选 。

条件详解

  • uri 匹配 (推荐)
    • uri匹配是根据你请求路径中的uri来进行匹配,在接入网关的时候,前端几乎不用做任何更改。
    • 当使用 match 方式匹配时候,同 springmvc 模糊匹配原理相同。
    • 在选择器中,推荐使用uri中的前缀来进行匹配,而在规则中,则使用具体路径来进行匹配。
    • 该匹配方式的时候,在匹配字段名称可以任意填写,匹配字段值需要正确填写。
  • header 匹配
    • header是根据你的http 请求头中的字段值来匹配。
  • query 匹配
    • 这个是根据你的uri中的查询参数来进行匹配,比如 /test?a=1&&b=2 ,那么可以选择该匹配方式。
    • 上述就可以新增一个条件,选取 query方式 , a = 1 。
  • ip匹配
    • 这个是根据 http调用方的 ip来进行匹配。
    • 尤其是在waf插件里面,如果发现一个ip地址有攻击,可以新增一条匹配条件,填上该ip,拒绝该ip的访问。
    • 如果在soul前面使用了nginx代理,为了获取正确的ip,你可能要参考 dev-iphost
  • host匹配
    • 这个是根据 http调用方的host来进行匹配。
    • 尤其是在waf插件里面,如果发现一个host地址有攻击,可以新增一条匹配条件,填上该host,拒绝该host的访问。
    • 如果在soul前面使用了nginx代理,为了获取正确的host,你可能要参考 dev-iphost
  • post匹配
    • 不推荐使用。

使用Postman调用soul网关进行转发

  1. 打开postman测试后端http服务是否能正常调用。
    在这里插入图片描述

  2. 通过调用soul网关来访问后端http服务,如果结果如上图所示说明访问成功。
    在这里插入图片描述
    以上通过soul网关进行单机版的http服务转发已经实现了,继续添加一个http后端服务,测试soul的负载均衡功能

  3. 添加第二个http后端服务

    如下图,本地复制一个SoulTestHttpApplication应用,修改端口号8189,启动服务。

    server:
      port: 8189
      address: 0.0.0.0
    
    soul:
      http:
        adminUrl: http://localhost:9095
        port: 8189
        contextPath: /http
        appName: http
        full: false
    

    打开admin编辑插件——选择器/http,可以看到选择器/http中多处了一行配置,这个是端口号为8189的服务配置。
    在这里插入图片描述
    修改weight参数,通过postman请求soul网关服务,观察负载的概率分布是否与weight的参数比符合。

这里需要将soul网关的服务的日志改为debug级别,才能观察。

logging:
    level:
        root: info
        org.springframework.boot: info
        org.apache.ibatis: info
        org.dromara.soul.bonuspoint: info
        org.dromara.soul.lottery: info
        org.dromara.soul: debug

实践结论

以上,通过实践我们可以验证我们之前思考的问题。

  1. 可以看到,网关是一个服务器,可以接受请求和转发请求。

    soul网关是一个基于netty的服务器,决定了它的高性能。

  2. 经过网关的请求,需要对url进行解析,判断其是否满足转发到后端服务的条件

    • 选择器(例子中的/http)决定了我们访问那个后端应用,从而把我们的流量限制在具体的某个后端服务。

    • 规则决定了我们更为细致的判断条件,并且可以从多个维度url、header、query等来限制请求,从而更近一步限制了流量。

  3. 如果后端服务有多个,需要考虑负责均衡策略。

    针对每个接口我们都可以控制其开关及负载均衡策略,这个在规则中可以配置。

  4. 网关调用后端服务,那么必定要知道后端服务的地址,有两种方式

    • 将后端地址配置在网关服务中(如spring cloud gateway)
    • 网关服务主动去获取后端地址(soul网关的决策)

    这部分在后面的章节再分析。

  5. 网关调用后端接口服务采用的方式,及RPC的方式。

    Soul网关既然是插件式的,那么这个rpc方式肯定是可以变化的,这里是采用http的方式,通过动态代理来与后端交互的。

思考总结

和Spring Cloud Gateway网关的思路差不多,**网关所做的事情主要就是服务的转发,但是并不是所有的请求都可以被服务的,必定要满足后端服务规则的请求才能被转发给后端服务。**因此如何设计判断规则是网关的重点。

Soul网关采用选择器+规则的方式,来组织请求的判断的规则,一个选择器对应多个规则,一个规则又对应多个条件。这个模型就好比一个后端服务有多个服务接口,一个接口有多个限制条件。如下图所示:
在这里插入图片描述

这样,在我们的微服务架构中,我们可以为每个服务配置一个选择器,分别为每个接口(对应的是rule)配置其具体限制条件(condition)。

以上这一切在soul网关中不需要我们手动配置,只需要在我们的服务中通过在接口上添加注解的方式来实现。

猜你喜欢

转载自blog.csdn.net/u010084384/article/details/112688724