• Apache ShenYu 学习笔记一


    1、简介

    这是一个异步的,高性能的,跨语言的,响应式的 API 网关。

    2、首次体验

    本次体验基本参照官方快速开始文档步骤

    2.1、本地环境

    • 开发工具:IDEA
    • JDK:1.8

    2.2、下载代码

    git clone https://github.com/apache/shenyu.git
    cd shenyu
    mvn clean install -Dmaven.javadoc.skip=true -B -Drat.skip=true -Djacoco.skip=true -DskipITs -DskipTests
    

    2.3、启动shenyu-admin

    • IDEA打开上一步下载好的项目
    • 找到shenyu-admin子项目,运行ShenyuAdminBootstrap
    • 该项目默认使用H2数据库,首次启动会自行初始化。默认web端口为:9095,默认账号密码为:admin/123456
    • 浏览器访问:http://localhost:9095 并登陆,可以看到如下界面:

    2.4、启动shenyu-bootstrap

    • 找到shenyu-bootstrap子项目,修改application.ymlshenyu.local.enabled的值为true,方便本地调试。
    • 运行ShenyuBootstrapApplication
    • 该项目默认端口为:9195,后面设置路由规则需要用到

    2.5、测试准备

    • 由于首次体验我们需要测试http接口转发,因此本地启动用于测试的web项目,提供一个待测试的接口:http://localhost:8081/test/hello 如下图:

    2.6、添加路由规则

    待测试的接口准备好了,接下来我们需要在ShenYu中添加路由规则,我直接通过终端发送请求如下:

    curl --location --request POST 'http://localhost:9195/shenyu/plugin/selectorAndRules' \
    --header 'Content-Type: application/json' \
    --header 'localKey: 123456' \
    --data-raw '{
        "pluginName": "divide",
        "selectorHandler": "[{\"upstreamUrl\":\"127.0.0.1:8081\"}]",
        "conditionDataList": [{
            "paramType": "uri",
            "operator": "match",
            "paramValue": "/**"
        }],
        "ruleDataList": [{
            "ruleHandler": "{\"loadBalance\":\"random\"}",
            "conditionDataList": [{
                "paramType": "uri",
                "operator": "match",
                "paramValue": "/**"
            }]
        }]
    }'
    

    2.7、测试转发

    根据上面的映射规则,我们直接访问: http://localhost:9195/test/hello ,结果如下:

    至此,首次体验已经完成。接下来,我想继续了解下本项目。

    3、转发实现流程探究

    以下的探究基于上面2.x体验流程

    3.1、单一职责插件

    通过官方文档:https://shenyu.apache.org/zh/docs/developer/custom-plugin ,可以看到如下内容:

    结合2.6添加路由规则中涉及的plugin:divide,于是本次探究我们围绕divide插件展开

    3.2、divide插件

    • shenyu项目下,可以看到一个子模块shenyu-plugin,点开后可以看到该模块下已经提供了众多插件实现

    • 点开shenyu-plugin-divdie,可以看到DividePlugin类,该类继承自org.apache.shenyu.plugin.base.AbstractShenyuPlugin,与官方文档描述如出一辙

    • org.apache.shenyu.plugin.base.AbstractShenyuPlugin.execute方法中打断点调试如下:

    • 此处正好印证官方文档关于插件的描述,具体的转发逻辑由插件各自实现,我们可以通过自定义插件的方式进行扩展

    • 那么一个请求过来?网关是如何找到具体插件的呢?

    3.3、ShenyuWebHandler

    • 断点通过方法调用栈发现,该请求从上游方法org.apache.shenyu.web.handler.ShenyuWebHandler.handle过来:

    • ShenyuWebHandler类实现了org.springframework.web.server.WebHandler接口。

    • 可以看到,该handler方法拿到了plugins,并通过Reactor异步地将exchange发布出去

    • 然后通过责任链机制,按照插件定义的顺序依次匹配。未匹配上则忽略,匹配上则由对应的插件处理,正好与3.2步骤中的divide插件衔接上。匹配逻辑如下:

    • 由于这是首次体验,我不想过多的探究细节,因此插件匹配、执行的细节此处暂且跳过,我们继续往下探究plugins从何而来?

    3.4、shenyu-spring-boot-starter-gateway

    • 继续追溯,发现ShenyuWebHandler实例的生产地位于shenyu-spring-boot-starter-gateway中的ShenyuConfiguration

    • 通过该方法发现,插件列表信息从方法参数ObjectProvider> plugins获取,因此我们只要找到插件Bean实例生成的位置即可

    3.5、shenyu-spring-boot-starter-plugin-divide

    • 于是很轻易的发现,在shenyu-spring-boot-starter-plugin-divide子项目下,有一个类:DividePluginConfiguration,包含如下代码:

    • 因此,本次探究过程至此结束

    4、本次学习总结

    • 项目主要模块
      • shenyu-admin:后台配置、监控
      • shenyu-bootstrap:服务端配置、启动入口
      • shenyu-plugin:服务端插件合集
      • shenyu-web: 服务端web层上游基础功能封装
      • shenyu-spring-boot-starter:将其他功能模块与springboot进行整合
    • 插件开发大致流程
      • shenyu-plugin下新建插件子模块,编写插件入口类(实现ShenyuPlugin接口,或继承AbstractShenyuPlugin类)
      • 定义好插件名称、优先级(Order)、skip逻辑、插件处理逻辑(execute)
      • shenyu-spring-boot-starter-plugin编写自定义插件对应的starter
    • 转发大致流程
      • 项目启动后,从bean容器加载插件列表
      • 请求过来后,首先到达org.apache.shenyu.web.handler.ShenyuWebHandler.handle,通过Reactor异步地将exchange发布出去
      • 然后通过责任链机制,按照插件定义的顺序依次匹配。未匹配上则忽略,匹配上则由对应的插件处理
      • 最后由具体的插件(如:divide插件,将http请求转发到目标地址)处理

    5、联系我吧

    我是一个热爱开源的小菜鸡,如果本文吸引到了你,欢迎通过下面的方式与我取得联系

  • 相关阅读:
    python 获取apk信息
    根据二叉树创建字符串
    第十九次CCF计算机软件能力认证
    php中RESTful API使用
    靶机: medium_socnet
    快来跟我一起抢先看看未来世界的出行,体验未来城市吧~
    阿里巴巴面试题- - -Java体系最新面试题(4)
    ANR系列之ContentProvider类型原理讲解
    Jenkins数据迁移、备份与恢复-旧设备到新设备(简单教程)
    在学习DNS的过程中给我的启发
  • 原文地址:https://www.cnblogs.com/aoshiguchen/p/17363492.html