qualifiedNameControllerMap = new ConcurrentHashMapEx<>();
+
+ protected QpsController globalQpsController;
+
+ public static final String SEPARATOR = ".";
+
+ private String configKeyPrefix;
+
+ public QpsController getOrCreate(String key) {
+ return qualifiedNameControllerMap.computeIfAbsent(key, this::create);
+ }
+
+ /**
+ * Create relevant qpsLimit dynamicProperty and watch the configuration change.
+ * Search and return a valid qpsController.
+ */
+ protected QpsController create(String qualifiedNameKey) {
+ if (!QUALIFIED_KEY_CHECKER.matcher(qualifiedNameKey).matches()) {
+ throw new IllegalArgumentException("Unexpected qualified name: [" + qualifiedNameKey + "]");
+ }
+ // create "microservice"
+ createQpsControllerIfNotExist(qualifiedNameKey.substring(0, qualifiedNameKey.indexOf(SEPARATOR)));
+ // create "microservice.schema"
+ createQpsControllerIfNotExist(qualifiedNameKey.substring(0, qualifiedNameKey.lastIndexOf(SEPARATOR)));
+ // create "microservice.schema.operation"
+ createQpsControllerIfNotExist(qualifiedNameKey);
+
+ return searchQpsController(qualifiedNameKey);
+ }
+
+ /**
+ * Use qualifiedNameKey to search {@link QpsController}.
+ * Firstly try to search "microservice.schema.operation". If no valid result found, then try "microservice.schema",
+ * and then "microservice" or global qpsController(If there is a global qpsController).
+ * This method ensures that there is always an existing qpsController returned, as the relevant qpsController has
+ * been created and stored in {@link #create(String)}
+ *
+ * @param qualifiedNameKey qualifiedNameKey in {@link #qualifiedNameControllerMap}
+ * @return a qps controller, lower level controllers with valid qpsLimit have priority.
+ */
+ protected QpsController searchQpsController(String qualifiedNameKey) {
+ QpsController qpsController = configQpsControllerMap.get(qualifiedNameKey);
+ if (isValidQpsController(qpsController)) {
+ return qpsController;
+ }
+
+ int index = qualifiedNameKey.lastIndexOf(SEPARATOR);
+ while (index > 0) {
+ qpsController = configQpsControllerMap.get(qualifiedNameKey.substring(0, index));
+ if (isValidQpsController(qpsController)) {
+ return qpsController;
+ }
+
+ index = qualifiedNameKey.lastIndexOf(SEPARATOR, index - 1);
+ }
+
+ if (isValidQpsController(qpsController)) {
+ return qpsController;
+ }
+
+ if (null != globalQpsController) {
+ return globalQpsController;
+ }
+
+ // if null is returned, maybe the operation qps controller is not initiated correctly.
+ // getOrCreateQpsController() should be invoked before.
+ return qpsController;
+ }
+
+ private boolean keyMatch(String configKey, Entry controllerEntry) {
+ return controllerEntry.getKey().equals(configKey)
+ || controllerEntry.getKey().startsWith(configKey + SEPARATOR);
+ }
+
+ private boolean isValidQpsController(QpsController qpsController) {
+ return null != qpsController && null != qpsController.getQpsLimit();
+ }
+
+ private void createQpsControllerIfNotExist(String configKey) {
+ if (configQpsControllerMap.keySet().contains(configKey)) {
+ return;
+ }
+
+ LOGGER.info("Create qpsController, configKey = [{}]", configKey);
+ DynamicProperty property = getDynamicProperty(configKey);
+ QpsController qpsController = new QpsController(configKey, property.getInteger());
+
+ configQpsControllerMap.put(configKey, qpsController);
+
+ property.addCallback(() -> {
+ qpsController.setQpsLimit(property.getInteger());
+ LOGGER.info("Qps limit updated, configKey = [{}], value = [{}]", configKey, property.getString());
+ updateObjMap(configKey);
+ });
+ }
+
+ protected void updateObjMap(String configKey) {
+ for (Entry controllerEntry : qualifiedNameControllerMap.entrySet()) {
+ if (keyMatch(configKey, controllerEntry)) {
+ QpsController qpsController = searchQpsController(controllerEntry.getKey());
+ controllerEntry.setValue(qpsController);
+ LOGGER.info("QpsController updated, operationId = [{}], configKey = [{}], qpsLimit = [{}]",
+ controllerEntry.getKey(), qpsController.getKey(), qpsController.getQpsLimit());
+ }
+ }
+ }
+
+ public QpsControllerManager setConfigKeyPrefix(String configKeyPrefix) {
+ this.configKeyPrefix = configKeyPrefix;
+ return this;
+ }
+
+ public QpsControllerManager setGlobalQpsController(String globalConfigKey) {
+ DynamicProperty globalQpsProperty = DynamicProperty.getInstance(globalConfigKey);
+ QpsController qpsController = new QpsController(globalConfigKey, globalQpsProperty.getInteger());
+
+ globalQpsProperty.addCallback(() -> {
+ qpsController.setQpsLimit(globalQpsProperty.getInteger());
+ LOGGER.info("Global qps limit update, value = [{}]", globalQpsProperty.getInteger());
+ });
+
+ this.globalQpsController = qpsController;
+ return this;
+ }
+
+ public QpsController getGlobalQpsController() {
+ return globalQpsController;
+ }
+
+ protected DynamicProperty getDynamicProperty(String configKey) {
+ return DynamicProperty.getInstance(configKeyPrefix + configKey);
+ }
+}
diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java
new file mode 100644
index 0000000000..1837ff2972
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.qps;
+
+import java.util.Map;
+
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.core.definition.SchemaMeta;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import mockit.Deencapsulation;
+
+public class QpsControllerManagerTest {
+
+ @Before
+ public void beforeTest() {
+ ArchaiusUtils.resetConfig();
+ }
+
+ @After
+ public void afterTest() {
+ ArchaiusUtils.resetConfig();
+ }
+
+ @Test
+ public void testGetOrCreate() {
+ QpsControllerManager testQpsControllerManager = new QpsControllerManager()
+ .setConfigKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX);
+ initTestQpsControllerManager(testQpsControllerManager);
+
+ // pojo
+ setConfigWithDefaultPrefix("pojo", 100);
+ QpsController qpsController = testQpsControllerManager.getOrCreate("pojo.server.test");
+ Assert.assertEquals("pojo", qpsController.getKey());
+ Assert.assertTrue(100 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("pojo2.server.test");
+ Assert.assertEquals("pojo2", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("poj.server.test");
+ Assert.assertEquals("poj", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+
+ testGetOrCreateCommon(testQpsControllerManager);
+ }
+
+ @Test
+ public void testGetOrCreateWithGlobalConfig() {
+ QpsControllerManager testQpsControllerManager = new QpsControllerManager()
+ .setGlobalQpsController(Config.PROVIDER_LIMIT_KEY_GLOBAL)
+ .setConfigKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX);
+
+ // global
+ setConfig(Config.PROVIDER_LIMIT_KEY_GLOBAL, 50);
+ QpsController qpsController = testQpsControllerManager.getOrCreate("pojo.server.test");
+ Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
+ Assert.assertTrue(50 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("pojo2.server.test");
+ Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
+ Assert.assertTrue(50 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("poj.server.test");
+ Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
+ Assert.assertTrue(50 == qpsController.getQpsLimit());
+
+ // pojo
+ setConfigWithDefaultPrefix("pojo", 100);
+ qpsController = testQpsControllerManager.getOrCreate("pojo.server.test");
+ Assert.assertEquals("pojo", qpsController.getKey());
+ Assert.assertTrue(100 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("pojo2.server.test");
+ Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
+ Assert.assertTrue(50 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("poj.server.test");
+ Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
+ Assert.assertTrue(50 == qpsController.getQpsLimit());
+
+ testGetOrCreateCommon(testQpsControllerManager);
+ }
+
+ @Test
+ public void testQualifiedNameKey() {
+ QpsControllerManager qpsControllerManager = new QpsControllerManager();
+ QpsController qpsController = qpsControllerManager.getOrCreate("service.schema.opr");
+ Assert.assertEquals("service", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+
+ qpsController = qpsControllerManager.getOrCreate("test_service.test_schema.test_opr");
+ Assert.assertEquals("test_service", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+
+ qpsController = qpsControllerManager.getOrCreate("test-service.test-schema.test-opr");
+ Assert.assertEquals("test-service", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+
+ Exception exception = null;
+ try {
+ qpsControllerManager.getOrCreate("svc.schema.opr.tail");
+ } catch (Exception e) {
+ exception = e;
+ }
+ Assert.assertNotNull(exception);
+ Assert.assertEquals(IllegalArgumentException.class, exception.getClass());
+ Assert.assertEquals("Unexpected qualified name: [svc.schema.opr.tail]", exception.getMessage());
+
+ try {
+ qpsControllerManager.getOrCreate("svc.schema");
+ } catch (Exception e) {
+ exception = e;
+ }
+ Assert.assertNotNull(exception);
+ Assert.assertEquals(IllegalArgumentException.class, exception.getClass());
+ Assert.assertEquals("Unexpected qualified name: [svc.schema]", exception.getMessage());
+
+ try {
+ qpsControllerManager.getOrCreate("...");
+ } catch (Exception e) {
+ exception = e;
+ }
+ Assert.assertNotNull(exception);
+ Assert.assertEquals(IllegalArgumentException.class, exception.getClass());
+ Assert.assertEquals("Unexpected qualified name: [...]", exception.getMessage());
+ }
+
+ private void testGetOrCreateCommon(QpsControllerManager testQpsControllerManager) {
+ // pojo.server
+ setConfigWithDefaultPrefix("pojo.server", 200);
+ QpsController qpsController = testQpsControllerManager.getOrCreate("pojo.server.test");
+ Assert.assertEquals("pojo.server", qpsController.getKey());
+ Assert.assertTrue(200 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("pojo.server2.test");
+ Assert.assertEquals("pojo", qpsController.getKey());
+ Assert.assertTrue(100 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("pojo.serve.test");
+ Assert.assertEquals("pojo", qpsController.getKey());
+ Assert.assertTrue(100 == qpsController.getQpsLimit());
+
+ // pojo.server.test
+ setConfigWithDefaultPrefix("pojo.server.test", 300);
+ qpsController = testQpsControllerManager.getOrCreate("pojo.server.test");
+ Assert.assertEquals("pojo.server.test", qpsController.getKey());
+ Assert.assertTrue(300 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("pojo.server.test2");
+ Assert.assertEquals("pojo.server", qpsController.getKey());
+ Assert.assertTrue(200 == qpsController.getQpsLimit());
+ qpsController = testQpsControllerManager.getOrCreate("pojo.server.tes");
+ Assert.assertEquals("pojo.server", qpsController.getKey());
+ Assert.assertTrue(200 == qpsController.getQpsLimit());
+ }
+
+ /**
+ * Init testQpsControllerManager to test search function.
+ */
+ private void initTestQpsControllerManager(QpsControllerManager testQpsControllerManager) {
+ // pojo.server.test
+ QpsController qpsController = testQpsControllerManager.getOrCreate("pojo.server.test");
+ Assert.assertEquals("pojo", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+
+ // pojo.server.test2
+ testQpsControllerManager.getOrCreate("pojo.server.test2");
+
+ // pojo.server.tes
+ testQpsControllerManager.getOrCreate("pojo.server.tes");
+
+ // pojo.server2.test
+ testQpsControllerManager.getOrCreate("pojo.server2.test");
+
+ // pojo.serve.test
+ testQpsControllerManager.getOrCreate("pojo.serve.test");
+
+ // pojo2.server.test
+ qpsController = testQpsControllerManager.getOrCreate("pojo2.server.test");
+ Assert.assertEquals("pojo2", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+
+ // poj.server.test
+ qpsController = testQpsControllerManager.getOrCreate("poj.server.test");
+ Assert.assertEquals("poj", qpsController.getKey());
+ Assert.assertNull(qpsController.getQpsLimit());
+ }
+
+ @Test
+ public void testMock() {
+ Invocation invocation = getMockInvocation("service", "schema", "oper");
+ OperationMeta operationMeta = invocation.getOperationMeta();
+ SchemaMeta schemaMeta = operationMeta.getSchemaMeta();
+
+ Assert.assertEquals("service", operationMeta.getMicroserviceName());
+ Assert.assertEquals("service.schema.oper", operationMeta.getMicroserviceQualifiedName());
+ Assert.assertEquals("schema.oper", operationMeta.getSchemaQualifiedName());
+ Assert.assertEquals("schema", schemaMeta.getSchemaId());
+ }
+
+ public static Invocation getMockInvocation(String microserviceName, String schemaId, String operationId) {
+ return getMockInvocation(
+ getMockOperationMeta(microserviceName, schemaId, operationId)
+ );
+ }
+
+ private static Invocation getMockInvocation(OperationMeta mockOperationMeta) {
+ Invocation invocation = Mockito.mock(Invocation.class);
+ Mockito.when(invocation.getOperationMeta()).thenReturn(mockOperationMeta);
+ return invocation;
+ }
+
+ public static OperationMeta getMockOperationMeta(String microserviceName, String schemaId, String operationId) {
+ OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
+ SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class);
+
+ Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta);
+ Mockito.when(operationMeta.getSchemaQualifiedName())
+ .thenReturn(schemaId + QpsControllerManager.SEPARATOR + operationId);
+ Mockito.when(operationMeta.getMicroserviceQualifiedName()).thenReturn(
+ microserviceName + QpsControllerManager.SEPARATOR + schemaId + QpsControllerManager.SEPARATOR
+ + operationId);
+ Mockito.when(operationMeta.getMicroserviceName()).thenReturn(microserviceName);
+ Mockito.when(schemaMeta.getSchemaId()).thenReturn(schemaId);
+
+ return operationMeta;
+ }
+
+ public static void setConfig(String key, int value) {
+ Utils.updateProperty(key, value);
+ }
+
+ public static void setConfigWithDefaultPrefix(String key, int value) {
+ String configKey = Config.CONSUMER_LIMIT_KEY_PREFIX + key;
+ Utils.updateProperty(configKey, value);
+ }
+
+ public static void clearState(QpsControllerManager qpsControllerManager) {
+ Map objMap = Deencapsulation.getField(qpsControllerManager, "qualifiedNameControllerMap");
+ objMap.clear();
+ Map configQpsControllerMap = Deencapsulation
+ .getField(qpsControllerManager, "configQpsControllerMap");
+ configQpsControllerMap.clear();
+ }
+}
diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsControllermanager.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsControllermanager.java
deleted file mode 100644
index 426f7f8db0..0000000000
--- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsControllermanager.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.qps;
-
-import org.apache.servicecomb.core.definition.OperationMeta;
-import org.apache.servicecomb.core.definition.SchemaMeta;
-import org.junit.Assert;
-import org.junit.Test;
-
-import mockit.Expectations;
-import mockit.Mocked;
-
-/**
- *
- *
- */
-public class TestConsumerQpsControllermanager {
- private static String microserviceName = "pojo";
-
- private static String schemaQualified = microserviceName + ".server";
-
- private static String operationQualified = schemaQualified + ".test";
-
- @Test
- public void testQpsLimit(@Mocked SchemaMeta schemaMeta, @Mocked OperationMeta operationMeta) {
- new Expectations() {
- {
- operationMeta.getMicroserviceQualifiedName();
- result = operationQualified;
-
- schemaMeta.getMicroserviceQualifiedName();
- result = schemaQualified;
-
- operationMeta.getMicroserviceName();
- result = microserviceName;
- }
- };
-
- ConsumerQpsControllerManager mgr = new ConsumerQpsControllerManager();
- QpsController qpsController = mgr.getOrCreate(operationMeta);
- Assert.assertEquals((Integer) Integer.MAX_VALUE, qpsController.getQpsLimit());
- Assert.assertEquals(microserviceName, qpsController.getKey());
-
- doTestQpsLimit(mgr, operationMeta, microserviceName, 100, microserviceName, 100);
- doTestQpsLimit(mgr, operationMeta, schemaQualified, 200, schemaQualified, 200);
- doTestQpsLimit(mgr, operationMeta, operationQualified, 300, operationQualified, 300);
- doTestQpsLimit(mgr, operationMeta, operationQualified, null, schemaQualified, 200);
- doTestQpsLimit(mgr, operationMeta, schemaQualified, null, microserviceName, 100);
- doTestQpsLimit(mgr, operationMeta, microserviceName, null, microserviceName, Integer.MAX_VALUE);
- }
-
- private void doTestQpsLimit(ConsumerQpsControllerManager mgr, OperationMeta operationMeta, String key,
- Integer newValue,
- String expectKey, Integer expectValue) {
- Utils.updateProperty(Config.CONSUMER_LIMIT_KEY_PREFIX + key, newValue);
- QpsController qpsController = mgr.getOrCreate(operationMeta);
- Assert.assertEquals(expectValue, qpsController.getQpsLimit());
- Assert.assertEquals(expectKey, qpsController.getKey());
- }
-}
diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsFlowControlHandler.java
index 368459e196..6359a7eec1 100644
--- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsFlowControlHandler.java
+++ b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsFlowControlHandler.java
@@ -17,20 +17,22 @@
package org.apache.servicecomb.qps;
+import java.util.concurrent.ConcurrentHashMap;
+
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.junit.After;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import mockit.Deencapsulation;
import mockit.Mock;
import mockit.MockUp;
-/**
- *
- *
- */
public class TestConsumerQpsFlowControlHandler {
ConsumerQpsFlowControlHandler handler = new ConsumerQpsFlowControlHandler();
@@ -41,8 +43,21 @@ public class TestConsumerQpsFlowControlHandler {
OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
+ @Before
+ public void setUP() {
+ ArchaiusUtils.resetConfig();
+ QpsControllerManagerTest.clearState(ConsumerQpsFlowControlHandler.qpsControllerMgr);
+ }
+
+
+ @After
+ public void afterTest() {
+ ArchaiusUtils.resetConfig();
+ QpsControllerManagerTest.clearState(ConsumerQpsFlowControlHandler.qpsControllerMgr);
+ }
+
@Test
- public void testQpsController() throws Exception {
+ public void testQpsController() {
QpsController qpsController = new QpsController("abc", 100);
Assert.assertEquals(false, qpsController.isLimitNewRequest());
@@ -68,9 +83,11 @@ public void testHandle() {
boolean validAssert;
try {
validAssert = true;
+ String key = "svc.schema.opr";
+ QpsController qpsController = new QpsController("key", 12);
Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
- Mockito.when(operationMeta.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName");
-
+ Mockito.when(operationMeta.getMicroserviceQualifiedName()).thenReturn(key);
+ setQpsController(key, qpsController);
new MockUp() {
@Mock
public boolean isLimitNewRequest() {
@@ -78,15 +95,15 @@ public boolean isLimitNewRequest() {
}
};
- new MockUp() {
-
+ new MockUp() {
@Mock
- protected QpsController create(OperationMeta operationMeta) {
- return new QpsController("key", 12);
+ protected QpsController create(String qualifiedNameKey) {
+ return qpsController;
}
};
handler.handle(invocation, asyncResp);
} catch (Exception e) {
+ e.printStackTrace();
validAssert = false;
}
Assert.assertTrue(validAssert);
@@ -97,8 +114,11 @@ public void testHandleIsLimitNewRequestAsFalse() {
boolean validAssert;
try {
validAssert = true;
+ String key = "MicroserviceQualifiedName";
+ QpsController qpsController = new QpsController("key", 12);
Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
- Mockito.when(operationMeta.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName");
+ Mockito.when(operationMeta.getMicroserviceQualifiedName()).thenReturn(key);
+ setQpsController(key, qpsController);
new MockUp() {
@Mock
@@ -107,17 +127,25 @@ public boolean isLimitNewRequest() {
}
};
- new MockUp() {
+ new MockUp() {
@Mock
- protected QpsController create(OperationMeta operationMeta) {
- return new QpsController("key", 12);
+ protected QpsController create(String qualifiedNameKey) {
+ return qpsController;
}
};
handler.handle(invocation, asyncResp);
} catch (Exception e) {
+ e.printStackTrace();
validAssert = false;
}
Assert.assertTrue(validAssert);
}
+
+ private void setQpsController(String key, QpsController qpsController) {
+ QpsControllerManager qpsControllerManager = Deencapsulation.getField(handler, "qpsControllerMgr");
+ ConcurrentHashMap objMap = Deencapsulation
+ .getField(qpsControllerManager, "qualifiedNameControllerMap");
+ objMap.put(key, qpsController);
+ }
}
diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsControllermanager.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsControllermanager.java
deleted file mode 100644
index c16f7092de..0000000000
--- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsControllermanager.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.qps;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestProviderQpsControllermanager {
- private static String microserviceName = "pojo";
-
- @Test
- public void testQpsLimit() {
- ProviderQpsControllerManager mgr = new ProviderQpsControllerManager();
- QpsController qpsController = mgr.getOrCreate(microserviceName);
- Assert.assertEquals(null, qpsController.getQpsLimit());
- Assert.assertEquals(microserviceName, qpsController.getKey());
-
- doTestQpsLimit(mgr, microserviceName, 100, microserviceName, 100);
- doTestQpsLimit(mgr, microserviceName, null, microserviceName, null);
- }
-
- private void doTestQpsLimit(ProviderQpsControllerManager mgr, String key, Integer newValue,
- String expectKey, Integer expectValue) {
- Utils.updateProperty(Config.PROVIDER_LIMIT_KEY_PREFIX + key, newValue);
- QpsController qpsController = mgr.getOrCreate(key);
- Assert.assertEquals(expectValue, qpsController.getQpsLimit());
- Assert.assertEquals(expectKey, qpsController.getKey());
- }
-}
diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java
index 40303db8e9..1bdf8a2152 100644
--- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java
+++ b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java
@@ -17,10 +17,14 @@
package org.apache.servicecomb.qps;
+import static org.junit.Assert.fail;
+
import org.apache.servicecomb.core.Const;
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -42,9 +46,18 @@ public class TestProviderQpsFlowControlHandler {
@Before
public void setUP() {
+ ArchaiusUtils.resetConfig();
+ QpsControllerManagerTest.clearState(ProviderQpsFlowControlHandler.qpsControllerMgr);
Utils.updateProperty(Config.PROVIDER_LIMIT_KEY_PREFIX + "test", 1);
}
+
+ @After
+ public void afterTest() {
+ ArchaiusUtils.resetConfig();
+ QpsControllerManagerTest.clearState(ProviderQpsFlowControlHandler.qpsControllerMgr);
+ }
+
@Test
public void testGlobalQpsControl(final @Injectable Invocation invocation,
final @Injectable AsyncResponse asyncResp) throws Exception {
@@ -52,6 +65,8 @@ public void testGlobalQpsControl(final @Injectable Invocation invocation,
{
invocation.getContext(Const.SRC_MICROSERVICE);
result = "test";
+ invocation.getOperationMeta();
+ result = QpsControllerManagerTest.getMockOperationMeta("pojo", "server", "opr");
asyncResp.producerFail((Throwable) any);
result = new RuntimeException("test error");
}
@@ -67,7 +82,7 @@ public void testGlobalQpsControl(final @Injectable Invocation invocation,
gHandler.handle(invocation, asyncResp);
count++;
gHandler.handle(invocation, asyncResp);
- Assert.assertTrue(false);
+ fail("An exception is expected!");
} catch (Exception e) {
Assert.assertEquals(2, count);
Assert.assertEquals("test error", e.getMessage());
@@ -75,7 +90,7 @@ public void testGlobalQpsControl(final @Injectable Invocation invocation,
}
@Test
- public void testQpsController() throws Exception {
+ public void testQpsController() {
QpsController qpsController = new QpsController("abc", 100);
Assert.assertEquals(false, qpsController.isLimitNewRequest());
@@ -93,6 +108,7 @@ public void testHandleWithException() {
handler.handle(invocation, asyncResp);
handler.handle(invocation, asyncResp);
} catch (Exception e) {
+ e.printStackTrace();
validAssert = false;
}
Assert.assertTrue(validAssert);
@@ -104,6 +120,8 @@ public void testHandle() {
try {
validAssert = true;
Mockito.when(invocation.getContext(Const.SRC_MICROSERVICE)).thenReturn("test");
+ OperationMeta mockOperationMeta = QpsControllerManagerTest.getMockOperationMeta("pojo", "server", "opr");
+ Mockito.when(invocation.getOperationMeta()).thenReturn(mockOperationMeta);
new MockUp() {
@Mock
@@ -112,15 +130,16 @@ public boolean isLimitNewRequest() {
}
};
- new MockUp() {
+ new MockUp() {
@Mock
- protected QpsController create(String serviceName) {
- return new QpsController(serviceName, 12);
+ protected QpsController create(String qualifiedNameKey) {
+ return new QpsController(qualifiedNameKey, 12);
}
};
handler.handle(invocation, asyncResp);
} catch (Exception e) {
+ e.printStackTrace();
validAssert = false;
}
Assert.assertTrue(validAssert);
@@ -132,6 +151,9 @@ public void testHandleIsLimitNewRequestAsFalse() {
try {
validAssert = true;
Mockito.when(invocation.getContext(Const.SRC_MICROSERVICE)).thenReturn("test");
+ OperationMeta mockOperationMeta = QpsControllerManagerTest
+ .getMockOperationMeta("pojo", "server", "opr");
+ Mockito.when(invocation.getOperationMeta()).thenReturn(mockOperationMeta);
new MockUp() {
@Mock
@@ -140,15 +162,16 @@ public boolean isLimitNewRequest() {
}
};
- new MockUp() {
+ new MockUp() {
@Mock
- protected QpsController create(String serviceName) {
- return new QpsController(serviceName, 12);
+ protected QpsController create(String qualifiedNameKey) {
+ return new QpsController(qualifiedNameKey, 12);
}
};
handler.handle(invocation, asyncResp);
} catch (Exception e) {
+ e.printStackTrace();
validAssert = false;
}
Assert.assertTrue(validAssert);