概念

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依赖

  1. <!-- gateway接入sentinel -->
  2. <dependency>
  3. <groupId>com.alibaba.cloud</groupId>
  4. <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alibaba.cloud</groupId>
  8. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  9. </dependency>

yaml配置

  1. server:
  2. port: 8888
  3. spring:
  4. application:
  5. name: mall-gateway-sentinel-demo
  6. main:
  7. allow-bean-definition-overriding: true
  8. #配置nacos注册中心地址
  9. cloud:
  10. nacos:
  11. discovery:
  12. server-addr: zjj101:8848
  13. sentinel:
  14. transport:
  15. # 添加sentinel的控制台地址
  16. dashboard: zjj101:8855
  17. # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
  18. #port: 8719
  19. gateway:
  20. # 是否开启网关
  21. enabled: true
  22. #设置路由:路由id、路由到微服务的uri、断言
  23. routes:
  24. - id: order_route #路由ID,全局唯一,建议配合服务名
  25. uri: lb://mall-order #lb 整合负载均衡器ribbon,loadbalancer
  26. predicates:
  27. - Path=/order/**

配置限流异常处理器和限流过滤器

  1. @Configuration
  2. public class GatewayConfiguration {
  3. private final List<ViewResolver> viewResolvers;
  4. private final ServerCodecConfigurer serverCodecConfigurer;
  5. public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
  6. ServerCodecConfigurer serverCodecConfigurer) {
  7. this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
  8. this.serverCodecConfigurer = serverCodecConfigurer;
  9. }
  10. /**
  11. * 限流异常处理器
  12. *
  13. * @return
  14. */
  15. @Bean
  16. @Order(Ordered.HIGHEST_PRECEDENCE)
  17. public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
  18. // Register the block exception handler for Spring Cloud Gateway.
  19. return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
  20. }
  21. /**
  22. * 限流过滤器
  23. *
  24. * @return
  25. */
  26. @Bean
  27. @Order(Ordered.HIGHEST_PRECEDENCE)
  28. public GlobalFilter sentinelGatewayFilter() {
  29. return new SentinelGatewayFilter();
  30. }
  31. @PostConstruct
  32. public void doInit() {
  33. // //初始化自定义的API
  34. // initCustomizedApis();
  35. // //初始化网关限流规则
  36. // initGatewayRules();
  37. // //自定义限流异常处理器
  38. initBlockRequestHandler();
  39. }
  40. private void initCustomizedApis() {
  41. Set<ApiDefinition> definitions = new HashSet<>();
  42. // 资源保护名user_service_api Path:/user/**
  43. ApiDefinition api = new ApiDefinition("user_service_api")
  44. .setPredicateItems(new HashSet<ApiPredicateItem>() {{
  45. add(new ApiPathPredicateItem().setPattern("/user/**")
  46. .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
  47. }});
  48. definitions.add(api);
  49. GatewayApiDefinitionManager.loadApiDefinitions(definitions);
  50. }
  51. private void initGatewayRules() {
  52. Set<GatewayFlowRule> rules = new HashSet<>();
  53. //resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。
  54. //count:限流阈值
  55. //intervalSec:统计时间窗口,单位是秒,默认是 1 秒。
  56. rules.add(new GatewayFlowRule("order_route")
  57. .setCount(1)
  58. .setIntervalSec(1)
  59. );
  60. rules.add(new GatewayFlowRule("user_service_api")
  61. .setCount(2)
  62. .setIntervalSec(1)
  63. );
  64. // 加载网关规则
  65. GatewayRuleManager.loadRules(rules);
  66. }
  67. /**
  68. * 自定义异常处理器
  69. */
  70. private void initBlockRequestHandler() {
  71. BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
  72. @Override
  73. public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
  74. HashMap<String, String> result = new HashMap<>();
  75. result.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
  76. result.put("msg", "你已经被限流了");
  77. return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
  78. .contentType(MediaType.APPLICATION_JSON)
  79. .body(BodyInserters.fromValue(result));
  80. }
  81. };
  82. //设置自定义异常处理器
  83. GatewayCallbackManager.setBlockHandler(blockRequestHandler);
  84. }
  85. }

测试

image.png

当postman访问超过阈值的时候会触发 自定义异常处理器 配置的返回值
image.png