概念
Gateway是整个应用的大门,是整个集群的入口,我们订单服务集群,商品服务集群等等集群都是由Gateway调用的,那我们其实可以在Gateway访问商品服务集群或者订单服务集群之前来使用sentinel进行流控
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:
- route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
- 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组
代码地址
https://gitee.com/zjj19941/ZJJ_Neaten5.10/tree/master/ZJJ_Gateway/demo10
代码
pom依赖
<!-- gateway接入sentinel -->
<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>
yaml配置
server:
port: 8888
spring:
application:
name: mall-gateway-sentinel-demo
main:
allow-bean-definition-overriding: true
#配置nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: zjj101:8848
sentinel:
transport:
# 添加sentinel的控制台地址
dashboard: zjj101:8855
# 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
#port: 8719
gateway:
# 是否开启网关
enabled: true
#设置路由:路由id、路由到微服务的uri、断言
routes:
- id: order_route #路由ID,全局唯一,建议配合服务名
uri: lb://mall-order #lb 整合负载均衡器ribbon,loadbalancer
predicates:
- Path=/order/**
配置限流异常处理器和限流过滤器
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
/**
* 限流异常处理器
*
* @return
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
/**
* 限流过滤器
*
* @return
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@PostConstruct
public void doInit() {
// //初始化自定义的API
// initCustomizedApis();
// //初始化网关限流规则
// initGatewayRules();
// //自定义限流异常处理器
initBlockRequestHandler();
}
private void initCustomizedApis() {
Set<ApiDefinition> definitions = new HashSet<>();
// 资源保护名user_service_api Path:/user/**
ApiDefinition api = new ApiDefinition("user_service_api")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem().setPattern("/user/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
//resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。
//count:限流阈值
//intervalSec:统计时间窗口,单位是秒,默认是 1 秒。
rules.add(new GatewayFlowRule("order_route")
.setCount(1)
.setIntervalSec(1)
);
rules.add(new GatewayFlowRule("user_service_api")
.setCount(2)
.setIntervalSec(1)
);
// 加载网关规则
GatewayRuleManager.loadRules(rules);
}
/**
* 自定义异常处理器
*/
private void initBlockRequestHandler() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
HashMap<String, String> result = new HashMap<>();
result.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
result.put("msg", "你已经被限流了");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(result));
}
};
//设置自定义异常处理器
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
测试
当postman访问超过阈值的时候会触发 自定义异常处理器 配置的返回值