Sentinel也可以在网关层对接口进行限流,在规定时间窗口期内允许通过几个请求(QPS)。官网文档:
api-gateway-flow-control | Sentinel
一、从Sentinel官网下载最新的版本控制台jar包
https://github.com/alibaba/Sentinel/releaseshttps://github.com/alibaba/Sentinel/releases
这里下载的是Sentinel-1.8.6.jar,放在指定位置后,直接执行启动。
nohup java -Dserver.port=18181 -Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=119.**.***.241:18181 -Dproject.name=my-sentinel-dashboard -Dsentinel.dashboard.auth.username=Sentinel -Dsentinel.dashboard.auth.password=666666 -Dserver.servlet.session.timeout=7200 -jar sentinel-dashboard-1.8.6.jar &
-Dcsp.sentinel.app.type=1 表示网关启动,控制台页面菜单会显示为网关限流的菜单(请求链路、API管理)。当然这个启动命令启动的只是Sentinel本身的应用,跟我们关系不大,我们要使用Zuul达到这么个效果。
执行命令启动成功之后,当前文件夹会有Sentinel日志文件: nohup.out。
访问你的控制台地址,输入启动命令上的账号密码登入,则会看到如下页面:
二、 Zuul1.x\2.x继承Sentinel,并Nacos持久化流控配置
1. Zuul项目的pom.xml文件添加如下依赖
<!-- zuul网关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!-- nacos的服务发现与nacos获取配置 -->
<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>
<!-- sentinel核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- sentinel配置持久化到nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<!-- zuul网关与sentinel继承到核心依赖,版本号与sentinel jar的版本号保持一致 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-zuul-adapter</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
2. 在Zuul项目的Application启动类的main方法上增加这行代码,标记这个项目需要为网关流控。
System.setProperty("csp.sentinel.app.type", "1");
3. 配置Sentinel在Zuul里面的过滤器,自定义限流返回信息
3.1 ZuulConfig.java
package com.***.framework.gateway.sentinel;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulErrorFilter;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPostFilter;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPreFilter;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackManager;
import com.netflix.zuul.ZuulFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* ZuulConfig
*
* @Author lxwang
* @Date 11/23/22 10:59 AM
* @Location shenzhen.china
*/
@Configuration
public class ZuulConfig {
/**
*将三个Sentinel实现的ZuulFilter 注入到 Spring 环境中
**/
@Bean
public ZuulFilter sentinelZuulPreFilter() {
// We can also provider the filter order in the constructor.
return new SentinelZuulPreFilter();
}
@Bean
public ZuulFilter sentinelZuulPostFilter() {
return new SentinelZuulPostFilter();
}
@Bean
public ZuulFilter sentinelZuulErrorFilter() {
return new SentinelZuulErrorFilter();
}
//初始化自定义限流异常返回信息
@PostConstruct
public void doInit() {
// 注册 FallbackProvider
ZuulBlockFallbackManager.registerProvider(new MyBlockFallbackProvider());
}
}
3.2 MyBlockFallbackProvider.java
package com.***.framework.gateway.sentinel;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.BlockResponse;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackProvider;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Component;
/**
* MyBlockFallbackProvider
*
* @Author lxwang
* @Date 11/23/22 11:00 AM
* @Location shenzhen.china
*/
@Component
public class MyBlockFallbackProvider implements ZuulBlockFallbackProvider {
@Override
public String getRoute() {
return "*";
}
@Override
public BlockResponse fallbackResponse(String route, Throwable cause) {
RecordLog.info(String.format("[Sentinel DefaultBlockFallbackProvider] Run fallback route: %s", route));
if (cause instanceof BlockException) {
return new BlockResponse(429, "当前人员访问过多,请稍等一下", route);
} else {
return new BlockResponse(500, "System Error", route);
}
}
}
4. Zuul项目的配置文件加上Sentinel的相关配置
4.1 网关配置文件增加sentinel的配置
spring:
cloud:
sentinel:
filter:
enabled: true
eager: true
datasource:
ds1: #网关流控规则
nacos:
username: nacos
password: ****
server-addr: 120.**.**.37:8848
rule-type: gw-flow
namespace: af5313f9-0c6a-4262-ad72-68a4e191b94d
data-id: gateway-sentinel.json
data-type: json
ds2: #网关api分组
nacos:
username: nacos
password: ****
server-addr: 120.**.**.37:8848
namespace: af5313f9-0c6a-4262-ad72-68a4e191b94d
data-id: gateway-sentinel-api-group.json
data-type: json
rule-type: gw-api-group
transport:
port: 8719
dashboard: 119.**.***.241:18181
feign:
sentinel:
enabled: true
4.2 网关api分支的规则:gateway-sentinel-api-group.json。更多配置项可查询官网文档
[
{
"apiName":"login_security",
"predicateItems":[
{
"matchStrategy":0,
"pattern":"/vtownappdoor/v1/login/security"
}
]
},
{
"apiName":"send_verification_code",
"predicateItems":[
{
"matchStrategy":0,
"pattern":"/vtownappdoor/v1/login/send/verification/code"
}
]
},
{
"apiName":"login_app_login",
"predicateItems":[
{
"matchStrategy":0,
"pattern":"/vtownappdoor/v1/login/app/login"
}
]
}
]
4.3 流控规则配置:gateway-sentinel.json。更多配置项可查询官网文档
[
{
"burst":0,
"controlBehavior":0,
"count":10,
"grade":1,
"intervalSec":1,
"resource":"login_security", # 与api_group的api_name要一一对应
"resourceMode":1
},
{
"burst":0,
"controlBehavior":0,
"count":10,
"grade":1,
"intervalSec":1,
"resource":"send_verification_code",
"resourceMode":1
},
{
"burst":0,
"controlBehavior":0,
"count":10,
"grade":1,
"intervalSec":1,
"resource":"login_app_login",
"resourceMode":1
}
]
5. 配置完启动Zuul网关
三、完成的页面是这个样子
四、亲测有效,Jmeter压测结果符合预期。测试结果就不在这里贴图了