当前位置:   article > 正文

Sentinel限流实战_sentinelgatewayblockexceptionhandler

sentinelgatewayblockexceptionhandler

一,应用场景:开放平台提供url给第三方调用时,针对调用方请求进行限流,实现对ip和参数进行限流

两种实现方式

1,对SentinelGatewayBlockExceptionHandler进行改造,新创建一个该类,重写里面的返回方法

可参考:http://www.cppcns.com/ruanjian/java/257764.html

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
    // Register the block exception handler for Spring Cloud Gateway.
    return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}

2,平台实现,自定义响应处理类,实现BlockRequestHandler接口,包装返回信息,初始化调用自定义响应处理类

参考:https://blog.csdn.net/developlee/article/details/100987345

您可以在 GatewayCallbackManager 注册回调进行定制:

  • setBlockHandler:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 BlockRequestHandler。默认实现为 DefaultBlockRequestHandler,当被限流时会返回类似于下面的错误信息:Blocked by Sentinel: FlowException

二,代码实现,改造SentinelGatewayBlockExceptionHandler

1,Sentinel配置类

  1. /**
  2. * sentinel配置
  3. *
  4. * @author lr
  5. * @date 2019-09-12 13:31
  6. */
  7. @Configuration
  8. public class SentinelGatewayConfiguration {
  9. @Autowired
  10. private InetUtils inetUtils;
  11. private final List<ViewResolver> viewResolvers;
  12. private final ServerCodecConfigurer serverCodecConfigurer;
  13. public SentinelGatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
  14. ServerCodecConfigurer serverCodecConfigurer) {
  15. this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
  16. this.serverCodecConfigurer = serverCodecConfigurer;
  17. }
  18. // @Bean
  19. // @Order(Ordered.HIGHEST_PRECEDENCE)
  20. // public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
  21. // // Register the block exception handler for Spring Cloud Gateway.
  22. // return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
  23. // }
  24. /**
  25. * 自定义响应参数
  26. *
  27. * @return
  28. */
  29. @Bean
  30. @Order(Ordered.HIGHEST_PRECEDENCE)
  31. public JsonSentinelGatewayBlockExceptionHandler jsonSentinelGatewayBlockExceptionHandler() {
  32. return new JsonSentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
  33. }
  34. @Bean
  35. @Order(-1)
  36. public GlobalFilter sentinelGatewayFilter() {
  37. return new SentinelGatewayFilter();
  38. }
  39. @PostConstruct
  40. public void doInit() {
  41. initGatewayRules();
  42. //GatewayCallbackManager.setBlockHandler(new OpenBlockRequestHandler());
  43. //设置监控ip(多网卡时默认获取有问题,所以需要采用springCloud网卡工具类)
  44. SentinelConfig.setConfig(TransportConfig.HEARTBEAT_CLIENT_IP, inetUtils.findFirstNonLoopbackAddress().getHostAddress());
  45. }
  46. /**
  47. * 初始化路由规则
  48. */
  49. private void initGatewayRules() {
  50. Set<GatewayFlowRule> rules = new HashSet<>();
  51. //限制每个ip每秒只能调用5次,
  52. //setBurst突发请求额外增加5
  53. rules.add(new GatewayFlowRule("open_gateway")
  54. .setCount(5)
  55. .setIntervalSec(1)
  56. .setBurst(5)
  57. .setParamItem(new GatewayParamFlowItem()
  58. .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_CLIENT_IP)
  59. )
  60. );
  61. //限制一个应用appId每秒只能调用5
  62. //setBurst突发请求额外增加5
  63. rules.add(new GatewayFlowRule("open_gateway")
  64. .setCount(5)
  65. .setIntervalSec(1)
  66. .setBurst(5)
  67. .setParamItem(new GatewayParamFlowItem()
  68. .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
  69. .setFieldName("appId")
  70. )
  71. );
  72. //限制一个应用appId每秒只能调用5
  73. //setBurst突发请求额外增加5
  74. rules.add(new GatewayFlowRule("open_gateway")
  75. .setCount(5)
  76. .setIntervalSec(1)
  77. .setBurst(5)
  78. .setParamItem(new GatewayParamFlowItem()
  79. .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
  80. .setFieldName("appId").setPattern("testApp")
  81. )
  82. );
  83. GatewayRuleManager.loadRules(rules);
  84. }
  85. }

