概念
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: 8888spring:application:name: mall-gateway-sentinel-demomain:allow-bean-definition-overriding: true#配置nacos注册中心地址cloud:nacos:discovery:server-addr: zjj101:8848sentinel:transport:# 添加sentinel的控制台地址dashboard: zjj101:8855# 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer#port: 8719gateway:# 是否开启网关enabled: true#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route #路由ID,全局唯一,建议配合服务名uri: lb://mall-order #lb 整合负载均衡器ribbon,loadbalancerpredicates:- Path=/order/**
配置限流异常处理器和限流过滤器
@Configurationpublic 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();}@PostConstructpublic 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() {@Overridepublic 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访问超过阈值的时候会触发 自定义异常处理器 配置的返回值
