sentinel 网关限流


sentinel 网关限流

        

官网:https://sentinelguard.io/zh-cn/docs/api-gateway-flow-control.html

                

                       

                                     

网关限流

        

sentinel支持对主流的网关应用(zuul、gateway等)进行限流

                   sentinel 网关限流_第1张图片

          

*************

实现原理

            

                   sentinel 网关限流_第2张图片

网关流控规则处理

# 规则加载
GatewayRuleManager加载网关流控规则(GatewayFlowRule),

# 规则转换
无论是否针对请求属性进行限流,都会将网关流控规则转化为热点参数规则(ParamFlowRule)
转换时根据请求属性配置,为网关流控规则设置参数索引(idx)
如果规则不针对请求属性,就在参数最后一个位置置入预设的常量,达到普通流控的效果

# 规则存储
将转换后的热点参数规则存储在GatewayRuleManager中,与正常的热点参数规则隔离

                        

网关请求处理

# 请求过滤:SentinelGatewayFilter
外部请求进入网关时会用SentinelGatewayFilter过滤,执行route id、api分组匹配;
 
# 请求属性处理:GatewayFlowRule、ParamFlowRule
根据配置的网关流控规则来解析请求属性(用于热点参数限流),
依照参数索引顺序组装参数数组,最终传入SphU.entry(res, args);

# 网关限流:GatewayFlowSlot
sentinel在slot chain中添加GatewayFlowSlot,
从GatewayRuleManager提取网关限流规则,执行限流操作

             

GatewayRuleManager:处理网关规则

public final class GatewayRuleManager {
    private static final Map> GATEWAY_RULE_MAP = new ConcurrentHashMap();
    private static final Map> CONVERTED_PARAM_RULE_MAP = new ConcurrentHashMap();
    private static final GatewayRuleManager.GatewayRulePropertyListener LISTENER = new GatewayRuleManager.GatewayRulePropertyListener();
    private static SentinelProperty> currentProperty = new DynamicSentinelProperty();
    private static final Set FIELD_REQUIRED_SET;

    public static void register2Property(SentinelProperty> property) {
        AssertUtil.notNull(property, "property cannot be null");
        synchronized(LISTENER) {
            RecordLog.info("[GatewayRuleManager] Registering new property to gateway flow rule manager", new Object[0]);
            currentProperty.removeListener(LISTENER);
            property.addListener(LISTENER);
            currentProperty = property;
        }
    }

    public static boolean loadRules(Set rules) {
        return currentProperty.updateValue(rules);
    }

    public static Set getRules() {   //获取所有规则
        Set rules = new HashSet();
        Iterator var1 = GATEWAY_RULE_MAP.values().iterator();

        while(var1.hasNext()) {
            Set ruleSet = (Set)var1.next();
            rules.addAll(ruleSet);
        }

        return rules;
    }

    public static Set getRulesForResource(String resourceName) {
                                       //获取指定资源的限流规则
        if (StringUtil.isBlank(resourceName)) {
            return new HashSet();
        } else {
            Set set = (Set)GATEWAY_RULE_MAP.get(resourceName);
            return set == null ? new HashSet() : new HashSet(set);
        }
    }

    public static List getConvertedParamRules(String resourceName) {
                                      //获取转换后的热点参数规则
        return (List)(StringUtil.isBlank(resourceName) ? new ArrayList() : (List)CONVERTED_PARAM_RULE_MAP.get(resourceName));
    }

    public static boolean isValidRule(GatewayFlowRule rule) {  //检验是否是有效规则
        if (rule != null && !StringUtil.isBlank(rule.getResource()) && rule.getResourceMode() >= 0 && rule.getGrade() >= 0 && !(rule.getCount() < 0.0D) && rule.getBurst() >= 0 && rule.getControlBehavior() >= 0) {
            if (rule.getGrade() == 2 && rule.getMaxQueueingTimeoutMs() < 0) {
                return false;
            } else if (rule.getIntervalSec() <= 0L) {
                return false;
            } else {
                GatewayParamFlowItem item = rule.getParamItem();
                return item != null ? isValidParamItem(item) : true;
            }
        } else {
            return false;
        }
    }

