网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,我们本次采用前面学过的Sentinel组件来实现网关的限流。Sentinel支持对SpringCloud Gateway、Zuul等主流网关进行限流。
从1.6.0版本开始,Sentinel提供了SpringCloud Gateway的适配模块,可以提供两种资源维度的限流:
1 导入依赖
- <dependency>
- <groupId>com.alibaba.csp</groupId>
- <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
- </dependency>
2 编写配置类
基于Sentinel 的Gateway限流是通过其提供的Filter来完成的,使用时只需注入对应的
SentinelGatewayFilter实例以及 SentinelGatewayBlockExceptionHandler 实例即可。
- @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 GlobalFilter sentinelGatewayFilter() {
- return new SentinelGatewayFilter();
- }
- // 配置初始化的限流参数
- @PostConstruct
- public void initGatewayRules() {
- Set<GatewayFlowRule> rules = new HashSet<>();
- rules.add(
- new GatewayFlowRule("product_route") //资源名称,对应路由id
- .setCount(1) // 限流阈值
- .setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
- );
- GatewayRuleManager.loadRules(rules);
- }
- // 配置限流的异常处理器
- @Bean
- @Order(Ordered.HIGHEST_PRECEDENCE)
- public SentinelGatewayBlockExceptionHandler
- sentinelGatewayBlockExceptionHandler() {
- return new SentinelGatewayBlockExceptionHandler(viewResolvers,
- serverCodecConfigurer);
- }
- // 自定义限流异常页面
- @PostConstruct
- public void initBlockHandlers() {
- BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
- public Mono<ServerResponse> handleRequest(ServerWebExchange
- serverWebExchange, Throwable throwable) {
- Map map = new HashMap<>();
- map.put("code", 0);
- map.put("message", "接口被限流了");
- return ServerResponse.status(HttpStatus.OK).
- contentType(MediaType.APPLICATION_JSON_UTF8).
- body(BodyInserters.fromObject(map));
- }
- };
- GatewayCallbackManager.setBlockHandler(blockRequestHandler);
- }
- }
3 测试
在一秒钟内多次访问http://localhost:7000/product-serv/product/1就可以看到限流启作用了。
4 自定义API分组
自定义API分组是一种更细粒度的限流规则定义
- /**
- * 配置初始化的限流参数
- */
- @PostConstruct
- public void initGatewayRules() {
- Set<GatewayFlowRule> rules = new HashSet<>();
- rules.add(new
- GatewayFlowRule("product_api1").setCount(1).setIntervalSec(1));
- rules.add(new
- GatewayFlowRule("product_api2").setCount(1).setIntervalSec(1));
- GatewayRuleManager.loadRules(rules);
- }
- //自定义API分组
- @PostConstruct
- private void initCustomizedApis() {
- Set<ApiDefinition> definitions = new HashSet<>();
- ApiDefinition api1 = new ApiDefinition("product_api1")
- .setPredicateItems(new HashSet<ApiPredicateItem>() {{
- // 以/product-serv/product/api1 开头的请求
- add(new ApiPathPredicateItem().setPattern("/product-
- serv/product/api1/**").
-
- setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
- }});
- ApiDefinition api2 = new ApiDefinition("product_api2")
- .setPredicateItems(new HashSet<ApiPredicateItem>() {{
- // 以/product-serv/product/api2/demo1 完成的url路径匹配
- add(new ApiPathPredicateItem().setPattern("/product-
- serv/product/api2/demo1"));
- }});
- definitions.add(api1);
- definitions.add(api2);
- GatewayApiDefinitionManager.loadApiDefinitions(definitions);
- }