Pārlūkot izejas kodu

Refactor API gateway common module to separate converted rules from other rule managers

- Separate converted parameter rules from ParamFlowManager. Now the converted rules will be kept in GatewayRuleManager directly.
- Add a GatewayFlowSlot to do separate flow checking for generated rules.
- Refactor rule converting mechanism: now gateway rules in normal mode (without parameter) will also be converted to a parameter flow rule. The index will be the last (the last position). In GatewayParamParser we put a constant value to the last position.

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao pirms 5 gadiem
vecāks
revīzija
ae0b8a5c74
10 mainītis faili ar 464 papildinājumiem un 29 dzēšanām
  1. +10
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/pom.xml
  2. +1
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/SentinelGatewayConstants.java
  3. +8
    -1
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/param/GatewayParamParser.java
  4. +11
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/rule/GatewayRuleConverter.java
  5. +92
    -24
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/rule/GatewayRuleManager.java
  6. +75
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewayFlowSlot.java
  7. +57
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewaySlotChainBuilder.java
  8. +1
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder
  9. +205
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/common/param/GatewayParamParserTest.java
  10. +4
    -4
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/common/rule/GatewayRuleManagerTest.java

+ 10
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/pom.xml Parādīt failu

@@ -37,5 +37,15 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

+ 1
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/SentinelGatewayConstants.java Parādīt failu

@@ -40,6 +40,7 @@ public final class SentinelGatewayConstants {
public static final String GATEWAY_CONTEXT_ROUTE_PREFIX = "sentinel_gateway_context$$route$$";

public static final String GATEWAY_NOT_MATCH_PARAM = "$$not_match";
public static final String GATEWAY_DEFAULT_PARAM = "$D";

private SentinelGatewayConstants() {}
}

+ 8
- 1
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/param/GatewayParamParser.java Parādīt failu