2,自定义响应类

  1. public class JsonSentinelGatewayBlockExceptionHandler implements WebExceptionHandler {
  2. private List<ViewResolver> viewResolvers;
  3. private List<HttpMessageWriter<?>> messageWriters;
  4. private final Supplier<ServerResponse.Context> contextSupplier = () -> {
  5. return new ServerResponse.Context() {
  6. public List<HttpMessageWriter<?>> messageWriters() {
  7. return JsonSentinelGatewayBlockExceptionHandler.this.messageWriters;
  8. }
  9. public List<ViewResolver> viewResolvers() {
  10. return JsonSentinelGatewayBlockExceptionHandler.this.viewResolvers;
  11. }
  12. };
  13. };
  14. public JsonSentinelGatewayBlockExceptionHandler(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
  15. this.viewResolvers = viewResolvers;
  16. this.messageWriters = serverCodecConfigurer.getWriters();
  17. }
  18. private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {
  19. ServerHttpResponse serverHttpResponse = exchange.getResponse();
  20. serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
  21. JSONObject responseObj = new JSONObject();
  22. responseObj.put("code", 403);
  23. responseObj.put("msg", "请求过于频繁,请稍后重试");
  24. byte[] datas = responseObj.toString().getBytes(StandardCharsets.UTF_8);
  25. DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);
  26. return serverHttpResponse.writeWith(Mono.just(buffer));
  27. }
  28. public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
  29. if (exchange.getResponse().isCommitted()) {
  30. return Mono.error(ex);
  31. } else {
  32. return !BlockException.isBlockException(ex) ? Mono.error(ex) : this.handleBlockedRequest(exchange, ex).flatMap((response) -> {
  33. return this.writeResponse(response, exchange);
  34. });
  35. }
  36. }
  37. private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) {
  38. return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
  39. }
  40. }

 三,代码实现,GatewayCallbackManager回调

1,Sentinel配置类

  1. /**
  2. * sentinel配置
  3. *
  4. * @author lr
  5. * @date 2019-09-12 13:31
  6. */
  7. @Configuration
  8. public class SentinelGatewayConfiguration {
  9. @Autowired
  10. private InetUtils inetUtils;
  11. private final List<ViewResolver> viewResolvers;
  12. private final ServerCodecConfigurer serverCodecConfigurer;
  13. public SentinelGatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
  14. ServerCodecConfigurer serverCodecConfigurer) {
  15. this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
  16. this.serverCodecConfigurer = serverCodecConfigurer;
  17. }
  18. @Bean
  19. @Order(Ordered.HIGHEST_PRECEDENCE)
  20. public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
  21. // Register the block exception handler for Spring Cloud Gateway.
  22. return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
  23. }
  24. /**
  25. * 自定义响应参数
  26. *
  27. * @return
  28. */
  29. // @Bean
  30. // @Order(Ordered.HIGHEST_PRECEDENCE)
  31. // public JsonSentinelGatewayBlockExceptionHandler jsonSentinelGatewayBlockExceptionHandler() {
  32. // return new JsonSentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
  33. // }
  34. @Bean
  35. @Order(-1)
  36. public GlobalFilter sentinelGatewayFilter() {
  37. return new SentinelGatewayFilter();
  38. }
  39. @PostConstruct
  40. public void doInit() {
  41. initGatewayRules();
  42. GatewayCallbackManager.setBlockHandler(new OpenBlockRequestHandler());
  43. //设置监控ip(多网卡时默认获取有问题,所以需要采用springCloud网卡工具类)
  44. SentinelConfig.setConfig(TransportConfig.HEARTBEAT_CLIENT_IP, inetUtils.findFirstNonLoopbackAddress().getHostAddress());
  45. }
  46. /**
  47. * 初始化路由规则
  48. */
  49. private void initGatewayRules() {
  50. Set<GatewayFlowRule> rules = new HashSet<>();
  51. //限制每个ip每秒只能调用5次,
  52. //setBurst突发请求额外增加5
  53. rules.add(new GatewayFlowRule("open_gateway")
  54. .setCount(5)
  55. .setIntervalSec(1)
  56. .setBurst(5)
  57. .setParamItem(new GatewayParamFlowItem()
  58. .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_CLIENT_IP)
  59. )
  60. );
  61. //限制一个应用appId每秒只能调用5
  62. //setBurst突发请求额外增加5
  63. rules.add(new GatewayFlowRule("open_gateway")
  64. .setCount(5)
  65. .setIntervalSec(1)
  66. .setBurst(5)
  67. .setParamItem(new GatewayParamFlowItem()
  68. .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
  69. .setFieldName("appId")
  70. )
  71. );
  72. //限制一个应用appId每秒只能调用5
  73. //setBurst突发请求额外增加5
  74. rules.add(new GatewayFlowRule("open_gateway")
  75. .setCount(5)
  76. .setIntervalSec(1)
  77. .setBurst(5)
  78. .setParamItem(new GatewayParamFlowItem()
  79. .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
  80. .setFieldName("appId").setPattern("testApp")
  81. )
  82. );
  83. GatewayRuleManager.loadRules(rules);
  84. }
  85. }

2,自定义响应消息类

  1. /**
  2. * @author lr
  3. * @date 2019-09-12 15:15
  4. */
  5. public class OpenBlockRequestHandler implements BlockRequestHandler {
  6. @Override
  7. public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) {
  8. // JSON result by default.
  9. return ServerResponse.status(HttpStatus.OK)
  10. .contentType(MediaType.APPLICATION_JSON_UTF8)
  11. .body(fromObject(buildErrorResult(ex)));
  12. }
  13. private ResponseBean buildErrorResult(Throwable ex) {
  14. return ResponseBeanUtils.getResponseBean(ErrorCode.REQUEST_QPS_LIMIT_ERROR);
  15. }
  16. }

四,postman调用结果

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/301974
推荐阅读