You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2021/01/11 11:14:34 UTC
[servicecomb-java-chassis] 01/07: [SCB-2116]improve algorithm to
match when applying rules
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit da7b7718f493600670076b8418dbb043977ffed4
Author: liubao <bi...@qq.com>
AuthorDate: Wed Dec 30 17:45:45 2020 +0800
[SCB-2116]improve algorithm to match when applying rules
---
.../servicecomb/governance/InvocationContext.java} | 15 +---
.../servicecomb/governance/MatchersManager.java | 57 ++++++++++---
.../governance/marker/GovHttpRequest.java | 20 +++++
.../governance/marker/TrafficMarker.java | 31 +++++++
.../governance/policy/AbstractPolicy.java | 24 ++++--
.../policy/{GovRule.java => GovernanceRule.java} | 42 +++++++++-
.../governance/properties/BulkheadProperties.java | 2 +-
.../properties/CircuitBreakerProperties.java | 2 +-
...ovProperties.java => GovernanceProperties.java} | 19 +++--
.../governance/properties/MatchProperties.java | 7 +-
.../PolicyProperties.java} | 25 ++----
.../governance/properties/RateLimitProperties.java | 2 +-
.../governance/properties/RetryProperties.java | 2 +-
.../governance/service/MatchersService.java | 5 +-
.../MatchersServiceImpl.java} | 46 ++++++-----
.../governance/service/PolicyServiceImpl.java | 6 +-
.../servicecomb/governance/FlowControlTest.java | 94 ++++++++++++++++++++++
...tiesTest.java => GovernancePropertiesTest.java} | 8 +-
...hersService.java => MockInvocationContext.java} | 29 +++++--
19 files changed, 335 insertions(+), 101 deletions(-)
diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockMatchersService.java b/governance/src/main/java/org/apache/servicecomb/governance/InvocationContext.java
similarity index 69%
copy from governance/src/test/java/org/apache/servicecomb/governance/MockMatchersService.java
copy to governance/src/main/java/org/apache/servicecomb/governance/InvocationContext.java
index 1387312..07d03ce 100644
--- a/governance/src/test/java/org/apache/servicecomb/governance/MockMatchersService.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/InvocationContext.java
@@ -17,17 +17,10 @@
package org.apache.servicecomb.governance;
-import java.util.List;
+import java.util.Map;
-import org.springframework.stereotype.Component;
+public interface InvocationContext {
+ Map<String, Boolean> getCalculatedMatches();
-import org.apache.servicecomb.governance.marker.GovHttpRequest;
-import org.apache.servicecomb.governance.service.MatchersService;
-
-@Component
-public class MockMatchersService implements MatchersService {
- @Override
- public List<String> getMatchedNames(GovHttpRequest govHttpRequest) {
- return null;
- }
+ void addMatch(String key, Boolean value);
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java b/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java
index c35c1a1..6a7ec0e 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java
@@ -16,17 +16,18 @@
*/
package org.apache.servicecomb.governance;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
-import org.apache.servicecomb.governance.policy.Policy;
+import org.apache.servicecomb.governance.marker.GovHttpRequest;
+import org.apache.servicecomb.governance.policy.AbstractPolicy;
import org.apache.servicecomb.governance.service.MatchersService;
import org.apache.servicecomb.governance.service.PolicyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
-import org.apache.servicecomb.governance.marker.GovHttpRequest;
-
@Component
public class MatchersManager {
@@ -36,17 +37,49 @@ public class MatchersManager {
@Autowired
private PolicyService policyService;
+ @Autowired
+ private InvocationContext invocationContext;
+
public MatchersManager() {
}
- public Map<String, Policy> match(GovHttpRequest request) {
- /**
- * 1.获取该请求携带的marker
- */
- List<String> marks = matchersService.getMatchedNames(request);
- /**
- * 2.通过 marker获取到所有的policy
- */
- return policyService.getAllPolicies(marks);
+ public <T extends AbstractPolicy> T match(GovHttpRequest request, Map<String, T> policies) {
+ List<T> matchedPolicy = new ArrayList<>();
+ List<String> matchedKeys = new ArrayList<>();
+
+ Map<String, Boolean> calculatedMatches = invocationContext.getCalculatedMatches();
+ calculatedMatches.forEach((k, v) -> {
+ if (v) {
+ matchedKeys.add(k);
+ }
+ });
+
+ for (Entry<String, T> entry : policies.entrySet()) {
+ T policy = entry.getValue();
+
+ if (policy.match(matchedKeys)) {
+ matchedPolicy.add(policy);
+ continue;
+ }
+
+ List<String> parsedMatches = policy.getParsedMatch();
+ if (parsedMatches != null) {
+ parsedMatches.stream().forEach(key -> {
+ if (!calculatedMatches.containsKey(key)) {
+ boolean keyMatch = matchersService.checkMatch(request, key);
+ invocationContext.addMatch(key, keyMatch);
+ if (keyMatch) {
+ matchedPolicy.add(policy);
+ }
+ }
+ });
+ }
+ }
+
+ if (matchedPolicy.size() > 0) {
+ matchedPolicy.sort(AbstractPolicy::compare);
+ return matchedPolicy.get(0);
+ }
+ return null;
}
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovHttpRequest.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovHttpRequest.java
index bc4d9ea..2176ef5 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovHttpRequest.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovHttpRequest.java
@@ -18,7 +18,12 @@ package org.apache.servicecomb.governance.marker;
import java.util.Map;
+import org.springframework.util.Assert;
+
public class GovHttpRequest {
+ private final String serviceName;
+
+ private final String version;
private Map<String, String> headers;
@@ -26,6 +31,21 @@ public class GovHttpRequest {
private String method;
+ public GovHttpRequest(String serviceName, String version) {
+ Assert.notNull(serviceName, "serviceName should not be null");
+ Assert.notNull(version, "version should not be null");
+ this.serviceName = serviceName;
+ this.version = version;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
public Map<String, String> getHeaders() {
return headers;
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java
index ba4cbf7..b64c168 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java
@@ -16,8 +16,11 @@
*/
package org.apache.servicecomb.governance.marker;
+import java.util.Arrays;
import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+
public class TrafficMarker {
private String services;
@@ -39,4 +42,32 @@ public class TrafficMarker {
public void setMatches(List<Matcher> matches) {
this.matches = matches;
}
+
+ public boolean checkMatch(GovHttpRequest govHttpRequest, RequestProcessor requestProcessor, String name) {
+ if (!servicesMatch(govHttpRequest)) {
+ return false;
+ }
+
+ return this.matches.stream().anyMatch(match ->
+ match.getName().equals(name) && requestProcessor.match(govHttpRequest, match));
+ }
+
+
+ private boolean servicesMatch(GovHttpRequest govHttpRequest) {
+ if (StringUtils.isEmpty(services)) {
+ return true;
+ }
+
+ return Arrays.stream(services.split(",")).anyMatch(ser -> {
+ String[] serviceAndVersion = ser.split(":");
+ if (serviceAndVersion.length == 1) {
+ return govHttpRequest.getServiceName().equals(serviceAndVersion[0]);
+ } else if (serviceAndVersion.length == 2) {
+ return govHttpRequest.getServiceName().equals(serviceAndVersion[0]) && govHttpRequest.getVersion()
+ .equals(serviceAndVersion[1]);
+ } else {
+ return false;
+ }
+ });
+ }
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java
index ae47da3..3e496c4 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java
@@ -16,20 +16,19 @@
*/
package org.apache.servicecomb.governance.policy;
-import java.util.Arrays;
import java.util.List;
public abstract class AbstractPolicy implements Policy {
private String name;
- private GovRule rules;
+ private GovernanceRule rules;
- public GovRule getRules() {
+ public GovernanceRule getRules() {
return rules;
}
- public void setRules(GovRule rules) {
+ public void setRules(GovernanceRule rules) {
this.rules = rules;
}
@@ -39,13 +38,24 @@ public abstract class AbstractPolicy implements Policy {
@Override
public boolean match(List<String> items) {
- if (rules == null || rules.getMatch() == null) {
+ if (rules == null) {
return false;
}
+ return items.stream().anyMatch(item -> rules.match(item));
+ }
+
+ public static int compare(AbstractPolicy policy1, AbstractPolicy policy2) {
+ int p1 = policy1.rules == null ? 0 : policy1.rules.getPrecedence();
+ int p2 = policy2.rules == null ? 0 : policy2.rules.getPrecedence();
+ return p1 - p2;
+ }
- List<String> configuredItems = Arrays.asList(rules.getMatch().split(","));
+ public List<String> getParsedMatch() {
+ if (rules == null) {
+ return null;
+ }
- return items.stream().anyMatch(item -> configuredItems.contains(item));
+ return rules.getParsedMatch();
}
@Override
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/GovRule.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceRule.java
similarity index 57%
copy from governance/src/main/java/org/apache/servicecomb/governance/policy/GovRule.java
copy to governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceRule.java
index 58db001..d75b250 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/policy/GovRule.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceRule.java
@@ -17,10 +17,18 @@
package org.apache.servicecomb.governance.policy;
-public class GovRule {
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class GovernanceRule {
+ private static final String MATCH_NONE = "none";
private String match;
+ private List<String> parsedMatch;
+
private int precedence;
public String getMatch() {
@@ -38,4 +46,36 @@ public class GovRule {
public void setPrecedence(int precedence) {
this.precedence = precedence;
}
+
+ public boolean match(String name) {
+ if (StringUtils.isEmpty(this.match)) {
+ return false;
+ }
+
+ if (MATCH_NONE.equals(this.match)) {
+ return true;
+ }
+
+ if (this.parsedMatch == null) {
+ this.parsedMatch = Arrays.asList(this.match.split(","));
+ }
+
+ return parsedMatch.contains(name);
+ }
+
+ public List<String> getParsedMatch() {
+ if (StringUtils.isEmpty(this.match)) {
+ return null;
+ }
+
+ if (MATCH_NONE.equals(this.match)) {
+ return null;
+ }
+
+ if (this.parsedMatch == null) {
+ this.parsedMatch = Arrays.asList(this.match.split(","));
+ }
+
+ return parsedMatch;
+ }
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java
index b61f4d3..2e340b7 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java
@@ -21,7 +21,7 @@ import org.apache.servicecomb.governance.policy.BulkheadPolicy;
import org.springframework.stereotype.Component;
@Component
-public class BulkheadProperties extends GovProperties<BulkheadPolicy> {
+public class BulkheadProperties extends PolicyProperties<BulkheadPolicy> {
public static final String MATCH_BULKHEAD__KEY = "servicecomb.bulkhead";
public BulkheadProperties() {
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java
index 5465f66..578d346 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java
@@ -20,7 +20,7 @@ import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy;
import org.springframework.stereotype.Component;
@Component
-public class CircuitBreakerProperties extends GovProperties<CircuitBreakerPolicy> {
+public class CircuitBreakerProperties extends PolicyProperties<CircuitBreakerPolicy> {
public static final String MATCH_CIRCUITBREAKER_KEY = "servicecomb.circuitBreaker";
public CircuitBreakerProperties() {
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/GovProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceProperties.java
similarity index 91%
rename from governance/src/main/java/org/apache/servicecomb/governance/properties/GovProperties.java
rename to governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceProperties.java
index 3a498e6..ab852eb 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/properties/GovProperties.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceProperties.java
@@ -41,11 +41,12 @@ import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.representer.Representer;
import com.google.common.eventbus.Subscribe;
+
import org.apache.servicecomb.governance.event.ConfigurationChangedEvent;
import org.apache.servicecomb.governance.event.EventManager;
-public abstract class GovProperties<T> implements InitializingBean {
- private static final Logger LOGGER = LoggerFactory.getLogger(GovProperties.class);
+public abstract class GovernanceProperties<T> implements InitializingBean {
+ private static final Logger LOGGER = LoggerFactory.getLogger(GovernanceProperties.class);
private final Representer representer = new Representer();
@@ -58,7 +59,7 @@ public abstract class GovProperties<T> implements InitializingBean {
protected Class<T> entityClass;
- protected GovProperties(String key) {
+ protected GovernanceProperties(String key) {
configKey = key;
representer.getPropertyUtils().setSkipMissingProperties(true);
EventManager.register(this);
@@ -75,7 +76,7 @@ public abstract class GovProperties<T> implements InitializingBean {
for (String key : event.getChangedConfigurations()) {
if (key.startsWith(configKey + ".")) {
// 删除的情况, 从配置文件读取配置。 需要保证 environment 已经刷新配置值。
- T entityItem = parseEntityItem(environment.getProperty(key));
+ T entityItem = parseEntityItem(key, environment.getProperty(key));
String mapKey = key.substring((configKey + ".").length());
if (entityItem == null) {
parsedEntity.remove(mapKey);
@@ -142,7 +143,7 @@ public abstract class GovProperties<T> implements InitializingBean {
Map<String, T> resultMap = new HashMap<>();
for (Entry<String, String> entry : yamlEntity.entrySet()) {
- T marker = parseEntityItem(entry.getValue());
+ T marker = parseEntityItem(entry.getKey(), entry.getValue());
if (marker != null) {
resultMap.put(entry.getKey(), marker);
}
@@ -152,14 +153,18 @@ public abstract class GovProperties<T> implements InitializingBean {
protected abstract Class<T> getEntityClass();
- protected T parseEntityItem(String value) {
+ protected abstract void setName(T value, String key);
+
+ protected T parseEntityItem(String key, String value) {
if (StringUtils.isEmpty(value)) {
return null;
}
try {
Yaml entityParser = new Yaml(new Constructor(new TypeDescription(entityClass, entityClass)), representer);
- return entityParser.loadAs(value, entityClass);
+ T result = entityParser.loadAs(value, entityClass);
+ setName(result, key);
+ return result;
} catch (YAMLException e) {
LOGGER.error("governance config yaml is illegal : {}", e.getMessage());
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java
index c910518..7a2a5ae 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java
@@ -20,7 +20,7 @@ import org.apache.servicecomb.governance.marker.TrafficMarker;
import org.springframework.stereotype.Component;
@Component
-public class MatchProperties extends GovProperties<TrafficMarker> {
+public class MatchProperties extends GovernanceProperties<TrafficMarker> {
public static final String MATCH_POLICY_KEY = "servicecomb.matchGroup";
public MatchProperties() {
@@ -31,4 +31,9 @@ public class MatchProperties extends GovProperties<TrafficMarker> {
public Class<TrafficMarker> getEntityClass() {
return TrafficMarker.class;
}
+
+ @Override
+ protected void setName(TrafficMarker value, String key) {
+ // do nothing
+ }
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/GovRule.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/PolicyProperties.java
similarity index 68%
rename from governance/src/main/java/org/apache/servicecomb/governance/policy/GovRule.java
rename to governance/src/main/java/org/apache/servicecomb/governance/properties/PolicyProperties.java
index 58db001..73a3a07 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/policy/GovRule.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/PolicyProperties.java
@@ -15,27 +15,16 @@
* limitations under the License.
*/
-package org.apache.servicecomb.governance.policy;
+package org.apache.servicecomb.governance.properties;
-public class GovRule {
+import org.apache.servicecomb.governance.policy.AbstractPolicy;
- private String match;
-
- private int precedence;
-
- public String getMatch() {
- return match;
- }
-
- public void setMatch(String match) {
- this.match = match;
- }
-
- public int getPrecedence() {
- return precedence;
+public abstract class PolicyProperties<T extends AbstractPolicy> extends GovernanceProperties<T> {
+ protected PolicyProperties(String key) {
+ super(key);
}
- public void setPrecedence(int precedence) {
- this.precedence = precedence;
+ protected void setName(T value, String key) {
+ value.setName(key);
}
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java
index e1a2653..472901c 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java
@@ -21,7 +21,7 @@ import org.apache.servicecomb.governance.policy.RateLimitingPolicy;
import org.springframework.stereotype.Component;
@Component
-public class RateLimitProperties extends GovProperties<RateLimitingPolicy> {
+public class RateLimitProperties extends PolicyProperties<RateLimitingPolicy> {
public static final String MATCH_RATE_LIMIT_KEY = "servicecomb.rateLimiting";
public RateLimitProperties() {
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java
index 9c87ba2..483ea52 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java
@@ -20,7 +20,7 @@ import org.apache.servicecomb.governance.policy.RetryPolicy;
import org.springframework.stereotype.Component;
@Component
-public class RetryProperties extends GovProperties<RetryPolicy> {
+public class RetryProperties extends PolicyProperties<RetryPolicy> {
public static final String MATCH_RETRY_KEY = "servicecomb.retry";
public RetryProperties() {
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java
index 265e632..bb01422 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java
@@ -18,9 +18,6 @@ package org.apache.servicecomb.governance.service;
import org.apache.servicecomb.governance.marker.GovHttpRequest;
-import java.util.List;
-
public interface MatchersService {
-
- List<String> getMatchedNames(GovHttpRequest govHttpRequest);
+ boolean checkMatch(GovHttpRequest govHttpRequest, String key);
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersServiceImpl.java
similarity index 54%
copy from governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java
copy to governance/src/main/java/org/apache/servicecomb/governance/service/MatchersServiceImpl.java
index c35c1a1..0df3159 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersServiceImpl.java
@@ -14,39 +14,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.servicecomb.governance;
-import java.util.List;
+package org.apache.servicecomb.governance.service;
+
import java.util.Map;
-import org.apache.servicecomb.governance.policy.Policy;
-import org.apache.servicecomb.governance.service.MatchersService;
-import org.apache.servicecomb.governance.service.PolicyService;
+import org.apache.servicecomb.governance.marker.GovHttpRequest;
+import org.apache.servicecomb.governance.marker.RequestProcessor;
+import org.apache.servicecomb.governance.marker.TrafficMarker;
+import org.apache.servicecomb.governance.properties.MatchProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
-import org.apache.servicecomb.governance.marker.GovHttpRequest;
-
@Component
-public class MatchersManager {
-
+public class MatchersServiceImpl implements MatchersService {
@Autowired
- private MatchersService matchersService;
+ private RequestProcessor requestProcessor;
@Autowired
- private PolicyService policyService;
+ private MatchProperties matchProperties;
- public MatchersManager() {
- }
+ @Override
+ public boolean checkMatch(GovHttpRequest govHttpRequest, String key) {
+ Map<String, TrafficMarker> parsedEntity = matchProperties.getParsedEntity();
+
+ String[] subKeys = key.split("\\.");
+ if (subKeys.length != 2) {
+ return false;
+ }
+
+ TrafficMarker trafficMarker = parsedEntity.get(subKeys[0]);
+
+ if (trafficMarker == null) {
+ return false;
+ }
- public Map<String, Policy> match(GovHttpRequest request) {
- /**
- * 1.获取该请求携带的marker
- */
- List<String> marks = matchersService.getMatchedNames(request);
- /**
- * 2.通过 marker获取到所有的policy
- */
- return policyService.getAllPolicies(marks);
+ return trafficMarker.checkMatch(govHttpRequest, requestProcessor, subKeys[1]);
}
}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/PolicyServiceImpl.java b/governance/src/main/java/org/apache/servicecomb/governance/service/PolicyServiceImpl.java
index 03f1a1b..47fa0d6 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/service/PolicyServiceImpl.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/service/PolicyServiceImpl.java
@@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
-import org.apache.servicecomb.governance.properties.GovProperties;
+import org.apache.servicecomb.governance.properties.GovernanceProperties;
@Component
public class PolicyServiceImpl implements PolicyService {
@@ -37,7 +37,7 @@ public class PolicyServiceImpl implements PolicyService {
private static final String MATCH_NONE = "none";
@Autowired
- private List<GovProperties<? extends AbstractPolicy>> propertiesList;
+ private List<GovernanceProperties<? extends AbstractPolicy>> propertiesList;
@Override
public Map<String, Policy> getAllPolicies(List<String> marks) {
@@ -47,7 +47,7 @@ public class PolicyServiceImpl implements PolicyService {
return policies;
}
- for (GovProperties<? extends AbstractPolicy> properties : propertiesList) {
+ for (GovernanceProperties<? extends AbstractPolicy> properties : propertiesList) {
Policy policy = match(properties.getParsedEntity(), marks);
if (policy != null) {
policies.put(properties.getClass().getName(), policy);
diff --git a/governance/src/test/java/org/apache/servicecomb/governance/FlowControlTest.java b/governance/src/test/java/org/apache/servicecomb/governance/FlowControlTest.java
new file mode 100644
index 0000000..8aeddba
--- /dev/null
+++ b/governance/src/test/java/org/apache/servicecomb/governance/FlowControlTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.governance;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.servicecomb.governance.handler.RateLimitingHandler;
+import org.apache.servicecomb.governance.marker.GovHttpRequest;
+import org.apache.servicecomb.governance.policy.Policy;
+import org.apache.servicecomb.governance.properties.RateLimitProperties;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import io.github.resilience4j.decorators.Decorators;
+import io.github.resilience4j.decorators.Decorators.DecorateCheckedSupplier;
+import io.github.resilience4j.ratelimiter.RequestNotPermitted;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class)
+public class FlowControlTest {
+ @Autowired
+ private RateLimitingHandler rateLimitingHandler;
+
+ @Autowired
+ private RateLimitProperties rateLimitProperties;
+
+ @Autowired
+ private MatchersManager matchersManager;
+
+ @Test
+ public void test_rate_limiting_work() throws Throwable {
+ DecorateCheckedSupplier<Object> ds = Decorators.ofCheckedSupplier(() -> {
+ return "test";
+ });
+
+ GovHttpRequest request = new GovHttpRequest("testService", "1.0");
+ request.setUri("/hello");
+ Policy policy = matchersManager.match(request, rateLimitProperties.getParsedEntity());
+ Assert.assertNotNull(policy);
+ DecorateCheckedSupplier<Object> dcs = rateLimitingHandler.process(ds, policy);
+
+ Assert.assertEquals("test", dcs.get());
+
+ // flow control
+ CountDownLatch cd = new CountDownLatch(10);
+ AtomicBoolean expected = new AtomicBoolean(false);
+ AtomicBoolean notExpected = new AtomicBoolean(false);
+ for (int i = 0; i < 10; i++) {
+ new Thread() {
+ public void run() {
+ try {
+ DecorateCheckedSupplier<Object> dcs = rateLimitingHandler.process(ds, policy);
+ Object result = dcs.get();
+ if (!"test".equals(result)) {
+ notExpected.set(true);
+ }
+ } catch (Throwable e) {
+ if (e instanceof RequestNotPermitted) {
+ expected.set(true);
+ } else {
+ notExpected.set(true);
+ }
+ }
+ cd.countDown();
+ }
+ }.start();
+ }
+ cd.await(1, TimeUnit.SECONDS);
+ Assert.assertTrue(expected.get());
+ Assert.assertFalse(notExpected.get());
+ }
+}
diff --git a/governance/src/test/java/org/apache/servicecomb/governance/GovPropertiesTest.java b/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java
similarity index 97%
rename from governance/src/test/java/org/apache/servicecomb/governance/GovPropertiesTest.java
rename to governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java
index 9b4d3c9..560bf05 100644
--- a/governance/src/test/java/org/apache/servicecomb/governance/GovPropertiesTest.java
+++ b/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java
@@ -47,17 +47,17 @@ import org.apache.servicecomb.governance.policy.RateLimitingPolicy;
import org.apache.servicecomb.governance.policy.RetryPolicy;
import org.apache.servicecomb.governance.properties.BulkheadProperties;
import org.apache.servicecomb.governance.properties.CircuitBreakerProperties;
-import org.apache.servicecomb.governance.properties.GovProperties;
+import org.apache.servicecomb.governance.properties.GovernanceProperties;
import org.apache.servicecomb.governance.properties.MatchProperties;
import org.apache.servicecomb.governance.properties.RateLimitProperties;
import org.apache.servicecomb.governance.properties.RetryProperties;
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class)
-public class GovPropertiesTest {
+public class GovernancePropertiesTest {
@Autowired
- private List<GovProperties<? extends AbstractPolicy>> propertiesList;
+ private List<GovernanceProperties<? extends AbstractPolicy>> propertiesList;
@Autowired
private MatchProperties matchProperties;
@@ -79,7 +79,7 @@ public class GovPropertiesTest {
private Map<String, Object> dynamicValues = new HashMap<>();
- public GovPropertiesTest() {
+ public GovernancePropertiesTest() {
System.out.print(1);
}
diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockMatchersService.java b/governance/src/test/java/org/apache/servicecomb/governance/MockInvocationContext.java
similarity index 58%
rename from governance/src/test/java/org/apache/servicecomb/governance/MockMatchersService.java
rename to governance/src/test/java/org/apache/servicecomb/governance/MockInvocationContext.java
index 1387312..bde9b38 100644
--- a/governance/src/test/java/org/apache/servicecomb/governance/MockMatchersService.java
+++ b/governance/src/test/java/org/apache/servicecomb/governance/MockInvocationContext.java
@@ -17,17 +17,32 @@
package org.apache.servicecomb.governance;
-import java.util.List;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import org.springframework.stereotype.Component;
-import org.apache.servicecomb.governance.marker.GovHttpRequest;
-import org.apache.servicecomb.governance.service.MatchersService;
-
@Component
-public class MockMatchersService implements MatchersService {
+public class MockInvocationContext implements InvocationContext {
+ private ThreadLocal<Map<String, Boolean>> context = new ThreadLocal<>();
+
+ @Override
+ public Map<String, Boolean> getCalculatedMatches() {
+ Map<String, Boolean> result = context.get();
+ if (result == null) {
+ return Collections.emptyMap();
+ }
+ return result;
+ }
+
@Override
- public List<String> getMatchedNames(GovHttpRequest govHttpRequest) {
- return null;
+ public void addMatch(String key, Boolean value) {
+ Map<String, Boolean> result = context.get();
+ if (result == null) {
+ result = new HashMap<>();
+ context.set(result);
+ }
+ result.put(key, value);
}
}