@@ -53,10 +53,13 @@ public class GatewayParamParser<T> {
}
Set<GatewayFlowRule> gatewayRules = new HashSet<>();
Set<Boolean> predSet = new HashSet<>();
boolean hasNonParamRule = false;
for (GatewayFlowRule rule : GatewayRuleManager.getRulesForResource(resource)) {
if (rule.getParamItem() != null) {
gatewayRules.add(rule);
predSet.add(rulePredicate.test(rule));
} else {
hasNonParamRule = true;
}
}
if (gatewayRules.isEmpty()) {
@@ -65,13 +68,17 @@ public class GatewayParamParser<T> {
if (predSet.size() != 1 || predSet.contains(false)) {
return new Object[0];
}
Object[] arr = new Object[gatewayRules.size()];
int size = hasNonParamRule ? gatewayRules.size() + 1 : gatewayRules.size();
Object[] arr = new Object[size];
for (GatewayFlowRule rule : gatewayRules) {
GatewayParamFlowItem paramItem = rule.getParamItem();
int idx = paramItem.getIndex();
String param = parseInternal(paramItem, request);
arr[idx] = param;
}
if (hasNonParamRule) {
arr[size - 1] = SentinelGatewayConstants.GATEWAY_DEFAULT_PARAM;
}
return arr;
}



+ 11
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/rule/GatewayRuleConverter.java Parādīt failu

@@ -32,6 +32,17 @@ final class GatewayRuleConverter {
.setMaxQueueingTimeMs(rule.getMaxQueueingTimeoutMs());
}

static ParamFlowRule applyNonParamToParamRule(/*@Valid*/ GatewayFlowRule gatewayRule, int idx) {
return new ParamFlowRule(gatewayRule.getResource())
.setCount(gatewayRule.getCount())
.setGrade(gatewayRule.getGrade())
.setDurationInSec(gatewayRule.getIntervalSec())
.setBurstCount(gatewayRule.getBurst())
.setControlBehavior(gatewayRule.getControlBehavior())
.setMaxQueueingTimeMs(gatewayRule.getMaxQueueingTimeoutMs())
.setParamIdx(idx);
}

/**
* Convert a gateway rule to parameter flow rule, then apply the generated
* parameter index to {@link GatewayParamFlowItem} of the rule.


+ 92
- 24
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/rule/GatewayRuleManager.java Parādīt failu

@@ -29,10 +29,9 @@ import com.alibaba.csp.sentinel.property.DynamicSentinelProperty;
import com.alibaba.csp.sentinel.property.PropertyListener;
import com.alibaba.csp.sentinel.property.SentinelProperty;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleUtil;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.util.StringUtil;

@@ -42,7 +41,12 @@ import com.alibaba.csp.sentinel.util.StringUtil;
*/
public final class GatewayRuleManager {

private static final Map<String, Set<GatewayFlowRule>> RULE_MAP = new ConcurrentHashMap<>();
/**
* Gateway flow rule map: (resource, [rules...])
*/
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 GatewayRulePropertyListener LISTENER = new GatewayRulePropertyListener();
private static SentinelProperty<Set<GatewayFlowRule>> currentProperty = new DynamicSentinelProperty<>();
@@ -74,46 +78,69 @@ public final class GatewayRuleManager {

public static Set<GatewayFlowRule> getRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
for (Set<GatewayFlowRule> ruleSet : RULE_MAP.values()) {
for (Set<GatewayFlowRule> ruleSet : GATEWAY_RULE_MAP.values()) {
rules.addAll(ruleSet);
}
return rules;
}

public static Set<GatewayFlowRule> getRulesForResource(String resourceName) {
AssertUtil.assertNotBlank(resourceName, "resourceName cannot be blank");
Set<GatewayFlowRule> set = RULE_MAP.get(resourceName);
if (StringUtil.isBlank(resourceName)) {
return new HashSet<>();
}
Set<GatewayFlowRule> set = GATEWAY_RULE_MAP.get(resourceName);
if (set == null) {
return new HashSet<>();
}
return new HashSet<>(set);
}

/**
* <p>Get all converted parameter rules.</p>
* <p>Note: caller SHOULD NOT modify the list and rules.</p>
*
* @param resourceName valid resource name
* @return converted parameter rules
*/
public static List<ParamFlowRule> getConvertedParamRules(String resourceName) {
if (StringUtil.isBlank(resourceName)) {
return new ArrayList<>();
}
return CONVERTED_PARAM_RULE_MAP.get(resourceName);
}

private static final class GatewayRulePropertyListener implements PropertyListener<Set<GatewayFlowRule>> {

@Override
public void configUpdate(Set<GatewayFlowRule> conf) {
applyGatewayRuleInternal(conf);
RecordLog.info("[GatewayRuleManager] Gateway flow rules received: " + RULE_MAP);
RecordLog.info("[GatewayRuleManager] Gateway flow rules received: " + GATEWAY_RULE_MAP);
}

@Override
public void configLoad(Set<GatewayFlowRule> conf) {
applyGatewayRuleInternal(conf);
RecordLog.info("[GatewayRuleManager] Gateway flow rules loaded: " + RULE_MAP);
RecordLog.info("[GatewayRuleManager] Gateway flow rules loaded: " + GATEWAY_RULE_MAP);
}

private int getIdxInternal(Map<String, Integer> idxMap, String resourceName) {
// Prepare index map.
if (!idxMap.containsKey(resourceName)) {
idxMap.put(resourceName, 0);
}
return idxMap.get(resourceName);
}

private synchronized void applyGatewayRuleInternal(Set<GatewayFlowRule> conf) {
if (conf == null || conf.isEmpty()) {
FlowRuleManager.loadRules(new ArrayList<FlowRule>());
ParamFlowRuleManager.loadRules(new ArrayList<ParamFlowRule>());
RULE_MAP.clear();
applyToConvertedParamMap(new HashSet<ParamFlowRule>());
GATEWAY_RULE_MAP.clear();
return;
}
Map<String, Set<GatewayFlowRule>> gatewayRuleMap = new ConcurrentHashMap<>();
Map<String, Integer> idxMap = new HashMap<>();
List<FlowRule> flowRules = new ArrayList<>();
Set<ParamFlowRule> paramFlowRules = new HashSet<>();
Map<String, List<GatewayFlowRule>> noParamMap = new HashMap<>();

for (GatewayFlowRule rule : conf) {
if (!isValidRule(rule)) {
@@ -122,14 +149,15 @@ public final class GatewayRuleManager {
}
String resourceName = rule.getResource();
if (rule.getParamItem() == null) {
// If param item is absent, it will be converted to normal flow rule.
flowRules.add(GatewayRuleConverter.toFlowRule(rule));
} else {
// Prepare index map.
if (!idxMap.containsKey(resourceName)) {
idxMap.put(resourceName, 0);
// Cache the rules with no parameter config, then skip.
List<GatewayFlowRule> noParamList = noParamMap.get(resourceName);
if (noParamList == null) {
noParamList = new ArrayList<>();
noParamMap.put(resourceName, noParamList);
}
int idx = idxMap.get(resourceName);
noParamList.add(rule);
} else {
int idx = getIdxInternal(idxMap, resourceName);
// Convert to parameter flow rule.
if (paramFlowRules.add(GatewayRuleConverter.applyToParamRule(rule, idx))) {
idxMap.put(rule.getResource(), idx + 1);
@@ -143,11 +171,51 @@ public final class GatewayRuleManager {
}
ruleSet.add(rule);
}
FlowRuleManager.loadRules(flowRules);
ParamFlowRuleManager.loadRules(new ArrayList<>(paramFlowRules));
// Handle non-param mode rules.
for (Map.Entry<String, List<GatewayFlowRule>> e : noParamMap.entrySet()) {
List<GatewayFlowRule> rules = e.getValue();
if (rules == null || rules.isEmpty()) {
continue;
}
for (GatewayFlowRule rule : rules) {
int idx = getIdxInternal(idxMap, e.getKey());
// Always use the same index (the last position).
paramFlowRules.add(GatewayRuleConverter.applyNonParamToParamRule(rule, idx));
}
}

applyToConvertedParamMap(paramFlowRules);

GATEWAY_RULE_MAP.clear();
GATEWAY_RULE_MAP.putAll(gatewayRuleMap);
}

private void applyToConvertedParamMap(Set<ParamFlowRule> paramFlowRules) {
Map<String, List<ParamFlowRule>> newRuleMap = ParamFlowRuleUtil.buildParamRuleMap(
new ArrayList<>(paramFlowRules));
if (newRuleMap == null || newRuleMap.isEmpty()) {
// No parameter flow rules, so clear all the metrics.
for (String resource : CONVERTED_PARAM_RULE_MAP.keySet()) {
ParameterMetricStorage.clearParamMetricForResource(resource);
}
RecordLog.info("[GatewayRuleManager] No gateway rules, clearing parameter metrics of previous rules");
CONVERTED_PARAM_RULE_MAP.clear();
return;
}

// Clear unused parameter metrics.
Set<String> previousResources = CONVERTED_PARAM_RULE_MAP.keySet();
for (String resource : previousResources) {
if (!newRuleMap.containsKey(resource)) {
ParameterMetricStorage.clearParamMetricForResource(resource);
}
}

// Apply to converted rule map.
CONVERTED_PARAM_RULE_MAP.clear();
CONVERTED_PARAM_RULE_MAP.putAll(newRuleMap);

RULE_MAP.clear();
RULE_MAP.putAll(gatewayRuleMap);
RecordLog.info("[GatewayRuleManager] Converted internal param rules: " + CONVERTED_PARAM_RULE_MAP);
}
}



+ 75
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewayFlowSlot.java Parādīt failu

@@ -0,0 +1,75 @@
/*
* Copyright 1999-2019 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.adapter.gateway.common.slot;

import java.util.List;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.context.Context;
import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowChecker;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage;

/**
* @author Eric Zhao
* @since 1.6.1
*/
public class GatewayFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
public void entry(Context context, ResourceWrapper resource, DefaultNode node, int count,
boolean prioritized, Object... args) throws Throwable {
checkGatewayParamFlow(resource, count, args);

fireEntry(context, resource, node, count, prioritized, args);
}

private void checkGatewayParamFlow(ResourceWrapper resourceWrapper, int count, Object... args)
throws BlockException {
if (args == null) {
return;
}

List<ParamFlowRule> rules = GatewayRuleManager.getConvertedParamRules(resourceWrapper.getName());
if (rules == null || rules.isEmpty()) {
return;
}

for (ParamFlowRule rule : rules) {
// Initialize the parameter metrics.
ParameterMetricStorage.initParamMetricsFor(resourceWrapper, rule);

if (!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);
}
}
}

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

+ 57
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewaySlotChainBuilder.java Parādīt failu

@@ -0,0 +1,57 @@
/*
* Copyright 1999-2019 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.adapter.gateway.common.slot;

import com.alibaba.csp.sentinel.slotchain.DefaultProcessorSlotChain;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain;
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder;
import com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot;
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot;
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
import com.alibaba.csp.sentinel.slots.logger.LogSlot;
import com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot;
import com.alibaba.csp.sentinel.slots.statistic.StatisticSlot;
import com.alibaba.csp.sentinel.slots.system.SystemSlot;

/**
* @author Eric Zhao
* @since 1.6.1
*/
public class GatewaySlotChainBuilder implements SlotChainBuilder {

@Override
public ProcessorSlotChain build() {
ProcessorSlotChain chain = new DefaultProcessorSlotChain();
// Prepare slot
chain.addLast(new NodeSelectorSlot());
chain.addLast(new ClusterBuilderSlot());
// Stat slot
chain.addLast(new LogSlot());
chain.addLast(new StatisticSlot());
// Rule checking slot
chain.addLast(new AuthoritySlot());
chain.addLast(new SystemSlot());
chain.addLast(new GatewayFlowSlot());

chain.addLast(new ParamFlowSlot());
chain.addLast(new FlowSlot());
chain.addLast(new DegradeSlot());

return chain;
}
}

+ 1
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder Parādīt failu

@@ -0,0 +1 @@
com.alibaba.csp.sentinel.adapter.gateway.common.slot.GatewaySlotChainBuilder

+ 205
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/common/param/GatewayParamParserTest.java Parādīt failu

@@ -0,0 +1,205 @@
/*
* Copyright 1999-2019 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.adapter.gateway.common.param;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayParamFlowItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.util.function.Predicate;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* @author Eric Zhao
*/
@SuppressWarnings("unchecked")
public class GatewayParamParserTest {

private final Predicate<GatewayFlowRule> routeIdPredicate = new Predicate<GatewayFlowRule>() {
@Override
public boolean test(GatewayFlowRule e) {
return e.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID;
}
};
private final Predicate<GatewayFlowRule> apiNamePredicate = new Predicate<GatewayFlowRule>() {
@Override
public boolean test(GatewayFlowRule e) {
return e.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME;
}
};

@Test
public void testParseParametersNoParamItem() {
RequestItemParser<Object> itemParser = mock(RequestItemParser.class);
GatewayParamParser<Object> parser = new GatewayParamParser<>(itemParser);
// Create a fake request.
Object request = new Object();
// Prepare gateway rules.
Set<GatewayFlowRule> rules = new HashSet<>();
String routeId1 = "my_test_route_A";
rules.add(new GatewayFlowRule(routeId1)
.setCount(5)
.setIntervalSec(1)
);
GatewayRuleManager.loadRules(rules);

Object[] params = parser.parseParameterFor(routeId1, request, routeIdPredicate);
assertThat(params.length).isZero();
}

@Test
public void testParseParametersWithItems() {
RequestItemParser<Object> itemParser = mock(RequestItemParser.class);
GatewayParamParser<Object> paramParser = new GatewayParamParser<>(itemParser);
// Create a fake request.
Object request = new Object();

// Prepare gateway rules.
Set<GatewayFlowRule> rules = new HashSet<>();
final String routeId1 = "my_test_route_A";
final String api1 = "my_test_route_B";
final String headerName = "X-Sentinel-Flag";
final String paramName = "p";
GatewayFlowRule routeRuleNoParam = new GatewayFlowRule(routeId1)
.setCount(10)
.setIntervalSec(10);
GatewayFlowRule routeRule1 = new GatewayFlowRule(routeId1)
.setCount(2)
.setIntervalSec(2)
.setBurst(2)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_CLIENT_IP)
);
GatewayFlowRule routeRule2 = new GatewayFlowRule(routeId1)
.setCount(10)
.setIntervalSec(1)
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)
.setMaxQueueingTimeoutMs(600)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER)
.setFieldName(headerName)
);
GatewayFlowRule routeRule3 = new GatewayFlowRule(routeId1)
.setCount(20)
.setIntervalSec(1)
.setBurst(5)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName(paramName)
);
GatewayFlowRule routeRule4 = new GatewayFlowRule(routeId1)
.setCount(120)
.setIntervalSec(10)
.setBurst(30)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HOST)
);
GatewayFlowRule apiRule1 = new GatewayFlowRule(api1)
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setCount(5)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName(paramName)
);
rules.add(routeRule1);
rules.add(routeRule2);
rules.add(routeRule3);
rules.add(routeRule4);
rules.add(routeRuleNoParam);
rules.add(apiRule1);
GatewayRuleManager.loadRules(rules);

