zoukankan      html  css  js  c++  java
  • spring cloud gateway集成sentinel实现网关限流全局处理

    官网地址 https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81

    Sentinel 1.6.0发布了Sentinel API网关适配器通用模块,此模块中包含网关限流的规则和自定义API的实体和管理逻辑:
    • GatewayFlowRule:网关限流规则,针对API Gateway的场景定制的限流规则,可以针对不同的路由或自定义的API分组进行限流,支持针对请求中的参数,标头,来源IP等进行定制化的限流。
    • ApiDefinition:用户自定义的API定义分组,可以看做是一些URL匹配的组合。就像我们可以定义一个API一样my_api,请求路径模式为/foo/**和/baz/**的都归到my_api这个API分组。限流的时候可以针对这个自定义的API分组维度进行限流。
    其中网关限流规则GatewayFlowRule的细分解释如下:
    • resource:资源名称,可以是网关中的路线名称或用户自定义的API分组名称。
    • resourceMode:规则是针对API网关的路由(RESOURCE_MODE_ROUTE_ID)还是用户在Sentinel中定义的API分组(RESOURCE_MODE_CUSTOM_API_NAME),而是路由。
    • grade:限流指标维度,同限流规则的grade细分。
    • count:限流阈值
    • intervalSec:统计时间窗口,单位是秒,至少是1秒。
    • controlBehavior:流量整形的控制效果,同限流规则的controlBehavior细分,目前支持快速失败和匀速排队两种模式,而是是快速失败。
    • burst:应对突发请求时额外允许的请求数量。
    • maxQueueingTimeoutMs:匀速排队模式下的最大排队时间,单位是几分钟,仅在匀速排队模式下生效。
    • paramItem:参数限流配置。若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换成热点规则。
      • parseStrategy:从请求中提取参数的策略,当前支持提取源IP(PARAM_PARSE_STRATEGY_CLIENT_IP),主机(PARAM_PARSE_STRATEGY_HOST),任意头(PARAM_PARSE_STRATEGY_HEADER)和任意URL参数(PARAM_PARSE_STRATEGY_URL_PARAM)模式。
      • fieldName:如果提取策略选择Header模式或URL参数模式,则需要指定对应的header名称或URL参数名。
      • pattern:参数值的匹配模式,只有匹配该模式的请求属性值会重新统计和流控;若为空则统计该请求属性的所有值。(1.6.2版本开始支持)
      • matchStrategy:参数值的匹配策略,当前支持精确匹配(PARAM_MATCH_STRATEGY_EXACT),子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)和正则匹配(PARAM_MATCH_STRATEGY_REGEX)。(1.6.2版本开始支持)
    用户可以通过GatewayRuleManager.loadRules(rules)手动加载网关规则,或通过GatewayRuleManager.register2Property(property)注册动态规则源动态推送(推荐方式)
     
    SpringCloudGateway
    引入Maven依赖
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    </dependency>
    注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例
    sentinel提供了两种方式用来设置资源
    1.通过配置文件进行路由设置
    server:
      port: 8085
    
    
    spring:
      main:
        allow-bean-definition-overriding: true
      application:
        name: live-gateway
      profiles:
        active: loc
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
        gateway:
          enabled: true
          discovery:
            locator:
              lower-case-service-id: true
          routes:
    #        会被标识为 Sentinel 的资源
            - id:cloud_route
              uri: lb://spring/cloud/test
              predicates:
                - Path=/spring/cloud/test/**

    网关设置路由:

     对应的服务:

    2.在代码中进行设置

    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.GatewayCallbackManager;
    import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
    import com.live.gateway.handler.GatewayHandler;
    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.codec.ServerCodecConfigurer;
    import org.springframework.web.reactive.result.view.ViewResolver;
    
    
    import javax.annotation.PostConstruct;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    
    /**
    * @author wjc
    * @description
    * @date 2020/10/9
    */
    @Configuration
    public class GatewayConfig {
    
    
        private final List<ViewResolver> viewResolvers;
        private final ServerCodecConfigurer serverCodecConfigurer;
    
    
        public GatewayConfig(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                             ServerCodecConfigurer serverCodecConfigurer) {
            this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
            this.serverCodecConfigurer = serverCodecConfigurer;
        }
    
    
        @Bean
        @Order(Ordered.HIGHEST_PRECEDENCE)
        public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
            // Register the block exception handler for Spring Cloud Gateway.
            return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
        }
    
    
        @Bean
        @Order(-1)
        public GlobalFilter sentinelGatewayFilter() {
            return new SentinelGatewayFilter();
        }
    
    
        @PostConstruct
        public void doInit() {
            initCustomizedApis();
            initGatewayRules();
            //自定义处理被限流的请求
            GatewayCallbackManager.setBlockHandler(new GatewayHandler());
        }
    
    
        //详细配置参考官方文档
        private void initCustomizedApis() {
            Set<ApiDefinition> definitions = new HashSet<>();
            ApiDefinition api1 = new ApiDefinition("some_customized_api")
                    .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                        add(new ApiPathPredicateItem().setPattern("/spring/cloud/test/**")
                                .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                    }});
            definitions.add(api1);
            GatewayApiDefinitionManager.loadApiDefinitions(definitions);
        }
    
    
        private void initGatewayRules() {
            Set<GatewayFlowRule> rules = new HashSet<>();
    
    
            rules.add(new GatewayFlowRule("some_customized_api")
                    .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
                    .setCount(1)
                    .setIntervalSec(1)
            );
            GatewayRuleManager.loadRules(rules);
        }
    
    
    }
    import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
    import org.springframework.http.MediaType;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.web.reactive.function.BodyInserters;
    import org.springframework.web.reactive.function.server.ServerResponse;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    
    /**
    * @author wjc
    * @description
    * @date 2020/10/9
    */
    public class GatewayHandler implements BlockRequestHandler {
    
    
        private static final String DEFAULT_BLOCK_MSG_PREFIX = "Blocked by Sentinel: ";
    
    
        @Override
        public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
            ServerHttpRequest request = serverWebExchange.getRequest();
            System.out.println(request.getPath());
            return ServerResponse.status(200)
                    .contentType(MediaType.APPLICATION_JSON)
    //                .body(BodyInserters.fromValue(buildErrorResult(throwable)));
                    .body(BodyInserters.fromValue(buildErrorResult(request.getPath().value())));
        }
    
    
        private ErrorResult buildErrorResult(Throwable ex) {
    //        return new ErrorResult(200, DEFAULT_BLOCK_MSG_PREFIX + ex.getClass().getSimpleName());
            return new ErrorResult(500, "限流");
        }
    
    
        private ErrorResult buildErrorResult(String path) {
            if(path.equals("/spring/cloud/test/block/handler")){
                return new ErrorResult(200, "hhahahhahah限流");
            }
            return new ErrorResult(500, "限流");
        }
    
    
        private static class ErrorResult {
            private final int code;
            private final String message;
    
    
            ErrorResult(int code, String message) {
                this.code = code;
                this.message = message;
            }
    
    
            public int getCode() {
                return code;
            }
    
    
            public String getMessage() {
                return message;
            }
        }
    }

    通过网关请求接口

    达到阈值限流

     

  • 相关阅读:
    pandas 修改指定列中所有内容
    Python 实现获取【昨天】【今天】【明天】日期
    Selenium定位不到指定元素原因之iframe(unable to locate element)
    Pandas 通过追加方式合并多个csv
    python setup.py install 报错:error: [WinError 3] 系统找不到指定的路径。: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\PlatformSDK\lib
    pandas 如何判断指定列是否(全部)为NaN(空值)
    报错:PermissionError: [WinError 5] Access is denied: 'C:\Program Files\Anaconda3\Lib\site-packages\pywebhdfs'
    Node.js的函数返回值
    在Eclipse中使用JSHint检查JavaScript
    Node.js前端自动化工具:gulp
  • 原文地址:https://www.cnblogs.com/gqymy/p/13794583.html
Copyright © 2011-2022 走看看