说明
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
- admin-url: shenyu-admin服务地址
- context-path:路由的全局前缀。原接口访问路径:http://localhost:8080/order/findById,通过shenyu网关访问地址为:http://localhost:8080/springcloud/order/findById
- full: true,路由所有接口;false,只路由通过shenyu-admin配置的接口或项目controller中加了 @ShenyuSpringCloudClient 注解的接口。
在springCloud服务中的pom文件中添加shenyu相关依赖
<dependency>
<groupId>org.apache.shenyu</groupId>
<artifactId>shenyu-spring-boot-starter-client-springcloud</artifactId>
<version>${shenyu.version}</version>
</dependency>
体验流程
在完成上述配置后,通过以下步骤接入shenyu网关并体验
-
先后启动euraka注册中心、shenyu-amdin、shenyu-bootstrap、springCloudDemo 服务。
-
在shenyu-admin后端开启 springCloud插件。
-
通过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
- adminUrl: shenyu-admin 服务地址。
- contextPath: 网关统一前缀。原访问地址 http://localhost:28011/findById, 接入shenyu网关通过网关访问地址:http://localhost:9195/sofa/findById。
- appName: 接入客户端名称
通过注解向网关注册路由的接口(也可通过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