final String expectedHost = "hello.test.sentinel";
final String expectedAddress = "66.77.88.99";
final String expectedHeaderValue1 = "Sentinel";
final String expectedUrlParamValue1 = "17";
mockClientHostAddress(itemParser, expectedAddress);
Map<String, String> expectedHeaders = new HashMap<String, String>() {{
put(headerName, expectedHeaderValue1); put("Host", expectedHost);
}};
mockHeaders(itemParser, expectedHeaders);
mockSingleUrlParam(itemParser, paramName, expectedUrlParamValue1);
Object[] params = paramParser.parseParameterFor(routeId1, request, routeIdPredicate);
// Param length should be 5 (4 with parameters, 1 normal flow with generated constant)
assertThat(params.length).isEqualTo(5);
assertThat(params[routeRule1.getParamItem().getIndex()]).isEqualTo(expectedAddress);
assertThat(params[routeRule2.getParamItem().getIndex()]).isEqualTo(expectedHeaderValue1);
assertThat(params[routeRule3.getParamItem().getIndex()]).isEqualTo(expectedUrlParamValue1);
assertThat(params[routeRule4.getParamItem().getIndex()]).isEqualTo(expectedHost);
assertThat(params[params.length - 1]).isEqualTo(SentinelGatewayConstants.GATEWAY_DEFAULT_PARAM);

