Apache ShenYu 官方examples体验

说明

shenyu 官方examples 在 shenyu-examples/项目路径下路径下。

shenyu 官方examples体验之http

项目中引入shenyu网关

引入shenyu相关依赖

  <dependency>
      <groupId>org.apache.shenyu</groupId>
      <artifactId>shenyu-spring-boot-starter-client-springmvc</artifactId>
      <version>2.2.1</version>
  </dependency>

配置说明
shenyu的配置在resources/application.yml中:

shenyu:
  http:
    adminUrl: http://localhost:9095  #shenyu 网关 admin管理地址
    port: 8188 #http服务端口地址
    contextPath: /http   #注册到shenyu网关到选择选择器的名称
    appName: http
    full: false

项目中关于shenyu网关的配置注入
shenyu网关是接口颗粒度的,可以针对配置的每个接口定义不同的策略,也可以根据uri前缀分组、正则模糊匹配来配置不同的策略。我们可以直接在我们项目中引用上述依赖,通过注解的方式配置,也可以在shenyu-admin管理前端页面输入相关配置。
下述为注解方式方式注入(其中@ShenyuSpringMvcClient配置的就是shenyu路由的具体uri):

@RestController
@RequestMapping("/order")
@ShenyuSpringMvcClient(path = "/order")
public class OrderController {

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

}
功能体验

当启动两个相同shenyu 路由的目标uri一致时,自动就配上了负载均衡,默认是随机加权重的算法,可以通过shenyu-admin 页面具体配置:

当我们配置50 比 50的权重时,两个地址基本平均路由到8188和8189服务上:

在路由配置上,我们可以加各种匹配配置各种条件。当条件满足时才路由,否则不路由。条件匹配方式有 and 和 or。

加header时,如果请求没有加相关header,直接抛-107。

curl http://localhost:9195/http/test/findByUserId\?userId\=10

{"code":-107,"message":"Can not find selector, please check your configuration!","data":null}

当我们将相关请求头加上后,就匹配上了。

curl -H "test:222" http://localhost:9195/http/test/findByUserId\?userId\=10

{"userId":"10","userName":"hello world"}

我们在shenyu-admin前端页面对选择器的配置最终会在我们配置的shenyu数据库中持久化下来,当网关重启后,会从数据库中拉取相关配置。协议、上游地址、权重等等信息都存放在 selector@shenyu 表中:

选择器条件的相关配置存放在 selector_condition@soul 表中:

压测

shenyu

# 12线程,400并发 ,持续30秒压力测试
wrk -t12 -c400 -d30s http://localhost:9195/http/test/findByUserId?userId=10

 Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    36.97ms   33.44ms 515.83ms   91.90%
    Req/Sec   580.67    278.31     1.39k    65.68%
  206406 requests in 30.09s, 21.85MB read
  Socket errors: connect 158, read 255, write 0, timeout 0
Requests/sec:   6858.69
Transfer/sec:    743.48KB

sprng cloud gateway

# 12线程,400并发 ,持续30秒压力测试
wrk -t12 -c400 -d30s http://localhost:8080/test/findByUserId\?userId\=10

Running 30s test @ http://localhost:8080/test/findByUserId?userId=10
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    28.36ms   56.35ms 924.63ms   98.10%
    Req/Sec     0.87k   405.22     1.95k    64.67%
  303360 requests in 30.08s, 32.11MB read
  Socket errors: connect 158, read 223, write 0, timeout 0
Requests/sec:  10086.51
Transfer/sec:      1.07MB

shenyu 官方examples体验之dubbo

说明
  • shenyu 支持dubbo的路由,我们可以以http协议访问dubbo的接口。文中将将探讨它的实现
  • 官方示例在 shenyu-exmples/shenyu-examples-dubbo目录下
  • shenyu 支持alibaba dubbo(< 2.7.x) 以及 apache dubbo (>=2.7.x)。
  • 接入前确保启动了shenyu-admin相关服务已启动
配置

