当前位置:   article > 正文

springcloudalibaba架构(17):Gateway网关限流_gateway 网关限流

gateway 网关限流

前言

什么是网关限流?
限流有哪些维度?
如何自定义限流规则?

本章代码已分享至Gitee: https://gitee.com/lengcz/springcloudalibaba01.git

第一节 Gateway网关限流

网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,本次采用Sentinel组件实现网关的限流。Sentinel支持对SpringCloud Gateway、 Zuul等主流网关进行限流。

在这里插入图片描述
从1.6.0版本后,Sentinel提供了SpringCloud Gateway的适配模块,可以提供两种资源维度的限流

  • route维度:在spring配置文件中配置的路由条目,资源名为对应的routeId
  • 自定义API维度:用户可以利用Sentinel提供的API来自定义一些API分组

第二节 路由维度的限流

如何进行路由维度的限流?

  1. 在api-gateway模块里引入依赖
   <!--sentinel网关限流-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 编写路由维度限流代码
package com.lcz.config;

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(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数
    @PostConstruct
    public void doInit() {
        Set<GatewayFlowRule> rules=new HashSet<>();
        rules.add(new GatewayFlowRule("product_route") //product_route 路由的id
                .setCount(1)  //限流阈值
                .setIntervalSec(1)); //统计时间窗口,单位秒
        GatewayRuleManager.loadRules(rules);
    }

    //配置限流的异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    //自定义限流异常页面
    @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("message","API网关限流");

                Mono<ServerResponse>  mono=ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(map));
                return mono;
            }
        };

        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

代码针对的是配置文件的product_route这个路由进行的限流。
在这里插入图片描述

  1. 启动网关测试,频繁请求,发现路由product_route被限流了。而请求其它路由则未被限流。
    在这里插入图片描述
    在这里插入图片描述

第三节 自定义API分组维度限流

自定义API分组限流是一种更细粒度的限流规则。
如何实现API分组限流?

  1. 只要对上面GatewayConfiguration进行稍作修改
package com.lcz.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(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数
    @PostConstruct
    public void doInit() {
        Set<GatewayFlowRule> rules=new HashSet<>();
        /**
         * 针对路由的限流,资源名product_route为路由id
         */
        rules.add(new GatewayFlowRule("product_route") //product_route 路由的id
                .setCount(1)  //限流阈值
                .setIntervalSec(1)); //统计时间窗口,单位秒

        /**
         * 针对api分组的限流,设置了两组限流规则
         */
        rules.add(new GatewayFlowRule("order_api1").setCount(1).setIntervalSec(1));
        rules.add(new GatewayFlowRule("order_api2").setCount(1).setIntervalSec(1));

        GatewayRuleManager.loadRules(rules);
    }

    //配置限流的异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    //自定义限流异常页面
    @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("message","API网关限流");

                Mono<ServerResponse>  mono=ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(map));
                return mono;
            }
        };

        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

    //自定义API分组
    @PostConstruct
    public void initCustomizedApis(){
        Set<ApiDefinition> definitions=new HashSet<>();
        ApiDefinition api1=new ApiDefinition("order_api1");
        api1.setPredicateItems(new HashSet<ApiPredicateItem>(){
            {
                //可以设置多个匹配规则
                add(new ApiPathPredicateItem().setPattern("/server-order/api1/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                add(new ApiPathPredicateItem().setPattern("/server-order/api3/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
            }
        });
        ApiDefinition api2=new ApiDefinition("order_api2");
        api2.setPredicateItems(new HashSet<ApiPredicateItem>(){
            {
//
                /**
                 * setMatchStrategy设置匹配策略,如果不设置匹配策略,默认就是SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT,精确匹配,URL链接需相同<br>
                 */
                add(new ApiPathPredicateItem().setPattern("/server-order/api2/demo1"));
//                add(new ApiPathPredicateItem().setPattern("/server-order/api2/demo1").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT));
            }
        });

        definitions.add(api1);
        definitions.add(api2);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

解释一下新增的内容,新增了两组资源的限流规则,资源名为order_api1和order_api2
在这里插入图片描述
在这里插入图片描述

  1. 上面我们定义了对/server-order/api1/**和/server-order/api2/demo1的不同限流分组,因为调用的是order这个微服务,所以需要在order模块里面编写测试的demo
@RestController
@Slf4j
public class ApiDemoController {


    @RequestMapping("/api1/demo1")
    public String demo1() {
        return "hello";
    }
    @RequestMapping("/api1/demo2")
    public String demo2() {
        return "hello";
    }
    @RequestMapping("/api2/demo1")
    public String demo3() {
        return "hello";
    }
    @RequestMapping("/api2/demo2")
    public String demo4() {
        return "hello";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  1. 启动网关和order模块测试,频繁请求http://127.0.0.1:7000/server-order/api1/demo2,提示被限流。而请求http://127.0.0.1:7000/server-order/api2/demo2 则未被限流,但是请求http://127.0.0.1:7000/server-order/api2/demo1则被限流,因为规则里添加了它。
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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

闽ICP备14008679号