可扩展、高性能、响应迅速的API网关——Soul进行http请求的代理(二)

本文章将成系列介绍:包含但不限于高性能微服务API网关Soul的环境搭建、源码设计

本章节介绍使用soul进行http请求的代理

概述

配置http请求的代理将使用到:

  • divide插件

  • soul-spring-boot-starter-plugin-divide、soul-spring-boot-starter-plugin-httpclient依赖(网关端)

  • soul-spring-boot-starter-client-springmvc依赖(业务系统端)

  • yml文件的配置

    soul:
      http:
        adminUrl: http://localhost:9095 #为你启动的soul-admin 项目的ip + 端口,注意要加http://
        port: 8189 #你本项目的启动端口
        contextPath: /http #为你的这个mvc项目在soul网关的路由前缀。 比如/order,/product等等,网关会根据你的这个前缀来进行路由.
        appName: http #你的应用名称,不配置的话,会默认取`spring.application.name`的值
        full: false #设置true 代表代理你的整个服务,false表示代理你其中某几个controller
    
  • @SoulSpringMvcClient 注解(加在controller的接口上)

    • 举例

      你可以把注解加到 Controller 类上面, 里面的path属性则为前缀,如果含有 /** 代表你的整个接口需要被网关代理。

      举例子 (1): 代表 /test/payment, /test/findByUserId 都会被网关代理。

      @RestController
      @RequestMapping("/test")
      @SoulSpringMvcClient(path = "/test/**")
      public class HttpTestController {
      
          /**
           * Post user dto.
           *
           * @param userDTO the user dto
           * @return the user dto
           */
          @PostMapping("/payment")
          public UserDTO post(@RequestBody final UserDTO userDTO) {
              return userDTO;
          }
      
          /**
           * Find by user id string.
           *
           * @param userId the user id
           * @return the string
           */
          @GetMapping("/findByUserId")
          public UserDTO findByUserId(@RequestParam("userId") final String userId) {
              UserDTO userDTO = new UserDTO();
              userDTO.setUserId(userId);
              userDTO.setUserName("hello world");
              return userDTO;
          }
      
      }
      

      举例子 (2): 代表 /order/save,会被网关代理,而/order/findById 则不会。

      @RestController
      @RequestMapping("/order")
      @SoulSpringMvcClient(path = "/order")
      public class OrderController {
      
          /**
           * Save order dto.
           *
           * @param orderDTO the order dto
           * @return the order dto
           */
          @PostMapping("/save")
          @SoulSpringMvcClient(path = "/save" , desc = "Save order")
          public OrderDTO save(@RequestBody final OrderDTO orderDTO) {
              orderDTO.setName("hello world save order");
              return orderDTO;
          }
      
          /**
           * Find by id order dto.
           *
           * @param id the id
           * @return the order dto
           */
          @GetMapping("/findById")
          public OrderDTO findById(@RequestParam("id") final String id) {
              OrderDTO orderDTO = new OrderDTO();
              orderDTO.setId(id);
              orderDTO.setName("hello world findById");
              return orderDTO;
          }
          
      }
      