shenyu-bootstrap中dubbo依赖配置


        <!--shenyu alibaba dubbo plugin start-->
        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-plugin-alibaba-dubbo</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>${alibaba.dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>${curator.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>${curator.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>${curator.version}</version>
        </dependency>
        <!-- shenyu  alibaba dubbo plugin end-->

dubbo项目中shenyu相关依赖

<dependency>
    <groupId>org.apache.shenyu</groupId>
    <artifactId>shenyu-spring-boot-starter-client-alibaba-dubbo</artifactId>
    <version>${shenyu.version}</version>
</dependency>

dubbo项目中shenyu相关的注入

@Service("dubboTestService")
public class DubboTestServiceImpl implements DubboTestService {

    @Override
    @ShenyuDubboClient(path = "/findById", desc = "Query by Id")
    public DubboTest findById(final String id) {
        DubboTest dubboTest = new DubboTest();
        dubboTest.setId(id);
        dubboTest.setName("hello world Shenyu Alibaba Dubbo, findById");
        return dubboTest;
    }
}

dubbo项目中shenyu网关的相关配置

shenyu:
  dubbo:
    adminUrl: http://localhost:9095 # shenyu-admin 服务的地址
    contextPath: /dubbo #网关请求该服务的上下文路径
    appName: dubbo
功能体验

在配置好上诉相关配置后,启动dubbo服务。我们通过上面shenyu注解方式将路由规则注册到shenyu网关上。

在启动shenyu-bootstrap服务时,发现报以下异常:

java.lang.IllegalStateException: No such application config! Please add <dubbo:application name="..." /> to your spring config.

且通过网关访问我们dubbo服务接口时,网关返回:

{
    "code": -103,
    "message": "Service invocation exception, or no result is returned!",
    "data": null
}

最后排查发现,shenyu网关支持的服务是插件化的,要路由dubbo服务,需要在admin插件管理里去开启dubbo插件。然后就能路由到了。
若是我们业务服务不涉及dubbo服务,那么我们可以在 shenyu-bootstrap服务的pom依赖中去掉dubbo相关依赖。

当在 shenyu-admin中开启dubbo插件后,get 请求http://localhost:9195/dubbo/findById?id=10,返回

{
    "code": 200,
    "message": "Access to success!",
    "data": {
        "name": "hello world Shenyu Alibaba Dubbo, findById",
        "id": "10"
    }
}
探究shenyu是如何从http访问到dubbo服务

shenyu支持的服务都是插件化的,所有的插件都继承自 AbstractShenyuPlugin。我们要探究哪个插件是如何实现的,就可以在相应的插件源码上打上断点一步步跟踪。
我们在shenyu-plugin/shenyu-pulgin-alibaba-dubbo服务的 AlibabaDubboPlug类的 doExecute 方法上打上断点,访问通过网关路由的dubbo服务。

我们所有的插件继承自 AbstractShenyuPlugin,现在来简单分析路由过程。下图为主要类调用的时序图:

shenyu 官方examples 体验之 springCloud

说明
  • 确保shenyu-bootstrap依赖配置、注册中心配置已配好(下文会详细说明)
  • 客户端注解接入,确保shenyu网关依赖已添加
  • 确保 shenyu-admin、shenyu-bootstrap、注册中心服务已正确启动
  • 确保在 shenyu-admin前台开启了对springCloud插件的支持
shenyu-bootstap配置说明

pom相关依赖

 <!--shenyu springCloud plugin start-->
 <dependency>
     <groupId>org.apache.shenyu</groupId>
     <artifactId>shenyu-spring-boot-starter-plugin-springcloud</artifactId>
     <version>${project.version}</version>
 </dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-commons</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
<!--shenyu springCloud plugin start end-->

shenyu-bootstrap 注册中心配置

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

shenyu-bootstrap关于 shenyu-admin 同步的配置

shenyu :
    file:
      enabled: true
    corss:
      enabled: true
    dubbo :
      parameter: multi
    sync:
        websocket :
             urls: ws://localhost:9095/websocket
springCloud项目配置说明

下面仅对springCloud服务接入shenyu网关做相关配置说明,springcloud服务本身配置不在此说明。

在项目中的yml配置文件中加入shenyu相关配置

shenyu:
  springcloud:
    admin-url: http://localhost:9095 
    context-path: /springcloud
#    full: true

在springCloud服务中的pom文件中添加shenyu相关依赖

 <dependency>
     <groupId>org.apache.shenyu</groupId>
     <artifactId>shenyu-spring-boot-starter-client-springcloud</artifactId>
     <version>${shenyu.version}</version>
</dependency>
体验流程

在完成上述配置后,通过以下步骤接入shenyu网关并体验

  1. 先后启动euraka注册中心、shenyu-amdin、shenyu-bootstrap、springCloudDemo 服务。

  2. 在shenyu-admin后端开启 springCloud插件。

  3. 通过shenyu网关访问springCloudDemo服务。
    http://localhost:9195/springcloud/order/findById?id=11

压测

shenyu

# 12线程,400并发 ,持续30秒压力测试
wrk -t12 -c400 -d30s http://localhost:9195/springcloud/order/findById?id=11

Running 30s test @ http://localhost:9195/springcloud/order/findById?id=11
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    32.69ms   23.68ms 286.36ms   80.79%
    Req/Sec   626.02    247.69     1.32k    62.06%
  223656 requests in 30.10s, 44.62MB read
  Socket errors: connect 158, read 100, write 0, timeout 0
Requests/sec:   7430.36
Transfer/sec:      1.48MB

spring cloud gateway

# 12线程,400并发 ,持续30秒压力测试
wrk -t12 -c400 -d30s http://localhost:8080/order/findById?id=11

Running 30s test @ http://localhost:8080/order/findById?id=11
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    26.99ms   16.05ms 478.84ms   78.68%
    Req/Sec   746.38    289.03     1.57k    63.00%
  267672 requests in 30.06s, 46.21MB read
  Socket errors: connect 158, read 145, write 0, timeout 0
Requests/sec:   8905.69
Transfer/sec:      1.54MB

shenyu 官方 examples 体验之 sofa

说明
  • 本文仅介绍蚂蚁金服开源的sofarpc服务接入shenyu网关,不会涉及sofa本身的配置、搭建。要了解sofa详情,可去sofarpc官方查看。
  • 启动前确保shenyu-admin、shenyu-bootstrap、zookeeper等正确配置启动。
  • 确保通过shenyu-admin打开了sofa插件开关
shenyu网关开启sofa插件相关配置

依赖配置(将下面sofa-rpc-all版本改为自己项目中实际版本)

<!-- shenyu sofa plugin start-->
<dependency>
    <groupId>com.alipay.sofa</groupId>
    <artifactId>sofa-rpc-all</artifactId>
    <version>5.7.6</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.shenyu</groupId>
    <artifactId>shenyu-spring-boot-starter-plugin-sofa</artifactId>
    <version>${project.version}</version>
</dependency>
<!-- shenyu sofa plugin end-->

在shenyu-admin中开启sofa插件的支持

spring boot sofa服务接入shenyu 网关相关配置

在项目中添加shenyu网关客户端依赖

 <dependency>
    <groupId>org.apache.shenyu</groupId>
    <artifactId>shenyu-spring-boot-starter-client-sofa</artifactId>
    <version>${shenyu.version}</version>
    <exclusions>
        <exclusion>
            <artifactId>guava</artifactId>
            <groupId>com.google.guava</groupId>
        </exclusion>
    </exclusions>
</dependency>

shenyu网关相关配置

shenyu:
  sofa:
    adminUrl: http://localhost:9095
    contextPath: /sofa
    appName: sofa

通过注解向网关注册路由的接口(也可通过sou-admin管理页面添加)

@Service("sofaTestService")
public class SofaTestServiceImpl implements DubboTestService {

    @Override
    @ShenyuSofaClient(path = "/findById", desc = "Find by Id")
    public DubboTest findById(final String id) {
        DubboTest dubboTest = new DubboTest();
        dubboTest.setId(id);
        dubboTest.setName("hello world Shenyu Sofa, findById");
        return dubboTest;
    }
}
  • @ShenyuSofaClient:加上该注解就会向shenyu网关注册该接口路径。

通过上述配置我们sofa服务就接入shenyu网关了,然后我们就可以通过shenyu网关路由的地址去访问被代理的接口了,若是请求不成功请检查:

  • shenyu网关是否正确启动,日志是否有报错
  • sofa若是用的zookeeper 作为注册中心,确认zookeeper是否运行正常
  • 是否通过shenyu-admin开启了sofa插件
压测

12线程,400并发 ,持续30秒压力测试

wrk -t12 -c400 -d30s http://localhost:9195/sofa/findById?id=11

Running 30s test @ http://localhost:9195/sofa/findById?id=11
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   141.37ms   45.57ms 462.89ms   66.38%
    Req/Sec   140.89     75.41   414.00     62.13%
  50469 requests in 30.09s, 8.42MB read
  Socket errors: connect 158, read 223, write 0, timeout 0
Requests/sec:   1677.05
Transfer/sec:    286.61KB

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注