spring cloud gateway整合sentinel + nacos 实现网关限流和持久化动态配置
Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId自定义 API 维度:用户可以利用 Sentine
Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:
route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组
Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑:
GatewayFlowRule :网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同
route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的
限流。
ApiDefinition :用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以
定义一个 API 叫 customized_api ,请求 path 模式为 /api/v8/**, /api/v5/ 的匹配路径都归到 customized_api 这个 API
分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。
这篇文章主要介绍了spring cloud gateway整合sentinel实现网关限流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下,Spring Cloud Gateway工程的搭建和Nacos的搭建不在这里讲述。
说明: sentinel可以作为各微服务的限流(点击查看),也可以作为gateway网关的限流组件。 spring cloud gateway有限流功能,但此处用sentinel来作为替待。
说明:sentinel流控可以放在gateway网关端,也可以放在各微服务端。
1、sentinel_dashboard的引入
下载sentinel-dashboard-1.6.3.jar
由于dashboard是springboot的项目,在CMD模式下使用命令
java -Dserver.port=8090 -Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar F:\workspace\sentinel\sentinel-dashboard-1.6.3.jar
-Dcsp.sentinel.app.type=1 表示 Sentinel 网关类型
浏览器访问地址:http://localhost:8090/#/login
登录后看到菜单有 “API管理“ 表示成功启动了Sentinel网关类型的控制台
2、Spring cloud gateway服务引入Nacos,Sentinel 依赖包(注意版本)
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.0</version>
</dependency>
Spring cloud gateway服务添加Nacos 相关配置
spring:
application:
# 应用名称
name: gateway-master
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
httpclient:
pool:
max-idle-time: 10000
discovery:
locator:
enabled: true
Spring cloud gateway服务增加Sentinel配置类
@Configuration
public class GatewaySentinelConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewaySentinelConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
/**
* 配置SentinelGatewayBlockExceptionHandler,限流后异常处理
*
* @return
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
// 自定义限流异常页面
@PostConstruct
public void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map result = new HashMap();
result.put("Suc","false");
result.put("ErrCode",0);
result.put("Info","接口被限流了");
return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(result));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
/**
* 配置SentinelGatewayFilter
*
* @return
*/
@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
}
3、进入nacos控制台-配置列表添加配置
dataId: sentinel-gateway-rules
groupId: sentinel
[
{
"resource": "api-v8-order1",
"resourceMode": 0,
"count": 1,
"intervalSec": 10
},
{
"resource": "customized_api",
"resourceMode": 1,
"pattern": "/api/v5/**",
"count": 1,
"intervalSec": 10
}
]
resource: 资源名称
resourceMode: 资源模式 0-路由ID模式 1-自定义API模式
count:限流阈值
intervalSec: 统计时间窗口,单位是秒,默认是 1 秒
pattern: 自定义API模式下的限流资源路径
Spring cloud gateway服务添加Nacos配置监听类,服务启动自动加载Nacos已有的限流配置
@Component
public class DynamicFlowRulesServiceImplByNacos implements CommandLineRunner {
protected static final Logger log = LoggerFactory.getLogger(DynamicFlowRulesServiceImplByNacos.class);
@Autowired
private NacosGatewayProperties nacosGatewayProperties;
private ConfigService configService;
/**
* 监听Nacos Server下发的动态配置
*/
public void dynamicByNacosListener() {
if (configService == null) {
try {
configService = NacosFactory.createConfigService(nacosGatewayProperties.getAddress());
} catch (NacosException e) {
e.printStackTrace();
}
}
sentinelConfigByNacosListener();
}
/**
* 网关动态配置基础信息
*/
public void sentinelConfigByNacosListener() {
try {
String dataId = "sentinel-gateway-rules";
String groupId = "sentinel";
String fristConfigInfo = configService.getConfigAndSignListener(dataId, groupId, 5000, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
addListenerByConfig(dataId, groupId, configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
addListenerByConfig(dataId, groupId, fristConfigInfo);
} catch (NacosException e) {
e.printStackTrace();
}
}
/**
*
*/
public void addListenerByConfig(String dataId, String groupId, String configInfo) {
log.info("DataId:" + dataId + ",GroupId:" + groupId + ",监听器获取的nacos-sentinel流控配置信息:" + configInfo);
//配置删除或不存在
if (configInfo == null) {
initDefultGatewaySentinelRules();
return;
}
List<GatewaySentinelConfig> gatewaySentinelConfigs = null;
try {
gatewaySentinelConfigs = new Gson().fromJson(configInfo, new TypeToken<List<GatewaySentinelConfig>>() {
}.getType());
} catch (JsonSyntaxException e) {
log.error("JsonSyntaxException", e, e.getMessage());
}
if (gatewaySentinelConfigs == null || gatewaySentinelConfigs.size() == 0) {
return;
}
//加载流控规则
initGatewaySentinelRules(gatewaySentinelConfigs);
}
public void initGatewaySentinelRules(List<GatewaySentinelConfig> gatewaySentinelConfigs) {
Set<GatewayFlowRule> rules = new HashSet<>();
Set<ApiDefinition> definitions = new HashSet<>();
for (GatewaySentinelConfig sentinelConfig : gatewaySentinelConfigs) {
rules.add(new GatewayFlowRule(sentinelConfig.resource)
.setResourceMode(sentinelConfig.resourceMode)
.setCount(sentinelConfig.count) // 限流阈值
.setIntervalSec(sentinelConfig.intervalSec) // 统计时间窗口,单位是秒,默认是 1 秒
);
if (sentinelConfig.resourceMode == 1) { //自定义API模式
ApiDefinition api1 = new ApiDefinition(sentinelConfig.resource).setPredicateItems(new HashSet<ApiPredicateItem>() {{
if (sentinelConfig.pattern.contains("**")) {
//前缀匹配
add(new ApiPathPredicateItem().setPattern(sentinelConfig.pattern).setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}
}});
definitions.add(api1);
}
}
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
GatewayRuleManager.loadRules(rules);
}
//配置删除,初始化一个默认规则
public void initDefultGatewaySentinelRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("no-rule")
.setResourceMode(0)
.setCount(10000000) // 限流阈值
.setIntervalSec(1)); // 统计时间窗口,单位是秒,默认是 1 秒
GatewayRuleManager.loadRules(rules);
}
@Override
public void run(String... args) throws Exception {
dynamicByNacosListener();
}
}
4、启动Spring cloud gateway服务
增加系统启动参数:-Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=gateway-sentinel
-Dcsp.sentinel.app.type=1 Sentinel 网关类型
-Dcsp.sentinel.dashboard.server=localhost:8090 限流控制服务地址
-Dproject.name=gateway-sentinel 注册到限流服务控制的项目名称
5、连续访问接口地址验证限流
出现以下信息表示限流成功
查看Sentinel控制台流控规则
6、Nacos配置中心修改限流规则验证动态加载配置
idea控制台会输出监听到的新配置
Sentinel控制台查看规则是否自动更新
以上就是本文的全部内容,希望对大家的学习有所帮助。
更多推荐
所有评论(0)