Gateway結合Sentinel 限流
阿新 • • 發佈:2021-11-30
Gateway結合Sentinel 限流
分組限流
實際開發中我們往往是分組限流
我們先為provider類編寫幾個分組介面
@GetMapping("/api1/demo1") public String demo1(){ return "api1-demo1"; } @GetMapping("/api1/demo2") public String demo2(){ return "api1-demo2"; } @GetMapping("/api2/demo1") public String demo3(){ return "api2-demo1"; } @GetMapping("/api2/demo2") public String demo4(){ return "api2-demo2"; }
編寫配置類
為gateway模組編寫配置類 處理分組限流配置
package com.jie.config; import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem; import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler; import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler; import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import javax.annotation.PostConstruct; import java.util.*; @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; } //配置限流的異常處理 @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } //配置初始化的限流引數 @PostConstruct public void initGatewayRules(){ Set<GatewayFlowRule> rules = new HashSet<>(); //為分組進行限流 一秒一次 這裡名字是自定義的 與下面對映 rules.add(new GatewayFlowRule("provider_api1").setCount(1).setIntervalSec(1)); rules.add(new GatewayFlowRule("provider_api2").setCount(1).setIntervalSec(1)); GatewayRuleManager.loadRules(rules); } //初始化限流過濾器 @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } //自定義限流異常頁面 @PostConstruct public void initBlockHandlers(){ BlockRequestHandler blockRequestHandler = new BlockRequestHandler() { @Override public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { Map map = new HashMap(); map.put("code",0); map.put("msg","被限流了"); return ServerResponse.status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(map)); } }; GatewayCallbackManager.setBlockHandler(blockRequestHandler); } //自定義API分組 @PostConstruct private void initCustomizedApis(){ Set<ApiDefinition> definitions = new HashSet<>(); //為上面自定義組名字匹配是對映哪些請求 ApiDefinition api1 = new ApiDefinition("provider_api1") .setPredicateItems(new HashSet<ApiPredicateItem>(){{ add(new ApiPathPredicateItem().setPattern("/provider/api1/**") .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); }}); ApiDefinition api2 = new ApiDefinition("provider_api2") .setPredicateItems(new HashSet<ApiPredicateItem>(){{ add(new ApiPathPredicateItem().setPattern("/provider/api2/demo1")); }}); definitions.add(api1); definitions.add(api2); GatewayApiDefinitionManager.loadApiDefinitions(definitions); } }
這裡我們對Api1這組全部介面都限流了
測試訪問:
如果超過一秒一次就會被限制
但是這裡要注意限流的是閘道器請求 如果你直接訪問提供訪問的埠是不會被限制的
由於我們設定api2只有demo1介面被限制 所以我們可以無限次通過閘道器訪問/ap2/demo2這個介面