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 2020/07/20 06:21:24 UTC

[servicecomb-java-chassis] branch master updated (dfe8ef5 -> 88c24e9)

This is an automated email from the ASF dual-hosted git repository.

liubao pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git.


    from dfe8ef5  [SCB-1832] Edge will lose public request headers:old request maybe null
     new 4aed86d  [SCB-2043] flow control support leak bucket and token bucket
     new 88c24e9  [SCB-2043] modify as comment, change strategy when strategy change.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/apache/servicecomb/qps/Config.java    |   9 ++
 .../qps/ConsumerQpsFlowControlHandler.java         |   7 +-
 .../qps/ProviderQpsFlowControlHandler.java         |  15 +-
 .../servicecomb/qps/QpsControllerManager.java      | 162 ++++++++++++++-------
 .../org/apache/servicecomb/qps/QpsStrategy.java    |   5 +-
 .../qps/strategy/AbstractQpsStrategy.java          |  49 ++++---
 .../FixedWindowStrategy.java}                      |  31 +---
 .../qps/strategy/LeakyBucketStrategy.java          |  75 ++++++++++
 .../servicecomb/qps/strategy/StrategyType.java     |  28 ++--
 .../qps/strategy/TokenBucketStrategy.java          |   9 +-
 .../servicecomb/qps/QpsControllerManagerTest.java  | 162 +++++++++++----------
 .../org/apache/servicecomb/qps/TestConfig.java     |   4 -
 .../qps/TestConsumerQpsFlowControlHandler.java     |  36 ++---
 .../qps/TestProviderQpsFlowControlHandler.java     |  20 +--
 .../apache/servicecomb/qps/TestQpsStrategy.java    |  41 +++---
 .../router/custom/RouterInvokeFilter.java          |   2 +-
 16 files changed, 399 insertions(+), 256 deletions(-)
 copy foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/SPIServiceDef.java => handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsStrategy.java (89%)
 copy inspector/src/main/java/org/apache/servicecomb/inspector/internal/model/DynamicPropertyView.java => handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java (59%)
 rename handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/{QpsController.java => strategy/FixedWindowStrategy.java} (77%)
 create mode 100644 handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java
 copy swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/model/HttpParameterType.java => handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java (66%)
 copy core/src/main/java/org/apache/servicecomb/core/provider/consumer/AbstractConsumerProvider.java => handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java (78%)
 copy foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleLatestParser.java => handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java (50%)


[servicecomb-java-chassis] 01/02: [SCB-2043] flow control support leak bucket and token bucket

Posted by li...@apache.org.
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 4aed86d2965dfa5d76b90ce9d5774a13e1d6ee8f
Author: GuoYL <gy...@gmail.com>
AuthorDate: Thu Jul 16 11:34:43 2020 +0800

    [SCB-2043] flow control support leak bucket and token bucket
---
 .../java/org/apache/servicecomb/qps/Config.java    |   9 ++
 .../qps/ConsumerQpsFlowControlHandler.java         |   7 +-
 .../qps/ProviderQpsFlowControlHandler.java         |  15 +-
 .../servicecomb/qps/QpsControllerManager.java      | 144 +++++++++++-------
 .../org/apache/servicecomb/qps/QpsStrategy.java    |  23 +++
 .../qps/strategy/AbstractQpsStrategy.java          |  66 +++++++++
 .../FixedWindowStrategy.java}                      |  34 ++---
 .../qps/strategy/LeakyBucketStrategy.java          |  79 ++++++++++
 .../qps/strategy/SlidingWindowStrategy.java        |  34 +++++
 .../servicecomb/qps/strategy/StrategyType.java     |  44 ++++++
 .../qps/strategy/TokenBucketStrategy.java          |  28 ++++
 .../servicecomb/qps/QpsControllerManagerTest.java  | 162 +++++++++++----------
 .../qps/TestConsumerQpsFlowControlHandler.java     |  36 ++---
 .../qps/TestProviderQpsFlowControlHandler.java     |  20 +--
 .../apache/servicecomb/qps/TestQpsStrategy.java    |  52 +++++++
 .../router/custom/RouterInvokeFilter.java          |   2 +-
 16 files changed, 564 insertions(+), 191 deletions(-)

diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java
index 2c6d69a..ea8e4a1 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java
@@ -26,6 +26,15 @@ import com.netflix.config.DynamicPropertyFactory;
 public final class Config {
   private static final Logger LOGGER = LoggerFactory.getLogger(Config.class);
 
+  public static final String STRATEGY_KEY_PREFIX = "servicecomb.flowcontrol.strategy";
+
+  public static final String CONSUMER_BUCKET_KEY_PREFIX = "servicecomb.flowcontrol.Consumer.qps.bucket.";
+
+  public static final String PROVIDER_BUCKET_KEY_PREFIX = "servicecomb.flowcontrol.Provider.qps.bucket.";
+
+  public static final String PROVIDER_BUCKET_KEY_GLOBAL =
+      "servicecomb.flowcontrol.Provider.qps.global.bucket";
+
   public static final String CONSUMER_LIMIT_KEY_PREFIX = "servicecomb.flowcontrol.Consumer.qps.limit.";
 
   public static final String PROVIDER_LIMIT_KEY_PREFIX = "servicecomb.flowcontrol.Provider.qps.limit.";
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerQpsFlowControlHandler.java
index bc82c6c..0972433 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerQpsFlowControlHandler.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerQpsFlowControlHandler.java
@@ -29,7 +29,8 @@ import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
  */
 public class ConsumerQpsFlowControlHandler implements Handler {
   static final QpsControllerManager qpsControllerMgr = new QpsControllerManager()
-      .setConfigKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX);
+      .setLimitKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX)
+      .setBucketKeyPrefix(Config.CONSUMER_BUCKET_KEY_PREFIX);
 
   @Override
   public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception {
@@ -38,8 +39,8 @@ public class ConsumerQpsFlowControlHandler implements Handler {
       return;
     }
 
-    QpsController qpsController = qpsControllerMgr.getOrCreate(invocation.getMicroserviceName(), invocation);
-    if (qpsController.isLimitNewRequest()) {
+    QpsStrategy qpsStrategy = qpsControllerMgr.getOrCreate(invocation.getMicroserviceName(), invocation);
+    if (qpsStrategy.isLimitNewRequest()) {
       // return http status 429
       CommonExceptionData errorData = new CommonExceptionData("rejected by qps flowcontrol");
       asyncResp.consumerFail(
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderQpsFlowControlHandler.java
index 67ade94..c5e4445 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderQpsFlowControlHandler.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderQpsFlowControlHandler.java
@@ -27,8 +27,9 @@ import org.springframework.util.StringUtils;
 
 public class ProviderQpsFlowControlHandler implements Handler {
   static final QpsControllerManager qpsControllerMgr = new QpsControllerManager()
-      .setConfigKeyPrefix(Config.PROVIDER_LIMIT_KEY_PREFIX)
-      .setGlobalQpsController(Config.PROVIDER_LIMIT_KEY_GLOBAL);
+      .setLimitKeyPrefix(Config.PROVIDER_LIMIT_KEY_PREFIX)
+      .setBucketKeyPrefix(Config.PROVIDER_BUCKET_KEY_PREFIX)
+      .setGlobalQpsStrategy(Config.PROVIDER_LIMIT_KEY_GLOBAL, Config.PROVIDER_BUCKET_KEY_GLOBAL);
 
   @Override
   public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception {
@@ -46,15 +47,15 @@ public class ProviderQpsFlowControlHandler implements Handler {
     }
 
     String microserviceName = invocation.getContext(Const.SRC_MICROSERVICE);
-    QpsController qpsController =
+    QpsStrategy qpsStrategy =
         StringUtils.isEmpty(microserviceName)
-            ? qpsControllerMgr.getGlobalQpsController()
+            ? qpsControllerMgr.getGlobalQpsStrategy()
             : qpsControllerMgr.getOrCreate(microserviceName, invocation);
-    isLimitNewRequest(qpsController, asyncResp);
+    isLimitNewRequest(qpsStrategy, asyncResp);
   }
 
-  private boolean isLimitNewRequest(QpsController qpsController, AsyncResponse asyncResp) {
-    if (qpsController.isLimitNewRequest()) {
+  private boolean isLimitNewRequest(QpsStrategy qpsStrategy, AsyncResponse asyncResp) {
+    if (qpsStrategy.isLimitNewRequest()) {
       CommonExceptionData errorData = new CommonExceptionData("rejected by qps flowcontrol");
       asyncResp.producerFail(new InvocationException(QpsConst.TOO_MANY_REQUESTS_STATUS, errorData));
       return true;
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java
index d637e1f..4a989e7 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java
@@ -22,6 +22,11 @@ import java.util.Map.Entry;
 
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.apache.servicecomb.qps.strategy.AbstractQpsStrategy;
+import org.apache.servicecomb.qps.strategy.FixedWindowStrategy;
+import org.apache.servicecomb.qps.strategy.LeakyBucketStrategy;
+import org.apache.servicecomb.qps.strategy.StrategyType;
+import org.apache.servicecomb.qps.strategy.TokenBucketStrategy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -33,31 +38,34 @@ public class QpsControllerManager {
   /**
    * Describe the relationship between configuration and qpsController.
    */
-  protected final Map<String, QpsController> configQpsControllerMap = new ConcurrentHashMapEx<>();
+  protected final Map<String, AbstractQpsStrategy> configQpsControllerMap = new ConcurrentHashMapEx<>();
 
   /**
    * Describe the relationship between qualifiedKey(format is "microservice.schema.operation") and qpsController.
    */
-  protected final Map<String, QpsController> qualifiedNameControllerMap = new ConcurrentHashMapEx<>();
+  protected final Map<String, AbstractQpsStrategy> qualifiedNameControllerMap = new ConcurrentHashMapEx<>();
 
-  protected QpsController globalQpsController;
+  protected AbstractQpsStrategy globalQpsStrategy;
 
   public static final String SEPARATOR = ".";
 
-  private String configKeyPrefix;
+  private String limitKeyPrefix;
 
-  public QpsController getOrCreate(String microserviceName, Invocation invocation) {
+  private String bucketKeyPrefix;
+
+  public QpsStrategy getOrCreate(String microserviceName, Invocation invocation) {
     return qualifiedNameControllerMap
-        .computeIfAbsent(microserviceName + SEPARATOR + invocation.getOperationMeta().getSchemaQualifiedName(), key -> {
-          return create(key, microserviceName, invocation);
-        });
+        .computeIfAbsent(
+            microserviceName + SEPARATOR + invocation.getOperationMeta().getSchemaQualifiedName(),
+            key -> create(key, microserviceName, invocation));
   }
 
   /**
    * Create relevant qpsLimit dynamicProperty and watch the configuration change.
    * Search and return a valid qpsController.
    */
-  protected QpsController create(String qualifiedNameKey, String microserviceName, Invocation invocation) {
+  protected AbstractQpsStrategy create(String qualifiedNameKey, String microserviceName,
+      Invocation invocation) {
     // create "microservice"
     createQpsControllerIfNotExist(microserviceName);
     // create "microservice.schema"
@@ -70,7 +78,7 @@ public class QpsControllerManager {
   }
 
   /**
-   * <p> Use qualifiedNameKey to search {@link QpsController}.
+   * <p> Use qualifiedNameKey to search {@link QpsStrategy}.
    * 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).</p>
    * <p> This method ensures that there is always an existing qpsController returned, as the relevant qpsController has
@@ -79,42 +87,42 @@ public class QpsControllerManager {
    * @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;
+  protected AbstractQpsStrategy searchQpsController(String qualifiedNameKey) {
+    AbstractQpsStrategy qpsStrategy = configQpsControllerMap.get(qualifiedNameKey);
+    if (isValidQpsController(qpsStrategy)) {
+      return qpsStrategy;
     }
 
     int index = qualifiedNameKey.lastIndexOf(SEPARATOR);
     while (index > 0) {
-      qpsController = configQpsControllerMap.get(qualifiedNameKey.substring(0, index));
-      if (isValidQpsController(qpsController)) {
-        return qpsController;
+      qpsStrategy = configQpsControllerMap.get(qualifiedNameKey.substring(0, index));
+      if (isValidQpsController(qpsStrategy)) {
+        return qpsStrategy;
       }
 
       index = qualifiedNameKey.lastIndexOf(SEPARATOR, index - 1);
     }
 
-    if (isValidQpsController(qpsController)) {
-      return qpsController;
+    if (isValidQpsController(qpsStrategy)) {
+      return qpsStrategy;
     }
 
-    if (null != globalQpsController) {
-      return globalQpsController;
+    if (null != globalQpsStrategy) {
+      return globalQpsStrategy;
     }
 
     // if null is returned, maybe the operation qps controller is not initiated correctly.
     // getOrCreateQpsController() should be invoked before.
-    return qpsController;
+    return qpsStrategy;
   }
 
-  private boolean keyMatch(String configKey, Entry<String, QpsController> controllerEntry) {
+  private boolean keyMatch(String configKey, Entry<String, AbstractQpsStrategy> controllerEntry) {
     return controllerEntry.getKey().equals(configKey)
         || controllerEntry.getKey().startsWith(configKey + SEPARATOR);
   }
 
-  private boolean isValidQpsController(QpsController qpsController) {
-    return null != qpsController && null != qpsController.getQpsLimit();
+  private boolean isValidQpsController(AbstractQpsStrategy qpsStrategy) {
+    return null != qpsStrategy && null != qpsStrategy.getQpsLimit();
   }
 
   private void createQpsControllerIfNotExist(String configKey) {
@@ -123,52 +131,86 @@ public class QpsControllerManager {
     }
 
     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());
+    DynamicProperty limitProperty = DynamicProperty.getInstance(limitKeyPrefix + configKey);
+    DynamicProperty bucketProperty = DynamicProperty.getInstance(bucketKeyPrefix + configKey);
+    AbstractQpsStrategy qpsStrategy = chooseStrategy(configKey, limitProperty.getLong(),
+        bucketProperty.getLong());
+
+    limitProperty.addCallback(() -> {
+      qpsStrategy.setQpsLimit(limitProperty.getLong());
+      LOGGER.info("Qps limit updated, configKey = [{}], value = [{}]", configKey,
+          limitProperty.getString());
       updateObjMap(configKey);
     });
+    bucketProperty.addCallback(() -> {
+      qpsStrategy.setBucketLimit(bucketProperty.getLong());
+      LOGGER.info("bucket limit updated, configKey = [{}], value = [{}]", configKey,
+          bucketProperty.getString());
+      updateObjMap(configKey);
+    });
+
+    configQpsControllerMap.put(configKey, qpsStrategy);
   }
 
   protected void updateObjMap(String configKey) {
-    for (Entry<String, QpsController> controllerEntry : qualifiedNameControllerMap.entrySet()) {
+    for (Entry<String, AbstractQpsStrategy> controllerEntry : qualifiedNameControllerMap
+        .entrySet()) {
       if (keyMatch(configKey, controllerEntry)) {
-        QpsController qpsController = searchQpsController(controllerEntry.getKey());
-        controllerEntry.setValue(qpsController);
+        AbstractQpsStrategy qpsStrategy = searchQpsController(controllerEntry.getKey());
+        controllerEntry.setValue(qpsStrategy);
         LOGGER.info("QpsController updated, operationId = [{}], configKey = [{}], qpsLimit = [{}]",
-            controllerEntry.getKey(), qpsController.getKey(), qpsController.getQpsLimit());
+            controllerEntry.getKey(), qpsStrategy.getKey(), qpsStrategy.getQpsLimit());
       }
     }
   }
 
-  public QpsControllerManager setConfigKeyPrefix(String configKeyPrefix) {
-    this.configKeyPrefix = configKeyPrefix;
+  public QpsControllerManager setLimitKeyPrefix(String limitKeyPrefix) {
+    this.limitKeyPrefix = limitKeyPrefix;
     return this;
   }
 
-  public QpsControllerManager setGlobalQpsController(String globalConfigKey) {
-    DynamicProperty globalQpsProperty = DynamicProperty.getInstance(globalConfigKey);
-    QpsController qpsController = new QpsController(globalConfigKey, globalQpsProperty.getInteger());
+  public QpsControllerManager setBucketKeyPrefix(String bucketKeyPrefix) {
+    this.bucketKeyPrefix = bucketKeyPrefix;
+    return this;
+  }
 
-    globalQpsProperty.addCallback(() -> {
-      qpsController.setQpsLimit(globalQpsProperty.getInteger());
-      LOGGER.info("Global qps limit update, value = [{}]", globalQpsProperty.getInteger());
+  public QpsControllerManager setGlobalQpsStrategy(String globalLimitKey, String globalBucketKey) {
+    DynamicProperty globalLimitProperty = DynamicProperty.getInstance(globalLimitKey);
+    DynamicProperty globalBucketProperty = DynamicProperty.getInstance(globalBucketKey);
+    globalQpsStrategy = chooseStrategy(globalLimitKey, globalLimitProperty.getLong(),
+        globalBucketProperty.getLong());
+    globalLimitProperty.addCallback(() -> {
+      globalQpsStrategy.setQpsLimit(globalLimitProperty.getLong());
+      LOGGER.info("Global qps limit update, value = [{}]", globalLimitProperty.getInteger());
+    });
+    globalBucketProperty.addCallback(() -> {
+      globalQpsStrategy.setBucketLimit(globalBucketProperty.getLong());
+      LOGGER.info("Global bucket limit update, value = [{}]", globalBucketProperty.getInteger());
     });
-
-    this.globalQpsController = qpsController;
     return this;
   }
 
-  public QpsController getGlobalQpsController() {
-    return globalQpsController;
+  private AbstractQpsStrategy chooseStrategy(String globalConfigKey, Long limit, Long bucket) {
+    String strategyKey = DynamicProperty.getInstance(Config.STRATEGY_KEY_PREFIX).getString();
+    AbstractQpsStrategy strategy;
+    switch (StrategyType.parseStrategyType(strategyKey)) {
+      case FixedWindow:
+        strategy = new FixedWindowStrategy(globalConfigKey, limit);
+        break;
+      case LeakyBucket:
+        strategy = new LeakyBucketStrategy(globalConfigKey, limit);
+        break;
+      case TokenBucket:
+        strategy = new TokenBucketStrategy(globalConfigKey, limit, bucket);
+        break;
+      case SlidingWindow:
+      default:
+        strategy = new FixedWindowStrategy(globalConfigKey, limit);
+    }
+    return strategy;
   }
 
-  protected DynamicProperty getDynamicProperty(String configKey) {
-    return DynamicProperty.getInstance(configKeyPrefix + configKey);
+  public QpsStrategy getGlobalQpsStrategy() {
+    return globalQpsStrategy;
   }
 }
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsStrategy.java
new file mode 100644
index 0000000..606d7b8
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsStrategy.java
@@ -0,0 +1,23 @@
+/*
+ * 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;
+
+public interface QpsStrategy {
+
+  boolean isLimitNewRequest();
+}
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java
new file mode 100644
index 0000000..9285142
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java
@@ -0,0 +1,66 @@
+/*
+ * 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.strategy;
+
+import org.apache.servicecomb.qps.QpsStrategy;
+
+/**
+ * @Date 2020/7/14
+ **/
+public class AbstractQpsStrategy implements QpsStrategy {
+
+  private Long qpsLimit;
+
+  private Long bucketLimit;
+
+  private String key;
+
+  public AbstractQpsStrategy(Long qpsLimit, String key) {
+    this.qpsLimit = qpsLimit;
+    this.key = key;
+  }
+
+  public Long getBucketLimit() {
+    return bucketLimit;
+  }
+
+  public void setBucketLimit(Long bucketLimit) {
+    this.bucketLimit = bucketLimit;
+  }
+
+  @Override
+  public boolean isLimitNewRequest() {
+    return true;
+  }
+
+  public void setQpsLimit(Long qpsLimit) {
+    this.qpsLimit = qpsLimit;
+  }
+
+  public Long getQpsLimit() {
+    return qpsLimit;
+  }
+
+  public String getKey() {
+    return key;
+  }
+
+  public void setKey(String key) {
+    this.key = key;
+  }
+}
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsController.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java
similarity index 77%
rename from handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsController.java
rename to handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java
index 5f294ba..01b6e31 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsController.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java
@@ -14,15 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.servicecomb.qps;
+package org.apache.servicecomb.qps.strategy;
 
 import java.util.concurrent.atomic.AtomicLong;
 
-public class QpsController {
-  private String key;
-
-  private Integer qpsLimit;
+/**
+ * @Date 2020/7/8
+ **/
+public class FixedWindowStrategy extends AbstractQpsStrategy {
 
   // Interval begin time
   private volatile long msCycleBegin;
@@ -35,26 +34,16 @@ public class QpsController {
 
   private static final int CYCLE_LENGTH = 1000;
 
-  public QpsController(String key, Integer qpsLimit) {
-    this.key = key;
-    this.qpsLimit = qpsLimit;
+  public FixedWindowStrategy(String key, Long qpsLimit) {
+    super(qpsLimit, key);
     this.msCycleBegin = System.currentTimeMillis();
   }
 
-  public String getKey() {
-    return key;
-  }
-
-  public Integer getQpsLimit() {
-    return qpsLimit;
-  }
-
-  public void setQpsLimit(Integer qpsLimit) {
-    this.qpsLimit = qpsLimit;
-  }
-
   // return true means new request need to be rejected
   public boolean isLimitNewRequest() {
+    if (this.getQpsLimit() == null) {
+      this.setQpsLimit(Long.MAX_VALUE);
+    }
     long newCount = requestCount.incrementAndGet();
     long msNow = System.currentTimeMillis();
     //Time jump cause the new request injected
@@ -66,7 +55,6 @@ public class QpsController {
 
     // Configuration update and use is at the situation of multi-threaded concurrency
     // It is possible that operation level updated to null,but schema level or microservice level does not updated
-    int limitValue = (qpsLimit == null) ? Integer.MAX_VALUE : qpsLimit;
-    return newCount - lastRequestCount >= limitValue;
+    return newCount - lastRequestCount >= this.getQpsLimit();
   }
 }
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java
new file mode 100644
index 0000000..9be7f2e
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java
@@ -0,0 +1,79 @@
+/*
+ * 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.strategy;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * leaky bucket algorithm include 2 implementation :
+ * 1. as a meter : it's same as the token bucket.
+ * 2. as a queue : the bucket size equal to qpsLimit.
+ *
+ * @Date 2020/7/7
+ **/
+public class LeakyBucketStrategy extends AbstractQpsStrategy {
+
+  // Request count between Interval begin and now in one interval
+  private volatile AtomicLong requestCount = new AtomicLong();
+
+  private volatile long lastTime;
+
+  private long remainder = 0;
+
+  public LeakyBucketStrategy(String key, Long qpsLimit) {
+    super(qpsLimit, key);
+    this.setBucketLimit(qpsLimit);
+  }
+
+  public LeakyBucketStrategy(String key, Long qpsLimit, Long bucketLimit) {
+    super(qpsLimit, key);
+    this.setBucketLimit(bucketLimit);
+  }
+
+  /**
+   * @return
+   */
+  @Override
+  public boolean isLimitNewRequest() {
+    if (this.getQpsLimit() == null) {
+      this.setQpsLimit(Long.MAX_VALUE);
+    }
+    if (this.getBucketLimit() == null) {
+      this.setBucketLimit(
+          this.getQpsLimit() <= Long.MAX_VALUE / 2 ? this.getQpsLimit() * 2 : this.getQpsLimit());
+    }
+    long nowTime = System.currentTimeMillis();
+    //get the num of te period time
+    long leakCount = ((nowTime - lastTime + remainder) / 1000) * this.getQpsLimit();
+    remainder = (nowTime - lastTime + remainder) % 1000;
+    // leak the request , if leak
+    if (requestCount.longValue() > leakCount) {
+      requestCount.addAndGet(-leakCount);
+    } else {
+      requestCount.set(0);
+    }
+    lastTime = nowTime;
+    //compute this time
+    if (requestCount.longValue() < this.getBucketLimit()) {
+      requestCount.incrementAndGet();
+      return false;
+    }
+    return true;
+  }
+
+}
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/SlidingWindowStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/SlidingWindowStrategy.java
new file mode 100644
index 0000000..4671ba2
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/SlidingWindowStrategy.java
@@ -0,0 +1,34 @@
+/*
+ * 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.strategy;
+
+
+/**
+ * @Date 2020/7/8
+ **/
+public class SlidingWindowStrategy extends AbstractQpsStrategy {
+
+  public SlidingWindowStrategy(long qpsLimit, String key) {
+    super(qpsLimit, key);
+  }
+
+  @Override
+  public boolean isLimitNewRequest() {
+    return true;
+  }
+}
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java
new file mode 100644
index 0000000..8aa241b
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java
@@ -0,0 +1,44 @@
+/*
+ * 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.strategy;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @Author GuoYl123
+ * @Date 2020/7/13
+ **/
+public enum StrategyType {
+  TokenBucket,
+  LeakyBucket,
+  FixedWindow,
+  SlidingWindow;
+
+
+  public static StrategyType parseStrategyType(String type) {
+    if (StringUtils.isEmpty(type)) {
+      return StrategyType.FixedWindow;
+    }
+
+    try {
+      return StrategyType.valueOf(type.toUpperCase());
+    } catch (IllegalArgumentException e) {
+      return StrategyType.FixedWindow;
+    }
+  }
+}
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java
new file mode 100644
index 0000000..582cbe6
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java
@@ -0,0 +1,28 @@
+/*
+ * 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.strategy;
+
+/**
+ * @Date 2020/7/16
+ **/
+public class TokenBucketStrategy extends LeakyBucketStrategy {
+
+  public TokenBucketStrategy(String key, Long qpsLimit, Long bucketLimit) {
+    super(key, qpsLimit, bucketLimit);
+  }
+}
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
index 44b86b2..6089eac 100644
--- 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
@@ -23,6 +23,7 @@ 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.apache.servicecomb.qps.strategy.AbstractQpsStrategy;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -58,30 +59,30 @@ public class QpsControllerManagerTest {
       }
     };
     QpsControllerManager testQpsControllerManager = new QpsControllerManager()
-        .setConfigKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX);
+        .setLimitKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX);
     initTestQpsControllerManager(testQpsControllerManager, invocation, operationMeta);
 
     // pojo
     setConfigWithDefaultPrefix("pojo", 100);
-    QpsController qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo", qpsController.getKey());
-    Assert.assertTrue(100 == qpsController.getQpsLimit());
-    qpsController = testQpsControllerManager.getOrCreate("pojo2", invocation);
-    Assert.assertEquals("pojo2", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
-    qpsController = testQpsControllerManager.getOrCreate("poj", invocation);
-    Assert.assertEquals("poj", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation);
+    Assert.assertEquals("pojo2", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation);
+    Assert.assertEquals("poj", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     ArchaiusUtils.setProperty("servicecomb.flowcontrol.Consumer.qps.limit.poj.server", 10000);
-    qpsController = testQpsControllerManager.getOrCreate("poj", invocation);
-    Assert.assertEquals("poj.server", qpsController.getKey());
-    Assert.assertEquals(qpsController.getQpsLimit(), (Integer) 10000);
+    qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation);
+    Assert.assertEquals("poj.server", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertEquals(((AbstractQpsStrategy) qpsStrategy).getQpsLimit(), (Long) 10000L);
 
     ArchaiusUtils.setProperty("servicecomb.flowcontrol.Consumer.qps.limit.poj.server.test", 20000);
-    qpsController = testQpsControllerManager.getOrCreate("poj", invocation);
-    Assert.assertEquals("poj.server.test", qpsController.getKey());
-    Assert.assertEquals(qpsController.getQpsLimit(), (Integer) 20000);
+    qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation);
+    Assert.assertEquals("poj.server.test", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertEquals(((AbstractQpsStrategy) qpsStrategy).getQpsLimit(), (Long) 20000L);
 
     testGetOrCreateCommon(testQpsControllerManager, invocation, operationMeta);
   }
@@ -100,32 +101,32 @@ public class QpsControllerManagerTest {
     };
 
     QpsControllerManager testQpsControllerManager = new QpsControllerManager()
-        .setGlobalQpsController(Config.PROVIDER_LIMIT_KEY_GLOBAL)
-        .setConfigKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX);
+        .setGlobalQpsStrategy(Config.PROVIDER_LIMIT_KEY_GLOBAL, Config.PROVIDER_BUCKET_KEY_GLOBAL)
+        .setLimitKeyPrefix(Config.CONSUMER_LIMIT_KEY_PREFIX);
 
     // global
     setConfig(Config.PROVIDER_LIMIT_KEY_GLOBAL, 50);
-    QpsController qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
-    Assert.assertTrue(50 == qpsController.getQpsLimit());
-    qpsController = testQpsControllerManager.getOrCreate("pojo2", invocation);
-    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
-    Assert.assertTrue(50 == qpsController.getQpsLimit());
-    qpsController = testQpsControllerManager.getOrCreate("poj", invocation);
-    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
-    Assert.assertTrue(50 == qpsController.getQpsLimit());
+    QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation);
+    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation);
+    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     // pojo
     setConfigWithDefaultPrefix("pojo", 100);
-    qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo", qpsController.getKey());
-    Assert.assertTrue(100 == qpsController.getQpsLimit());
-    qpsController = testQpsControllerManager.getOrCreate("pojo2", invocation);
-    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
-    Assert.assertTrue(50 == qpsController.getQpsLimit());
-    qpsController = testQpsControllerManager.getOrCreate("poj", invocation);
-    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, qpsController.getKey());
-    Assert.assertTrue(50 == qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation);
+    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation);
+    Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     testGetOrCreateCommon(testQpsControllerManager, invocation, operationMeta);
   }
@@ -143,9 +144,9 @@ public class QpsControllerManagerTest {
       }
     };
     QpsControllerManager qpsControllerManager = new QpsControllerManager();
-    QpsController qpsController = qpsControllerManager.getOrCreate("service", invocation);
-    Assert.assertEquals("service", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    QpsStrategy qpsStrategy = qpsControllerManager.getOrCreate("service", invocation);
+    Assert.assertEquals("service", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     new Expectations() {
       {
@@ -157,9 +158,9 @@ public class QpsControllerManagerTest {
         result = "test_schema.test_opr";
       }
     };
-    qpsController = qpsControllerManager.getOrCreate("test_service", invocation);
-    Assert.assertEquals("test_service", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    qpsStrategy = qpsControllerManager.getOrCreate("test_service", invocation);
+    Assert.assertEquals("test_service", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     new Expectations() {
       {
@@ -171,9 +172,9 @@ public class QpsControllerManagerTest {
         result = "test-schema.test-opr";
       }
     };
-    qpsController = qpsControllerManager.getOrCreate("test-service", invocation);
-    Assert.assertEquals("test-service", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    qpsStrategy = qpsControllerManager.getOrCreate("test-service", invocation);
+    Assert.assertEquals("test-service", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     new Expectations() {
       {
@@ -185,9 +186,9 @@ public class QpsControllerManagerTest {
         result = "schema.opr.tail";
       }
     };
-    qpsController = qpsControllerManager.getOrCreate("svc", invocation);
-    Assert.assertEquals("svc", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    qpsStrategy = qpsControllerManager.getOrCreate("svc", invocation);
+    Assert.assertEquals("svc", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     new Expectations() {
       {
@@ -199,9 +200,9 @@ public class QpsControllerManagerTest {
         result = "schema.opr2.tail";
       }
     };
-    qpsController = qpsControllerManager.getOrCreate("svc", invocation);
-    Assert.assertEquals("svc", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    qpsStrategy = qpsControllerManager.getOrCreate("svc", invocation);
+    Assert.assertEquals("svc", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
   }
 
   private void testGetOrCreateCommon(QpsControllerManager testQpsControllerManager, Invocation invocation,
@@ -215,9 +216,9 @@ public class QpsControllerManagerTest {
       }
     };
     setConfigWithDefaultPrefix("pojo.server", 200);
-    QpsController qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo.server", qpsController.getKey());
-    Assert.assertTrue(200 == qpsController.getQpsLimit());
+    QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(200 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
     new Expectations() {
       {
         invocation.getOperationMeta();
@@ -226,9 +227,9 @@ public class QpsControllerManagerTest {
         result = "server2.test";
       }
     };
-    qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo", qpsController.getKey());
-    Assert.assertTrue(100 == qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
     new Expectations() {
       {
         invocation.getOperationMeta();
@@ -237,9 +238,9 @@ public class QpsControllerManagerTest {
         result = "serve.test";
       }
     };
-    qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo", qpsController.getKey());
-    Assert.assertTrue(100 == qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     // pojo.server.test
     new Expectations() {
@@ -251,9 +252,9 @@ public class QpsControllerManagerTest {
       }
     };
     setConfigWithDefaultPrefix("pojo.server.test", 300);
-    qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo.server.test", qpsController.getKey());
-    Assert.assertTrue(300 == qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo.server.test", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(300 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
     new Expectations() {
       {
         invocation.getOperationMeta();
@@ -262,9 +263,9 @@ public class QpsControllerManagerTest {
         result = "server.test2";
       }
     };
-    qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo.server", qpsController.getKey());
-    Assert.assertTrue(200 == qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(200 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
     new Expectations() {
       {
         invocation.getOperationMeta();
@@ -274,9 +275,9 @@ public class QpsControllerManagerTest {
         result = "server.tes";
       }
     };
-    qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo.server", qpsController.getKey());
-    Assert.assertTrue(200 == qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertTrue(200 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
   }
 
   /**
@@ -295,9 +296,9 @@ public class QpsControllerManagerTest {
         result = "server.test";
       }
     };
-    QpsController qpsController = testQpsControllerManager.getOrCreate("pojo", invocation);
-    Assert.assertEquals("pojo", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation);
+    Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     // pojo.server.test2
     new Expectations() {
@@ -362,9 +363,9 @@ public class QpsControllerManagerTest {
         result = "server.test";
       }
     };
-    qpsController = testQpsControllerManager.getOrCreate("pojo2", invocation);
-    Assert.assertEquals("pojo2", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation);
+    Assert.assertEquals("pojo2", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
 
     // poj.server.test
     new Expectations() {
@@ -377,9 +378,9 @@ public class QpsControllerManagerTest {
         result = "server.test";
       }
     };
-    qpsController = testQpsControllerManager.getOrCreate("poj", invocation);
-    Assert.assertEquals("poj", qpsController.getKey());
-    Assert.assertNull(qpsController.getQpsLimit());
+    qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation);
+    Assert.assertEquals("poj", ((AbstractQpsStrategy) qpsStrategy).getKey());
+    Assert.assertNull(((AbstractQpsStrategy) qpsStrategy).getQpsLimit());
   }
 
   @Test
@@ -431,9 +432,10 @@ public class QpsControllerManagerTest {
   }
 
   public static void clearState(QpsControllerManager qpsControllerManager) {
-    Map<String, QpsController> objMap = Deencapsulation.getField(qpsControllerManager, "qualifiedNameControllerMap");
+    Map<String, QpsStrategy> objMap = Deencapsulation
+        .getField(qpsControllerManager, "qualifiedNameControllerMap");
     objMap.clear();
-    Map<String, QpsController> configQpsControllerMap = Deencapsulation
+    Map<String, QpsStrategy> configQpsControllerMap = Deencapsulation
         .getField(qpsControllerManager, "configQpsControllerMap");
     configQpsControllerMap.clear();
   }
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 b472a85..619ef76 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
@@ -24,6 +24,8 @@ 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.qps.strategy.AbstractQpsStrategy;
+import org.apache.servicecomb.qps.strategy.FixedWindowStrategy;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
 import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
@@ -68,23 +70,23 @@ public class TestConsumerQpsFlowControlHandler {
 
   @Test
   public void testQpsController() {
-    QpsController qpsController = new QpsController("abc", 100);
-    Assert.assertEquals(false, qpsController.isLimitNewRequest());
+    AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy("abc", 100L);
+    Assert.assertEquals(false, qpsStrategy.isLimitNewRequest());
 
-    qpsController.setQpsLimit(1);
-    Assert.assertEquals(true, qpsController.isLimitNewRequest());
+    qpsStrategy.setQpsLimit(1L);
+    Assert.assertEquals(true, qpsStrategy.isLimitNewRequest());
   }
 
   @Test
   public void testHandle() throws Exception {
     String key = "svc.schema.opr";
-    QpsController qpsController = new QpsController("key", 12);
+    AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy("key", 12L);
     Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
     Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("schema.opr");
     Mockito.when(invocation.getSchemaId()).thenReturn("schema");
     Mockito.when(invocation.getMicroserviceName()).thenReturn("svc");
-    setQpsController(key, qpsController);
-    new MockUp<QpsController>() {
+    setQpsController(key, qpsStrategy);
+    new MockUp<FixedWindowStrategy>() {
       @Mock
       public boolean isLimitNewRequest() {
         return true;
@@ -93,8 +95,8 @@ public class TestConsumerQpsFlowControlHandler {
 
     new MockUp<QpsControllerManager>() {
       @Mock
-      protected QpsController create(String qualifiedNameKey) {
-        return qpsController;
+      protected QpsStrategy create(String qualifiedNameKey) {
+        return qpsStrategy;
       }
     };
 
@@ -111,14 +113,14 @@ public class TestConsumerQpsFlowControlHandler {
   @Test
   public void testHandleIsLimitNewRequestAsFalse() throws Exception {
     String key = "service.schema.id";
-    QpsController qpsController = new QpsController("service", 12);
+    AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy("service", 12L);
     Mockito.when(invocation.getMicroserviceName()).thenReturn("service");
     Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
 
     Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("schema.id");
-    setQpsController(key, qpsController);
+    setQpsController(key, qpsStrategy);
 
-    new MockUp<QpsController>() {
+    new MockUp<QpsStrategy>() {
       @Mock
       public boolean isLimitNewRequest() {
         return false;
@@ -128,8 +130,8 @@ public class TestConsumerQpsFlowControlHandler {
     new MockUp<QpsControllerManager>() {
 
       @Mock
-      protected QpsController create(String qualifiedNameKey) {
-        return qpsController;
+      protected QpsStrategy create(String qualifiedNameKey) {
+        return qpsStrategy;
       }
     };
     handler.handle(invocation, asyncResp);
@@ -137,10 +139,10 @@ public class TestConsumerQpsFlowControlHandler {
     Mockito.verify(invocation).next(asyncResp);
   }
 
-  private void setQpsController(String key, QpsController qpsController) {
+  private void setQpsController(String key, QpsStrategy qpsStrategy) {
     QpsControllerManager qpsControllerManager = Deencapsulation.getField(handler, "qpsControllerMgr");
-    ConcurrentHashMap<String, QpsController> objMap = Deencapsulation
+    ConcurrentHashMap<String, QpsStrategy> objMap = Deencapsulation
         .getField(qpsControllerManager, "qualifiedNameControllerMap");
-    objMap.put(key, qpsController);
+    objMap.put(key, qpsStrategy);
   }
 }
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 d5a7267..6182007 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
@@ -26,6 +26,8 @@ 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.qps.strategy.AbstractQpsStrategy;
+import org.apache.servicecomb.qps.strategy.FixedWindowStrategy;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
 import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
@@ -97,11 +99,11 @@ public class TestProviderQpsFlowControlHandler {
 
   @Test
   public void testQpsController() {
-    QpsController qpsController = new QpsController("abc", 100);
-    assertFalse(qpsController.isLimitNewRequest());
+    AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy("abc", 100L);
+    assertFalse(qpsStrategy.isLimitNewRequest());
 
-    qpsController.setQpsLimit(1);
-    assertTrue(qpsController.isLimitNewRequest());
+    qpsStrategy.setQpsLimit(1L);
+    assertTrue(qpsStrategy.isLimitNewRequest());
   }
 
   @Test
@@ -111,7 +113,7 @@ public class TestProviderQpsFlowControlHandler {
     Mockito.when(invocation.getHandlerIndex()).thenReturn(0);
     ArchaiusUtils.setProperty("servicecomb.flowcontrol.Provider.qps.global.limit", 1);
     ProviderQpsFlowControlHandler.qpsControllerMgr
-        .setGlobalQpsController("servicecomb.flowcontrol.Provider.qps.global.limit");
+        .setGlobalQpsStrategy(Config.PROVIDER_LIMIT_KEY_GLOBAL, Config.PROVIDER_BUCKET_KEY_GLOBAL);
 
     handler.handle(invocation, asyncResp);
     handler.handle(invocation, asyncResp);
@@ -141,8 +143,8 @@ public class TestProviderQpsFlowControlHandler {
 
     new MockUp<QpsControllerManager>() {
       @Mock
-      protected QpsController create(String qualifiedNameKey) {
-        return new QpsController(qualifiedNameKey, 1);
+      protected QpsStrategy create(String qualifiedNameKey) {
+        return new FixedWindowStrategy(qualifiedNameKey, 1L);
       }
     };
 
@@ -168,8 +170,8 @@ public class TestProviderQpsFlowControlHandler {
 
     new MockUp<QpsControllerManager>() {
       @Mock
-      protected QpsController create(String qualifiedNameKey) {
-        return new QpsController(qualifiedNameKey, 1);
+      protected QpsStrategy create(String qualifiedNameKey) {
+        return new FixedWindowStrategy(qualifiedNameKey, 1L);
       }
     };
     handler.handle(invocation, asyncResp);
diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java
new file mode 100644
index 0000000..75beb71
--- /dev/null
+++ b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java
@@ -0,0 +1,52 @@
+/*
+ * 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.qps.strategy.AbstractQpsStrategy;
+import org.apache.servicecomb.qps.strategy.FixedWindowStrategy;
+import org.apache.servicecomb.qps.strategy.LeakyBucketStrategy;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @Author GuoYl123
+ * @Date 2020/7/16
+ **/
+public class TestQpsStrategy {
+
+  @Test
+  public void testFixedWindowStrategy() {
+    AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy("abc", 100L);
+    Assert.assertEquals(false, qpsStrategy.isLimitNewRequest());
+
+    qpsStrategy.setQpsLimit(1L);
+    Assert.assertEquals(true, qpsStrategy.isLimitNewRequest());
+  }
+
+
+  @Test
+  public void testLeakyBucketStrategy() {
+    LeakyBucketStrategy qpsStrategy = new LeakyBucketStrategy("abc", 100L);
+    Assert.assertEquals(false, qpsStrategy.isLimitNewRequest());
+
+    qpsStrategy.setQpsLimit(1L);
+    qpsStrategy.setBucketLimit(1L);
+    Assert.assertEquals(true, qpsStrategy.isLimitNewRequest());
+  }
+
+}
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterInvokeFilter.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterInvokeFilter.java
index 97858a9..7e345a9 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterInvokeFilter.java
+++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterInvokeFilter.java
@@ -109,7 +109,7 @@ public class RouterInvokeFilter implements HttpServerFilter {
   private boolean isHaveHeadersRule() {
     DynamicStringProperty headerStr = DynamicPropertyFactory.getInstance()
         .getStringProperty(SERVICECOMB_ROUTER_HEADER, null);
-    return !StringUtils.isEmpty(headerStr.get());
+    return StringUtils.isNotEmpty(headerStr.get());
   }
 
   private boolean addAllHeaders(String str) {


[servicecomb-java-chassis] 02/02: [SCB-2043] modify as comment, change strategy when strategy change.

Posted by li...@apache.org.
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 88c24e95746cb143edf2405696004d9946aa04f0
Author: GuoYL <gy...@gmail.com>
AuthorDate: Fri Jul 17 16:26:35 2020 +0800

    [SCB-2043] modify as comment, change strategy when strategy change.
---
 .../servicecomb/qps/QpsControllerManager.java      | 28 ++++++++++++++----
 .../qps/strategy/AbstractQpsStrategy.java          |  4 +--
 .../qps/strategy/FixedWindowStrategy.java          |  3 --
 .../qps/strategy/LeakyBucketStrategy.java          |  6 +---
 .../qps/strategy/SlidingWindowStrategy.java        | 34 ----------------------
 .../servicecomb/qps/strategy/StrategyType.java     |  4 ---
 .../qps/strategy/TokenBucketStrategy.java          |  3 --
 .../org/apache/servicecomb/qps/TestConfig.java     |  4 ---
 8 files changed, 25 insertions(+), 61 deletions(-)

diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java
index 4a989e7..40e25c5 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java
@@ -133,9 +133,19 @@ public class QpsControllerManager {
     LOGGER.info("Create qpsController, configKey = [{}]", configKey);
     DynamicProperty limitProperty = DynamicProperty.getInstance(limitKeyPrefix + configKey);
     DynamicProperty bucketProperty = DynamicProperty.getInstance(bucketKeyPrefix + configKey);
+    DynamicProperty strategyProperty = DynamicProperty
+        .getInstance(Config.STRATEGY_KEY_PREFIX);
     AbstractQpsStrategy qpsStrategy = chooseStrategy(configKey, limitProperty.getLong(),
-        bucketProperty.getLong());
-
+        bucketProperty.getLong(), strategyProperty.getString());
+
+    strategyProperty.addCallback(() -> {
+      AbstractQpsStrategy innerQpsStrategy = chooseStrategy(configKey, limitProperty.getLong(),
+          bucketProperty.getLong(), strategyProperty.getString());
+      configQpsControllerMap.put(configKey, innerQpsStrategy);
+      LOGGER.info("Global flow control strategy update, value = [{}]",
+          strategyProperty.getString());
+      updateObjMap(configKey);
+    });
     limitProperty.addCallback(() -> {
       qpsStrategy.setQpsLimit(limitProperty.getLong());
       LOGGER.info("Qps limit updated, configKey = [{}], value = [{}]", configKey,
@@ -177,8 +187,16 @@ public class QpsControllerManager {
   public QpsControllerManager setGlobalQpsStrategy(String globalLimitKey, String globalBucketKey) {
     DynamicProperty globalLimitProperty = DynamicProperty.getInstance(globalLimitKey);
     DynamicProperty globalBucketProperty = DynamicProperty.getInstance(globalBucketKey);
+    DynamicProperty globalStrategyProperty = DynamicProperty
+        .getInstance(Config.STRATEGY_KEY_PREFIX);
     globalQpsStrategy = chooseStrategy(globalLimitKey, globalLimitProperty.getLong(),
-        globalBucketProperty.getLong());
+        globalBucketProperty.getLong(), globalStrategyProperty.getString());
+    globalStrategyProperty.addCallback(() -> {
+      globalQpsStrategy = chooseStrategy(globalLimitKey, globalLimitProperty.getLong(),
+          globalBucketProperty.getLong(), globalStrategyProperty.getString());
+      LOGGER.info("Global flow control strategy update, value = [{}]",
+          globalStrategyProperty.getString());
+    });
     globalLimitProperty.addCallback(() -> {
       globalQpsStrategy.setQpsLimit(globalLimitProperty.getLong());
       LOGGER.info("Global qps limit update, value = [{}]", globalLimitProperty.getInteger());
@@ -190,8 +208,8 @@ public class QpsControllerManager {
     return this;
   }
 
-  private AbstractQpsStrategy chooseStrategy(String globalConfigKey, Long limit, Long bucket) {
-    String strategyKey = DynamicProperty.getInstance(Config.STRATEGY_KEY_PREFIX).getString();
+  private AbstractQpsStrategy chooseStrategy(String globalConfigKey, Long limit, Long bucket,
+      String strategyKey) {
     AbstractQpsStrategy strategy;
     switch (StrategyType.parseStrategyType(strategyKey)) {
       case FixedWindow:
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java
index 9285142..4fc0ed8 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/AbstractQpsStrategy.java
@@ -19,9 +19,7 @@ package org.apache.servicecomb.qps.strategy;
 
 import org.apache.servicecomb.qps.QpsStrategy;
 
-/**
- * @Date 2020/7/14
- **/
+
 public class AbstractQpsStrategy implements QpsStrategy {
 
   private Long qpsLimit;
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java
index 01b6e31..74bb9b5 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java
@@ -18,9 +18,6 @@ package org.apache.servicecomb.qps.strategy;
 
 import java.util.concurrent.atomic.AtomicLong;
 
-/**
- * @Date 2020/7/8
- **/
 public class FixedWindowStrategy extends AbstractQpsStrategy {
 
   // Interval begin time
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java
index 9be7f2e..b2f4f3e 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java
@@ -24,7 +24,6 @@ import java.util.concurrent.atomic.AtomicLong;
  * 1. as a meter : it's same as the token bucket.
  * 2. as a queue : the bucket size equal to qpsLimit.
  *
- * @Date 2020/7/7
  **/
 public class LeakyBucketStrategy extends AbstractQpsStrategy {
 
@@ -45,9 +44,6 @@ public class LeakyBucketStrategy extends AbstractQpsStrategy {
     this.setBucketLimit(bucketLimit);
   }
 
-  /**
-   * @return
-   */
   @Override
   public boolean isLimitNewRequest() {
     if (this.getQpsLimit() == null) {
@@ -61,7 +57,7 @@ public class LeakyBucketStrategy extends AbstractQpsStrategy {
     //get the num of te period time
     long leakCount = ((nowTime - lastTime + remainder) / 1000) * this.getQpsLimit();
     remainder = (nowTime - lastTime + remainder) % 1000;
-    // leak the request , if leak
+    // leak the request
     if (requestCount.longValue() > leakCount) {
       requestCount.addAndGet(-leakCount);
     } else {
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/SlidingWindowStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/SlidingWindowStrategy.java
deleted file mode 100644
index 4671ba2..0000000
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/SlidingWindowStrategy.java
+++ /dev/null
@@ -1,34 +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.strategy;
-
-
-/**
- * @Date 2020/7/8
- **/
-public class SlidingWindowStrategy extends AbstractQpsStrategy {
-
-  public SlidingWindowStrategy(long qpsLimit, String key) {
-    super(qpsLimit, key);
-  }
-
-  @Override
-  public boolean isLimitNewRequest() {
-    return true;
-  }
-}
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java
index 8aa241b..5a9192a 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/StrategyType.java
@@ -19,10 +19,6 @@ package org.apache.servicecomb.qps.strategy;
 
 import org.apache.commons.lang3.StringUtils;
 
-/**
- * @Author GuoYl123
- * @Date 2020/7/13
- **/
 public enum StrategyType {
   TokenBucket,
   LeakyBucket,
diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java
index 582cbe6..68f3334 100644
--- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java
+++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/TokenBucketStrategy.java
@@ -17,9 +17,6 @@
 
 package org.apache.servicecomb.qps.strategy;
 
-/**
- * @Date 2020/7/16
- **/
 public class TokenBucketStrategy extends LeakyBucketStrategy {
 
   public TokenBucketStrategy(String key, Long qpsLimit, Long bucketLimit) {
diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java
index 04f9400..9035ba5 100644
--- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java
+++ b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java
@@ -23,10 +23,6 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-/**
- *
- *
- */
 public class TestConfig {
   @BeforeClass
   public static void classSetup() {