assertThat(paramParser.parseParameterFor(api1, request, routeIdPredicate).length).isZero();

String expectedUrlParamValue2 = "fs";
mockSingleUrlParam(itemParser, paramName, expectedUrlParamValue2);
params = paramParser.parseParameterFor(api1, request, apiNamePredicate);
assertThat(params.length).isEqualTo(1);
assertThat(params[apiRule1.getParamItem().getIndex()]).isEqualTo(expectedUrlParamValue2);
}

private void mockClientHostAddress(/*@Mock*/ RequestItemParser parser, String address) {
when(parser.getRemoteAddress(any())).thenReturn(address);
}

private void mockHeaders(/*@Mock*/ RequestItemParser parser, Map<String, String> headerMap) {
for (Map.Entry<String, String> e : headerMap.entrySet()) {
when(parser.getHeader(any(), eq(e.getKey()))).thenReturn(e.getValue());
}
}

private void mockUrlParams(/*@Mock*/ RequestItemParser parser, Map<String, String> paramMap) {
for (Map.Entry<String, String> e : paramMap.entrySet()) {
when(parser.getUrlParam(any(), eq(e.getKey()))).thenReturn(e.getValue());
}
}

private void mockSingleUrlParam(/*@Mock*/ RequestItemParser parser, String key, String value) {
when(parser.getUrlParam(any(), eq(key))).thenReturn(value);
}