示例步骤

  1. 启动soul-admin(插件和其他信息配置的管理后台)、soul-bootstrap(网关项目);

  2. 配置业务工程(以soul-examples项下soul-examples-http为例)中的controller、application.yml,在application.yml中添加:

    soul:
      http:
        adminUrl: http://localhost:9095 #为你启动的soul-admin 项目的ip + 端口,注意要加http://
        port: 8189 #你本项目的启动端口
        contextPath: /http #为你的这个mvc项目在soul网关的路由前缀。 比如/order,/product等等,网关会根据你的这个前缀来进行路由.
        appName: http #你的应用名称,不配置的话,会默认取`spring.application.name`的值
        full: false #设置true 代表代理你的整个服务,false表示代理你其中某几个controller
    

    为controller中你所需的程序加上对应注解;

  3. 启动业务工程,会打印出对应的URI映射信息,如:

    在这里插入图片描述

  4. 在soul-admin页面中可进行divide插件配置

    divide插件介绍

    divide插件是网关处理 http协议请求的核心处理插件。

    插件设置
    • 开启插件, soul-admin --> 插件管理–> divide 设置为启用;

    • divide插件,配合如下 starter一起才能生效(网关项目中依赖即可)

      <!--if you use http proxy start this-->
      <dependency>
          <groupId>org.dromara</groupId>
          <artifactId>soul-spring-boot-starter-plugin-divide</artifactId>
          <version>${project.version}</version>
      </dependency>
      <dependency>
          <groupId>org.dromara</groupId>
          <artifactId>soul-spring-boot-starter-plugin-httpclient</artifactId>
          <version>${project.version}</version>
      </dependency>
      <!--if you use http proxy end this-->
      
    插件讲解
    • divide插件是进行http正向代理的插件,所有http类型的请求,都是由该插件进行负载均衡的调用。

    • 选择器和规则,请详细看 : 选择器与规则介绍

    • http配置,是网关匹配到流量以后,真实调用的http配置,可以配置多个,设置负载均衡权重,具体的负载均衡策略,在规则中指定。

      • 配置详解 :

        • 第一个框:hostName,一般填写 localhost,该字段暂时没使用。
        • 第二个框:http协议,一般填写 http:// 或者 https:// ,不填写默认为:http://
        • 第三个框:ip与端口,这里填写你真实服务的 ip + 端口。
        • 第四个框:负载均衡权重。

        在这里插入图片描述

      • ip + port 检测

        • 在soul-admin 会有一个定时任务来扫描 配置的ip端口,如果发现下线,则会除该 ip + port
        • 可以进行如下配置 :
          soul.upstream.check:true  默认为 ture,设置为false,不检测
          soul.upstream.scheduledTime:10  定时检测时间间隔,默认10秒
    
    选择器与规则介绍
    • 一个插件有多个选择器,一个选择器对应多种规则。选择器相当于是对流量的第一次筛选,规则就是最终的筛选。
    • 我们想象一下,在一个插件里面,我们是不是希望根据我们的配置,达到满足条件的流量,我们插件才去执行它?
    • 选择器和规则就是为了让流量在满足特定的条件下,才去执行我们想要的,这个你首先头脑要点数。
    选择器详解

    在这里插入图片描述

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

    上述图片中表示:当请求的uri前缀是 /http,会转发到 192.168.137.1:8189 这个服务。

    选择器建议 : 可以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 的方式,转发到 192.168.137.1:8189

规则建议: 可以uri 条件, match 最真实的uri路径,进行流量的最终筛选 。

  1. 配置完成后进行http请求映射,访问网关divide选择器对应的规则列表URI,如:http://localhost:9195/http/test/findByUserId?userId=3,则soul会自动代理到http://localhost:8189/test/findByUserId?userId=3

源码跟踪

根据代理时日志打印:SoulBootstrapApplication打印出的线程类跟踪AbstractSoulPlugin,WebClientPlugin两个类:

2021-01-16 03:51:20.890 INFO 19912 — [-work-threads-3] o.d.soul.plugin.base.AbstractSoulPlugin : divide selector success match , selector name :/http
2021-01-16 03:51:20.893 INFO 19912 — [-work-threads-3] o.d.soul.plugin.base.AbstractSoulPlugin : divide selector success match , selector name :/http/test/**
2021-01-16 03:51:20.895 INFO 19912 — [-work-threads-3] o.d.s.plugin.httpclient.WebClientPlugin : you request,The resulting urlPath is :http://192.168.137.1:8189/test/findByUserId?userId=3, retryTimes: 0

AbstractSoulPlugin:

在execute方法中进行每个插件的链式执行,分别匹配判断其选择器及规则匹配。

AbstractSoulPlugin.execute执行divid插件doExecute方法,返回chain.execute(exchange);之后进行响应式编程的plugin.execut,执行WebClientPlugin的execute方法进行转发实时URI。

读源码感觉只懂了不到10%,白天再参考下同学大牛的总结,今天太晚了就到这里。

另外,选择器规则注册后为持久化数据,若需取消则需要手动配置取消规则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值