    static boolean isValidParamItem(GatewayParamFlowItem item) {

    private GatewayRuleManager() {
    }

    static {
        currentProperty.addListener(LISTENER);
        FIELD_REQUIRED_SET = new HashSet(Arrays.asList(3, 2, 4));
    }


*********
内部类:GatewayRulePropertyListener

    private static final class GatewayRulePropertyListener implements PropertyListener> {
        private GatewayRulePropertyListener() {
        }

        public void configUpdate(Set conf) {
            this.applyGatewayRuleInternal(conf);
            RecordLog.info("[GatewayRuleManager] Gateway flow rules received: " + GatewayRuleManager.GATEWAY_RULE_MAP, new Object[0]);
        }

        public void configLoad(Set conf) {
            this.applyGatewayRuleInternal(conf);
            RecordLog.info("[GatewayRuleManager] Gateway flow rules loaded: " + GatewayRuleManager.GATEWAY_RULE_MAP, new Object[0]);
        }

        private int getIdxInternal(Map idxMap, String resourceName) {
        private void cacheRegexPattern(GatewayParamFlowItem item) {
        private synchronized void applyGatewayRuleInternal(Set conf) {
        private void applyToConvertedParamMap(Set paramFlowRules) {

SentinelGatewayFilter:处理网关请求

public class SentinelGatewayFilter implements GatewayFilter, GlobalFilter, Ordered {
    private final int order;
    private final GatewayParamParser paramParser;

    public SentinelGatewayFilter() {
        this(-2147483648);
    }

    public SentinelGatewayFilter(int order) {
        this.paramParser = new GatewayParamParser(new ServerWebExchangeItemParser());
        this.order = order;
    }

    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Route route = (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        Mono asyncResult = chain.filter(exchange);
        String apiName;
        if (route != null) {
            String routeId = route.getId();    //解析routrId数据
            Object[] params = this.paramParser.parseParameterFor(routeId, exchange, (r) -> {
                return r.getResourceMode() == 0;
            });
            apiName = (String)Optional.ofNullable(GatewayCallbackManager.getRequestOriginParser()).map((f) -> {
                return (String)f.apply(exchange);
            }).orElse("");
                                              //解析自定义分组数据
            asyncResult = asyncResult.transform(new SentinelReactorTransformer(new EntryConfig(routeId, 3, EntryType.IN, 1, params, new ContextConfig(this.contextName(routeId), apiName))));
        }

        Set matchingApis = this.pickMatchingApiDefinitions(exchange);

        Object[] params;
        for(Iterator var10 = matchingApis.iterator(); var10.hasNext(); asyncResult = asyncResult.transform(new SentinelReactorTransformer(new EntryConfig(apiName, 3, EntryType.IN, 1, params)))) {
            apiName = (String)var10.next();
            params = this.paramParser.parseParameterFor(apiName, exchange, (r) -> {
                return r.getResourceMode() == 1;
            });
        }

        return asyncResult;
    }

    private String contextName(String route) {
        return "sentinel_gateway_context$$route$$" + route;
    }

    Set pickMatchingApiDefinitions(ServerWebExchange exchange) {
        return (Set)GatewayApiMatcherManager.getApiMatcherMap().values().stream().filter((m) -> {
            return m.test(exchange);
        }).map(AbstractApiMatcher::getApiName).collect(Collectors.toSet());
    }

    public int getOrder() {
        return this.order;
    }
}

                     

GatewayFlowSlot:添加到slotChain中,根据规则执行网关限流操作

@SpiOrder(-4000)
public class GatewayFlowSlot extends AbstractLinkedProcessorSlot {
    public GatewayFlowSlot() {
    }

    public void entry(Context context, ResourceWrapper resource, DefaultNode node, int count, boolean prioritized, Object... args) throws Throwable {
        this.checkGatewayParamFlow(resource, count, args);                 //检验限流规则
        this.fireEntry(context, resource, node, count, prioritized, args); //触发限流操作
    }

    private void checkGatewayParamFlow(ResourceWrapper resourceWrapper, int count, Object... args) throws BlockException {
        if (args != null) {
            List rules = GatewayRuleManager.getConvertedParamRules(resourceWrapper.getName());
                                          //获取转换后的热点限流规则
            if (rules != null && !rules.isEmpty()) {
                Iterator var5 = rules.iterator();

                ParamFlowRule rule;
                do {
                    if (!var5.hasNext()) {
                        return;
                    }

                    rule = (ParamFlowRule)var5.next();
                    ParameterMetricStorage.initParamMetricsFor(resourceWrapper, rule);
                } while(ParamFlowChecker.passCheck(resourceWrapper, rule, count, args));

                String triggeredParam = "";
                if (args.length > rule.getParamIdx()) {
                    Object value = args[rule.getParamIdx()];
                    triggeredParam = String.valueOf(value);
                }

                throw new ParamFlowException(resourceWrapper.getName(), triggeredParam, rule);
            }
        }
    }

    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        this.fireExit(context, resourceWrapper, count, args);
    }
}

                

                  

                                     

gateway 限流

      

spring cloud gateway可处理route、api维度的请求数据:

route维度数据:spring配置文件定义的路由分组,资源名为routeId

api维度数据:用户自定义api分组

             

相关依赖

        
            com.alibaba.cloud
            spring-cloud-alibaba-sentinel-gateway
        

                

注入bean实例

@Configuration
public class GatewayConfiguration {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }   //注入SentinelGatewayBlockExceptionHandler实例,处理限流异常(block exception)

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }   //注入SentinelGatewayFilter实例,处理网关请求
}

             

application.yml:定义route维度数据

spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          lower-case-service-id: true
      routes:
        # Add your routes here.
        - id: product_route
          uri: lb://product
          predicates:
            - Path=/product/**
        - id: httpbin_route
          uri: https://httpbin.org
          predicates:
            - Path=/httpbin/**
          filters:
            - RewritePath=/httpbin/(?.*), /$\{segment}

           

自定义api分组

private void initCustomizedApis() {
    Set definitions = new HashSet<>();
    ApiDefinition api1 = new ApiDefinition("some_customized_api")
        .setPredicateItems(new HashSet() {{
            add(new ApiPathPredicateItem().setPattern("/product/baz"));
            add(new ApiPathPredicateItem().setPattern("/product/foo/**")
                .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_PREFIX));
        }});
    ApiDefinition api2 = new ApiDefinition("another_customized_api")
        .setPredicateItems(new HashSet() {{
            add(new ApiPathPredicateItem().setPattern("/ahas"));
        }});
    definitions.add(api1);
    definitions.add(api2);
    GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}

            

sentinel处理说明

# sentinel 限流资源
route ID:product_route、httpbin_route
API name:some_customized_api、another_customized_api
说明:Spring Cloud Gateway可能会在route前面拼一个前缀,
     如ReactiveCompositeDiscoveryClient_xxx

# URL为http://localhost:8090/product/foo/22
统计到product_route、some_customized_api资源上面

# url:http://localhost:8090/httpbin/json
统计到httpbin_route资源上面

          

GatewayCallbackManager:注册回调,自定义限流处理

public final class GatewayCallbackManager {
    private static final Function DEFAULT_ORIGIN_PARSER = (w) -> {
        return "";
    };
    private static volatile BlockRequestHandler blockHandler = new DefaultBlockRequestHandler();
    private static volatile Function requestOriginParser;

    public static BlockRequestHandler getBlockHandler() {
        return blockHandler;
    }

    public static void resetBlockHandler() {
        blockHandler = new DefaultBlockRequestHandler();
    }

    public static void setBlockHandler(BlockRequestHandler blockHandler) {
        AssertUtil.notNull(blockHandler, "blockHandler cannot be null");
        GatewayCallbackManager.blockHandler = blockHandler;
    }   //网关请求被限流后,自定义的处理操作,默认实现为DefaultBlockRequestHandler,抛出异常信息

    public static Function getRequestOriginParser() {
        return requestOriginParser;
    }

    public static void resetRequestOriginParser() {
        requestOriginParser = DEFAULT_ORIGIN_PARSER;
    }

    public static void setRequestOriginParser(Function requestOriginParser) {
        AssertUtil.notNull(requestOriginParser, "requestOriginParser cannot be null");
        GatewayCallbackManager.requestOriginParser = requestOriginParser;
    }

    private GatewayCallbackManager() {
    }

    static {
        requestOriginParser = DEFAULT_ORIGIN_PARSER;
    }
}

           

注意事项

# 网关流控粒度
sentinel网关流控粒度是 route、API维度,默认不支持 URL 粒度
若通过Spring Cloud Alibaba接入,请将spring.cloud.sentinel.filter.enabled配置项置为 false(若在网关流控控制台上看到了 URL 资源,就是此配置项没有置为 false)

# 网关规则持久化(数据源模块)
若使用Spring Cloud Alibaba Sentinel数据源模块,需要注意网关流控规则数据源类型是gw-flow,
若将网关流控规则数据源指定为flow则不生效

             

             

                                     

相关类与接口

     

SentinelGatewayConstants

public final class SentinelGatewayConstants {
    public static final int APP_TYPE_GATEWAY = 1;
    public static final int RESOURCE_MODE_ROUTE_ID = 0;
    public static final int RESOURCE_MODE_CUSTOM_API_NAME = 1;
    public static final int PARAM_PARSE_STRATEGY_CLIENT_IP = 0;
    public static final int PARAM_PARSE_STRATEGY_HOST = 1;
    public static final int PARAM_PARSE_STRATEGY_HEADER = 2;
    public static final int PARAM_PARSE_STRATEGY_URL_PARAM = 3;
    public static final int PARAM_PARSE_STRATEGY_COOKIE = 4;
    public static final int URL_MATCH_STRATEGY_EXACT = 0;
    public static final int URL_MATCH_STRATEGY_PREFIX = 1;
    public static final int URL_MATCH_STRATEGY_REGEX = 2;
    public static final int PARAM_MATCH_STRATEGY_EXACT = 0;
    public static final int PARAM_MATCH_STRATEGY_PREFIX = 1;
    public static final int PARAM_MATCH_STRATEGY_REGEX = 2;
    public static final int PARAM_MATCH_STRATEGY_CONTAINS = 3;
    public static final String GATEWAY_CONTEXT_DEFAULT = "sentinel_gateway_context_default";
    public static final String GATEWAY_CONTEXT_PREFIX = "sentinel_gateway_context$$";
    public static final String GATEWAY_CONTEXT_ROUTE_PREFIX = "sentinel_gateway_context$$route$$";
    public static final String GATEWAY_NOT_MATCH_PARAM = "$NM";
    public static final String GATEWAY_DEFAULT_PARAM = "$D";

    private SentinelGatewayConstants() {
    }
}

                 

SentinelGatewayProperties

@ConfigurationProperties(
    prefix = "spring.cloud.sentinel.scg"
)
public class SentinelGatewayProperties {
    @NestedConfigurationProperty
    private FallbackProperties fallback;
    private Integer order = -2147483648;

    public SentinelGatewayProperties() {
    }

    public FallbackProperties getFallback() {
        return this.fallback;
    }

    public SentinelGatewayProperties setFallback(FallbackProperties fallback) {
        this.fallback = fallback;
        return this;
    }

    public Integer getOrder() {
        return this.order;
    }

    public void setOrder(Integer order) {
        this.order = order;
    }
}

           

FallbackProperties

public class FallbackProperties {
    private String mode;
    private String redirect;
    private String responseBody;
    private Integer responseStatus;
    private String contentType;

    public FallbackProperties() {
        this.responseStatus = HttpStatus.TOO_MANY_REQUESTS.value();
        this.contentType = MediaType.APPLICATION_JSON.toString();
    }

              

GatewayApiDefinitionManager

public final class GatewayApiDefinitionManager {
    private static final Map API_MAP = new ConcurrentHashMap();
    private static final GatewayApiDefinitionManager.ApiDefinitionPropertyListener LISTENER = new GatewayApiDefinitionManager.ApiDefinitionPropertyListener();
    private static SentinelProperty> currentProperty = new DynamicSentinelProperty();
    private static final Map API_CHANGE_OBSERVERS = new ConcurrentHashMap();

    public GatewayApiDefinitionManager() {
    }

    private static void initializeApiChangeObserverSpi() {
        List listeners = SpiLoader.loadInstanceList(ApiDefinitionChangeObserver.class);
        Iterator var1 = listeners.iterator();

        while(var1.hasNext()) {
            ApiDefinitionChangeObserver e = (ApiDefinitionChangeObserver)var1.next();
            API_CHANGE_OBSERVERS.put(e.getClass().getCanonicalName(), e);
            RecordLog.info("[GatewayApiDefinitionManager] ApiDefinitionChangeObserver added: " + e.getClass().getCanonicalName(), new Object[0]);
        }

    }

    public static void register2Property(SentinelProperty> property) {
        AssertUtil.notNull(property, "property cannot be null");
        synchronized(LISTENER) {
            RecordLog.info("[GatewayApiDefinitionManager] Registering new property to gateway API definition manager", new Object[0]);
            currentProperty.removeListener(LISTENER);
            property.addListener(LISTENER);
            currentProperty = property;
        }
    }

    public static boolean loadApiDefinitions(Set apiDefinitions) {
                          //加载api资源
        return currentProperty.updateValue(apiDefinitions);
    }

    public static ApiDefinition getApiDefinition(String apiName) {
        return apiName == null ? null : (ApiDefinition)API_MAP.get(apiName);
    }

    public static Set getApiDefinitions() {
        return new HashSet(API_MAP.values());
    }

    private static void notifyDownstreamListeners(Set definitions) {
        try {
            Iterator var1 = API_CHANGE_OBSERVERS.entrySet().iterator();

            while(var1.hasNext()) {
                Entry entry = (Entry)var1.next();
                ((ApiDefinitionChangeObserver)entry.getValue()).onChange(definitions);
            }
        } catch (Exception var3) {
            RecordLog.warn("[GatewayApiDefinitionManager] WARN: failed to notify downstream api listeners", var3);
        }

    }

    public static boolean isValidApi(ApiDefinition apiDefinition) {
        return apiDefinition != null && StringUtil.isNotBlank(apiDefinition.getApiName()) && apiDefinition.getPredicateItems() != null;
    }

    static void addApiChangeListener(ApiDefinitionChangeObserver listener) {
        AssertUtil.notNull(listener, "listener cannot be null");
        API_CHANGE_OBSERVERS.put(listener.getClass().getCanonicalName(), listener);
    }

    static void removeApiChangeListener(Class clazz) {
        AssertUtil.notNull(clazz, "class cannot be null");
        API_CHANGE_OBSERVERS.remove(clazz.getCanonicalName());
    }

    static {
        try {
            currentProperty.addListener(LISTENER);
            initializeApiChangeObserverSpi();
        } catch (Throwable var1) {
            RecordLog.warn("[GatewayApiDefinitionManager] Failed to initialize", var1);
            var1.printStackTrace();
        }

    }


***********
内部类:ApiDefinitionPropertyListener

    private static final class ApiDefinitionPropertyListener implements PropertyListener> {
        private ApiDefinitionPropertyListener() {
        }

        public void configUpdate(Set set) {
            applyApiUpdateInternal(set);
            RecordLog.info("[GatewayApiDefinitionManager] Api definition updated: " + GatewayApiDefinitionManager.API_MAP, new Object[0]);
        }

        public void configLoad(Set set) {
            applyApiUpdateInternal(set);
            RecordLog.info("[GatewayApiDefinitionManager] Api definition loaded: " + GatewayApiDefinitionManager.API_MAP, new Object[0]);
        }

        private static synchronized void applyApiUpdateInternal(Set set) {

                    

ApiDefinition

public class ApiDefinition {
    private String apiName;
    private Set predicateItems;

    public ApiDefinition() {
    }

    public ApiDefinition(String apiName) {
        this.apiName = apiName;
    }

    public ApiDefinition setApiName(String apiName) {
    public ApiDefinition setPredicateItems(Set predicateItems) {

    public String getApiName() {
    public Set getPredicateItems() {

    public boolean equals(Object o) {
    public int hashCode() {
    public String toString() {

          

ApiPredicateItem

public interface ApiPredicateItem {
}

          

ApiPathPredicateItem

public class ApiPathPredicateItem implements ApiPredicateItem {
    private String pattern;
    private int matchStrategy = 0;

    public ApiPathPredicateItem() {
    }

    public ApiPathPredicateItem setPattern(String pattern) {
    public ApiPathPredicateItem setMatchStrategy(int matchStrategy) {

    public String getPattern() {
    public int getMatchStrategy() {

    public boolean equals(Object o) {
    public int hashCode() {
    public String toString() {

             

ApiPredicateGroupItem

public class ApiPredicateGroupItem implements ApiPredicateItem {
    private final Set items = new HashSet();

    public ApiPredicateGroupItem() {
    }

    public ApiPredicateGroupItem addItem(ApiPredicateItem item) {
        AssertUtil.notNull(item, "item cannot be null");
        this.items.add(item);
        return this;
    }

    public Set getItems() {
        return this.items;
    }
}

           

                   

                                     

使用示例

   

************

网关应用

         

                             sentinel 网关限流_第3张图片

           

application.yml

spring:
  application:
    name: nacos-gateway
  cloud:
    gateway:
      routes:
        - id: hello
          uri: http://localhost:8081
          predicates:
            - Path=/service/hello
        - id: hello2
          uri: http://localhost:8081
          predicates:
            - Path=/service/hello2
        - id: test
          uri: http://localhost:8081
          predicates:
            - Path=/service/test
        - id: test2
          uri: http://localhost:8081
          predicates:
            - Path=/service/test2

           

CustomApiDefinitionConfig

public class CustomApiDefinitionConfig implements InitFunc {

    @Override
    public void init() throws Exception {
        Set definitions = new HashSet<>();
        ApiDefinition api1 = new ApiDefinition("hello-service")
                .setPredicateItems(new HashSet() {{
                    add(new ApiPathPredicateItem().setPattern("/hello"));
                    add(new ApiPathPredicateItem().setPattern("/hello2/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        definitions.add(api1);

        ApiDefinition api2 = new ApiDefinition("test-service")
                .setPredicateItems(new HashSet() {{
                    add(new ApiPathPredicateItem().setPattern("/test"));
                    add(new ApiPathPredicateItem().setPattern("/test2/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        definitions.add(api2);

        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }
}

           

CustomGatewayFlowRule

public class CustomGatewayFlowRule implements InitFunc {
 
    @Override
    public void init() throws Exception {
        Set rules = new HashSet<>();
        
        rules.add(new GatewayFlowRule("hello")
                .setCount(1).setIntervalSec(1));

        rules.add(new GatewayFlowRule("hello2")
                .setCount(1).setIntervalSec(1).setBurst(1)
                .setParamItem(new GatewayParamFlowItem()
                        .setFieldName("name")
                        .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
                        .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_EXACT)
                ));

        rules.add(new GatewayFlowRule("test")
                .setCount(1).setIntervalSec(1));

        rules.add(new GatewayFlowRule("test2")
                .setCount(1).setIntervalSec(1)
                .setParamItem(new GatewayParamFlowItem()
                        .setFieldName("age")
                        .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
                        .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_EXACT)
                ));
        
        rules.add(new GatewayFlowRule("hello-service")
                .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
                .setCount(1).setIntervalSec(1)
                .setParamItem(new GatewayParamFlowItem()
                        .setFieldName("name")
                        .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
                        .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_EXACT)
                ));

        rules.add(new GatewayFlowRule("test-service")
                .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
                .setCount(1).setIntervalSec(1)
                .setParamItem(new GatewayParamFlowItem()
                        .setFieldName("age")
                        .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
                        .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_EXACT)
                ));

        GatewayRuleManager.loadRules(rules);
    }
}

           

************

后端服务

     

                             sentinel 网关限流_第4张图片

           

application.properties

# 应用名称
spring.application.name=demo

# 应用服务 WEB 访问端口
server.port=8081

         

HelloController

@RestController
@RequestMapping("/service")
public class HelloController {

    @RequestMapping("/hello")
    public String hello(){
        System.out.println("hello");
        return "hello";
    }

    @RequestMapping("/hello2")
    public String hello2(String name){
        System.out.println("hello2 "+name);
        return "hello2 "+name;
    }

    @RequestMapping("/test")
    public String test(){
        return "test";
    }

    @RequestMapping("/test2")
    public String test2(Integer age){
        return "test2 "+age;
    }
}

            

************

本地限流配置

  

META-INF/services/com.alibaba.csp.sentinel.initFunc

com.example.demo.config.CustomGatewayFlowRule
com.example.demo.config.CustomApiDefinitionConfig

           

jmeter 测试

             sentinel 网关限流_第5张图片

            

 localhost:8080/service/hello

             sentinel 网关限流_第6张图片             sentinel 网关限流_第7张图片

             sentinel 网关限流_第8张图片

             

 localhost:8080/service/hello2?name=gtlx

             sentinel 网关限流_第9张图片

             sentinel 网关限流_第10张图片

             sentinel 网关限流_第11张图片

             

************

控制台限流配置

  

请求链路

             sentinel 网关限流_第12张图片

            

api管理

             sentinel 网关限流_第13张图片 

             sentinel 网关限流_第14张图片 

        

流控规则

             sentinel 网关限流_第15张图片

             sentinel 网关限流_第16张图片

          

jmeter测试

             sentinel 网关限流_第17张图片

            

localhost:8080/service/test

             sentinel 网关限流_第18张图片

             sentinel 网关限流_第19张图片

             sentinel 网关限流_第20张图片 

            

localhost:8080/service/test2?age=20

             sentinel 网关限流_第21张图片

              sentinel 网关限流_第22张图片

              sentinel 网关限流_第23张图片 

                

                      

你可能感兴趣的:(spring,cloud,alibaba,sentinel,sentinel)