SpringCloud Gateway整合sentinel+nacos实现sentinel动态持久化配置
解决:如何通过在网关配置sentinel,可以针对不同的服务实现不同的限流规则(粗粒度),同时针对服务中的个别接口单独做限流处理。最后把配置sentinel配置信息放到nacos,实现持久化的动态配置。
1、添加依赖。修改pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
2、修改application.yml
server:
port: 4000
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
# - id: order-route
# uri: lb://cloud-consumer-order
# predicates:
# - Path=/api/order/**
# - After=2021-02-28T18:22:13.426+08:00[Asia/Shanghai] #该时间后网关才会对该order请求进行转发
- id: user-route
uri: lb://cloud-provider-user
predicates:
- Path=/api/user/**
nacos:
discovery:
server-addr: localhost:8848
config:
server-addr: localhost:8848
sentinel:
transport:
port: 8719
dashboard: localhost:8080
datasource:
# dsl.file: #通过本地文件方式。基于服务级别的配置
# file: classpath:gw-flow.json
# ruleType: gw-flow
# ds2.file: #通过本地文件方式。细粒度对指定api进行配置
# file: classpath:gw-api-group.json
# ruleType: gw-api-group
ds1:
nacos: #通过nacos实现动态配置
server-addr: localhost:8848
data-id: gw-flow
group-id: JXF_GROUP
data-type: json
rule-type: gw-flow #gw-flow网关流控规则。用于定义服务或者自定义api组 的具体流控规则
ds2:
nacos:
server-addr: localhost:8848
data-id: gw-api-group
group-id: JXF_GROUP
data-type: json
rule-type: gw-api-group #对上面服务中个别接口做单独指定流控规则,那么就可以使用自定义api组。先声明 一个一个的资源,每个资源可以匹配多个接口,每个资源对应一个appName,appName就是资源。注:gw-api-group只是声明一个个的资源,不参与指定具体的网关流控规则。网关流控规则是由rule-type: gw-flow 来指定。
management:
endpoints:
web:
exposure:
include: "*"
3.1、本地文件配置sentinel方式(可选,不推荐)。(不够灵活,上面被注释掉的dsl.file方式)
注1:参数看不懂没关系,这里知道啥意思就行了,继续往下看。后面教你怎么弄。
注2:下面的json文件为了让大家看得懂,我添加了#符号来代表注释。而josn文件是不允许你添加注释的,如果你拷贝了json文件中的内容,记得把#以及后面的注释给去掉。
gw-api-group.json(自定义网关api组的方式)
这里只定义资源,不做具体的网关限流配置
[
{
"apiName": "myCustomApiFlow", #资源名称
"predicateItems": [
{
"pattern": "/api/user/gw/group/exactMacth" #默认是精确匹配方式
},
{
"pattern": "/api/user/gw/group/fuzzy/**",
"matchStrategy": 1 #模糊匹配方式
}
]
}
]
gw-flow.json
这里做网关限流配置。配置的目标对象可以是某个服务(粗粒度),也可以是我们上边编写的自定义网关api组(资源)。
[
{
"resource": "user-route", #这里有两种选择。第一种是基于整个服务来处理,用application.yml中定义的route-id名称来表示。第二种是针对 自定义网关组,用appName的值来代表。
"resourceMode": 0, #0是网关限流模式 ,1是自定义网关api组的方式
"count": 5, #只能执行5次
"intervalSec": 10 #周期是10s。结合上面就是每10s只能执行5次
},
{
"resource": "myCustomApiFlow", #和上面文件中apiName的名字要对应上
"resourceMode": 1, #1是自定义网关api组的方式
"count": 1, #只能执行1次
"intervalSec": 10 #即10s内只能只能执行1次。
}
]
所以结合上面的意思就是:
localhost:4000/api/user开头的请求 所在的服务 10s内只能处理5个请求。
但是个别请求比较特殊,localhost:4000/api/user/gw/group/exactMacth 和 /api/user/gw/group/fuzzy开头的请求10s内最多只能处理请求1次。
注意:上面的10s只能处理5个请求,是对于服务来说。不是每个接口10s只能处理5个请求。
例1、10s内,localhost:4000/api/user/1执行了3次,那么localhost:4000/api/user/2就只能执行2次,执行第三次的时候就会出现限流了,因为3+3=6>5了
例2、10s内访问localhost:4000/api/user/gw/group/fuzzy 1次,再次访问的时候就会出现限流,此时再去执行localhost:4000/api/user/1,那么最多只能执行5-1=4次。5是指服务10s只能执行5次,1是指 已经被/api/user/gw/group/fuzzy执行掉的一次。所以该服务最多只能处理4个请求
3.2 nocos动态配置sentinel方式(灵活,推荐)
在naocs管理界面新增两个文件
内容分别为:
4、初步测试
先测试user-route
效果:
测试 api组限流 myCustomApiFlow
(10s内最多只能执行1次)
效果:
精确匹配测试
模糊匹配测试
这样就结束了???不不不,还记得我们最开始说的吗,通过sentinel-dashboard界面进行配置。所以你也就不用在担心 例如上面json文件中的resource、resourceMode、count等字段信息是什么,不会怎么办的问题,我们继续往下看。
5、结合Sentinal-dashboard界面来配置限流规则
在网关配置接口,可以方便我们查看gateway配置的sentinel信息
package com.jxf.controller;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SentinelController {
/**
* route 维度。这样就可以看到我们的配置信息
* @return
*/
@GetMapping("/gw-flow")
public Object GetGatewayFlowConfig(){
return GatewayRuleManager.getRules();
}
/**
* 用户自定义的 API 定义分组。这样就可以看到我们的配置信息
* @return
*/
@GetMapping("/gw-api-group")
public Object GetGatewayApiGroupConfig(){
return GatewayApiDefinitionManager.getApiDefinitions();
}
}
访问网关限流接口,查看配置信息
访问 自定义api组 接口,查看配置信息
启动你的sentinal-dashboard,通过http://localhost:8080/打开你的sentinal-bashboard界面,然后随便访问一下http://localhost:4000/gw-flow。因为你需要初次访问后,sentinel-dashboard才会显示该服务的配置信息。
可以看到界面已经加载我们的gateway服务了
点开查看,具体配置也是一一对应的
重点来了:
我修改和新增一些配置数据
测试效果:
然后点击保存,这样就大功告成。
此时我们把网关服务重启一下。看gateway-dashboard能不能正确读取到naocs中定义的 网关限流 配置信息
还记得我上面说的吗,需要初次访问该访问的接口后,sentinel-bashboard才会加载该服务的配置信息
我们随便访问一下:http://localhost:4000/gw-flow
然后再刷新sentinel-dashboard界面
当然,效果也是没有问题的。访问http://localhost:4000/api/user/gw/group/fuzzy,会发现第一二次,可以正常访问,10s内的第三次,就出现限流提示了!!这里就不在演示了。
同理,我们也可以新增或修改 api组信息,步骤和上面的差不多,这里再演示一下,就当再次巩固一下。
说明一切OK
最后只需拷贝 网关api组信息,粘贴到nacos中就行了
最后点击保存即可。