private void mockSingleHeader(/*@Mock*/ RequestItemParser parser, String key, String value) {
when(parser.getHeader(any(), eq(key))).thenReturn(value);
}

@Before
public void setUp() {
GatewayApiDefinitionManager.loadApiDefinitions(new HashSet<ApiDefinition>());
GatewayRuleManager.loadRules(new HashSet<GatewayFlowRule>());
}

@After
public void tearDown() {
GatewayApiDefinitionManager.loadApiDefinitions(new HashSet<ApiDefinition>());
GatewayRuleManager.loadRules(new HashSet<GatewayFlowRule>());
}
}

+ 4
- 4
sentinel-adapter/sentinel-api-gateway-adapter-common/src/test/java/com/alibaba/csp/sentinel/adapter/gateway/common/rule/GatewayRuleManagerTest.java Parādīt failu

@@ -16,12 +16,12 @@
package com.alibaba.csp.sentinel.adapter.gateway.common.rule;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;

import org.junit.After;
import org.junit.Before;
@@ -62,8 +62,8 @@ public class GatewayRuleManagerTest {
rules.add(rule3);
GatewayRuleManager.loadRules(rules);

assertTrue(FlowRuleManager.hasConfig(ahasRoute));
assertTrue(ParamFlowRuleManager.hasRules(ahasRoute));
List<ParamFlowRule> convertedRules = GatewayRuleManager.getConvertedParamRules(ahasRoute);
assertNotNull(convertedRules);
assertEquals(0, (int)rule2.getParamItem().getIndex());
assertEquals(0, (int)rule3.getParamItem().getIndex());
assertTrue(GatewayRuleManager.getRulesForResource(ahasRoute).contains(rule1));


Notiek ielāde…
Atcelt
Saglabāt