sentinel 网关限流


sentinel 网关限流

        

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

                

                       

                                     

网关限流

        

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

                  

          

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

实现原理

            

                  

网关流控规则处理

# 规则加载
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<String, Set<GatewayFlowRule>> GATEWAY_RULE_MAP = new ConcurrentHashMap();
    private static final Map<String, List<ParamFlowRule>> CONVERTED_PARAM_RULE_MAP = new ConcurrentHashMap();
    private static final GatewayRuleManager.GatewayRulePropertyListener LISTENER = new GatewayRuleManager.GatewayRulePropertyListener();
    private static SentinelProperty<Set<GatewayFlowRule>> currentProperty = new DynamicSentinelProperty();
    private static final Set<Integer> FIELD_REQUIRED_SET;

    public static void register2Property(SentinelProperty<Set<GatewayFlowRule>> 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<GatewayFlowRule> rules) {
        return currentProperty.updateValue(rules);
    }

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

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

        return rules;
    }

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

    public static List<ParamFlowRule> 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<Set<GatewayFlowRule>> {
        private GatewayRulePropertyListener() {
        }

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

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

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

SentinelGatewayFilter:处理网关请求

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

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

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

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Route route = (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        Mono<Void> 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<String> 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<String> 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<DefaultNode> {
    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<ParamFlowRule> 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分组

             

相关依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>

                

注入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>.*), /$\{segment}

           

自定义api分组

private void initCustomizedApis() {
    Set<ApiDefinition> definitions = new HashSet<>();
    ApiDefinition api1 = new ApiDefinition("some_customized_api")
        .setPredicateItems(new HashSet<ApiPredicateItem>() {{
            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<ApiPredicateItem>() {{
            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<ServerWebExchange, String> DEFAULT_ORIGIN_PARSER = (w) -> {
        return "";
    };
    private static volatile BlockRequestHandler blockHandler = new DefaultBlockRequestHandler();
    private static volatile Function<ServerWebExchange, String> 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<ServerWebExchange, String> getRequestOriginParser() {
        return requestOriginParser;
    }

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

    public static void setRequestOriginParser(Function<ServerWebExchange, String> 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<String, ApiDefinition> API_MAP = new ConcurrentHashMap();
    private static final GatewayApiDefinitionManager.ApiDefinitionPropertyListener LISTENER = new GatewayApiDefinitionManager.ApiDefinitionPropertyListener();
    private static SentinelProperty<Set<ApiDefinition>> currentProperty = new DynamicSentinelProperty();
    private static final Map<String, ApiDefinitionChangeObserver> API_CHANGE_OBSERVERS = new ConcurrentHashMap();

    public GatewayApiDefinitionManager() {
    }

    private static void initializeApiChangeObserverSpi() {
        List<ApiDefinitionChangeObserver> 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<Set<ApiDefinition>> 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<ApiDefinition> apiDefinitions) {
                          //加载api资源
        return currentProperty.updateValue(apiDefinitions);
    }

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

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

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

            while(var1.hasNext()) {
                Entry<?, ApiDefinitionChangeObserver> 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<Set<ApiDefinition>> {
        private ApiDefinitionPropertyListener() {
        }

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

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

        private static synchronized void applyApiUpdateInternal(Set<ApiDefinition> set) {

                    

ApiDefinition

public class ApiDefinition {
    private String apiName;
    private Set<ApiPredicateItem> predicateItems;

    public ApiDefinition() {
    }

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

    public ApiDefinition setApiName(String apiName) {
    public ApiDefinition setPredicateItems(Set<ApiPredicateItem> predicateItems) {

    public String getApiName() {
    public Set<ApiPredicateItem> 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<ApiPredicateItem> 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<ApiPredicateItem> getItems() {
        return this.items;
    }
}

           

                   

                                     

使用示例

   

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

网关应用

         

                            

           

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<ApiDefinition> definitions = new HashSet<>();
        ApiDefinition api1 = new ApiDefinition("hello-service")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    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<ApiPredicateItem>() {{
                    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<GatewayFlowRule> 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);
    }
}

           

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

后端服务

     

                            

           

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 测试

            

            

 localhost:8080/service/hello

                         

            

             

 localhost:8080/service/hello2?name=gtlx

            

            

            

             

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

控制台限流配置

  

请求链路

            

            

api管理

              

              

        

流控规则

            

            

          

jmeter测试

            

            

localhost:8080/service/test

            

            

              

            

localhost:8080/service/test2?age=20

            

              

               

                

                      

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Gateway Sentinel是一种关限流技术,它可以在关层面对请求进行限流,防止过多的请求对后端服务造成压力。它可以根据不同的规则对请求进行限制,例如根据IP地址、请求路径、请求参数等进行限制。同时,Gateway Sentinel还可以对请求进行统计和监控,帮助开发人员了解系统的负载情况,及时调整系统配置,保证系统的稳定性和可靠性。 ### 回答2: Gateway sentinel是如今常用的一种关限流技术。其作用和传统的限流技术类似,主要是用来保护服务的可用性和稳定性,避免因过多请求而导致的服务宕机或系统崩溃等问题。但是与传统技术不同的是,Gateway sentinel的限流策略更加精细和灵活,可以根据实际情况进行动态调整,使得限流更加准确和高效。 Gateway sentinel主要有以下几个特点: 一、有多种限流策略可供选择:针对不同的场景和需求,Gateway sentinel提供了多种不同的限流策略,如令牌桶限流、漏桶限流、并发数限流等等。管理员可以根据实际情况选择适合自己的限流策略。 二、支持动态调整:Gateway sentinel可以根据流量的变化动态调整限流策略和参数,使得限流更加准确和高效。同时,还可以根据实时数据进行分析和预测,预判可能出现的问题,提前进行限流和调整,避免系统崩溃。 三、集成了监控和报警系统:Gateway sentinel不仅可以实现限流功能,还具备监控和报警功能。管理员可以根据需要设置监控指标和报警规则,及时获取系统状态和异常信息,保证系统的可用性和可靠性。 四、易于使用和扩展:Gateway sentinel是一个基于插件架构的限流框架,可以集成在各种不同的Web应用程序和微服务框架中。同时,其还提供了友好的API和文档,方便开发者进行二次开发和定制化。 总之,Gateway sentinel是一种功能强大、灵活性高、易于使用和扩展的关限流技术,对于保障服务的稳定性和可用性有着重要的作用,是现代企业必不可少的一项技术。 ### 回答3: Gateway sentinel关限流是一种防止DDoS攻击的络安全机制,它通过限制络请求的访问频率来保护服务端资源免受过多的请求而崩溃的风险。这种机制可用于所有类型的Web应用程序,包括本地安装的Web应用程序、云服务和SaaS软件。 这项限流工具可以通过对每个请求进行流量监测来识别是否存在异常请求,并采取适当的措施来处理它们。在正常的络流量条件下,所有来自客户端的请求都会在关层进行处理和审核。但如果关层检测到来自一个IP地址的数据包进行了多次重复的无效请求,它就会限制该IP地址的访问频率,以防止它进一步地消耗服务器资源。 此外,关限流机制还可以实时监测络流量,检测和分析异常攻击流量,并将攻击行为数据传递给安全高级性工具,从而加强安全防御体系。 在安装和配置软件之后,管理员可以选择合适的阈值来控制关限流,根据您的需求进行配置,以便确保服务器和络能够在意外高流量流入的情况下顺利运行。 总之,关限流是一种可靠而安全的防御工具,它可以让您的Web应用程序不受攻击,从而保障用户的数据和络安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值