You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2021/08/12 12:30:16 UTC

[servicecomb-java-chassis] branch master updated: [#SCB-2271]refactoring router code (#2500)

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


The following commit(s) were added to refs/heads/master by this push:
     new bb49ed3  [#SCB-2271]refactoring router code (#2500)
bb49ed3 is described below

commit bb49ed3aee016938ead8516f70124ff3812d939d
Author: liubao68 <bi...@qq.com>
AuthorDate: Thu Aug 12 20:30:10 2021 +0800

    [#SCB-2271]refactoring router code (#2500)
    
    * [#SCB-2271]refactoring router code so that it can be used in spring cloud
    
    * [#SCB-2271]add an integration test for canary release
---
 .../servicecomb/samples/ConsumerController.java    |   6 +
 .../servicecomb/samples/ProviderService.java       |   2 +
 .../consumer/src/main/resources/application.yml    |  31 ++++-
 .../gateway/src/main/resources/application.yml     |   6 +-
 demo/demo-cse-v1/pom.xml                           |   1 +
 demo/demo-cse-v1/{ => provider-canary}/pom.xml     |  42 +++----
 .../servicecomb/samples/ProviderApplication.java}  |  31 +++--
 .../servicecomb/samples/ProviderController.java    |   7 +-
 .../src/main/resources/application.yml             |   6 +-
 .../provider-canary/src/main/resources/log4j2.xml  |  34 ++++--
 .../servicecomb/samples/ProviderController.java    |   5 +
 .../provider/src/main/resources/application.yml    |   2 +-
 .../apache/servicecomb/samples/HelloWorldIT.java   |  41 ++++++-
 .../test-client/src/main/resources/application.yml |   2 +-
 .../servicecomb/foundation/common}/Version.java    |   6 +-
 .../registry/api/registry/MicroserviceFactory.java |   2 +-
 .../registry/consumer/MicroserviceVersion.java     |   2 +-
 .../consumer/StaticMicroserviceVersions.java       |   2 +-
 .../servicecomb/registry/version/VersionRule.java  |   2 +
 .../registry/version/VersionRuleFixedParser.java   |   2 +
 .../registry/version/VersionRuleLatestParser.java  |   1 +
 .../registry/version/VersionRuleRangeParser.java   |   2 +
 .../version/VersionRuleStartFromParser.java        |   2 +
 .../servicecomb/registry/version/VersionUtils.java |   1 +
 .../servicecomb/registry/version/TestVersion.java  |   2 +-
 .../registry/version/TestVersionRule.java          |   3 +-
 .../registry/version/TestVersionUtils.java         |   3 +-
 .../servicecomb/registry/version/VersionConst.java |   2 +-
 governance/pom.xml                                 |   4 +
 .../apache/servicecomb/router/RouterFilter.java    |  26 ++--
 .../servicecomb/router/cache/RouterRuleCache.java  | 135 ++++++++++++++++++++
 .../distribute/AbstractRouterDistributor.java      |  34 ++----
 .../router/distribute/RouterDistributor.java       |   0
 .../exception/RouterIllegalParamException.java     |   0
 .../router/match/RouterRuleMatcher.java            |  26 ++--
 .../servicecomb/router/model/HeaderRule.java       |   0
 .../apache/servicecomb/router/model/Matcher.java   |   0
 .../servicecomb/router/model/PolicyRuleItem.java   |   0
 .../apache/servicecomb/router/model/RouteItem.java |   0
 .../servicecomb/router/model/ServiceInfoCache.java |   0
 .../apache/servicecomb/router/model/TagItem.java   |   0
 .../router/util/VersionCompareUtil.java            |   2 +-
 .../servicecomb/router/ExampleDistributor.java     |  24 ++--
 .../servicecomb/router/RouterDistributorTest.java  | 136 +++++++++------------
 .../org/apache/servicecomb/router/ServiceIns.java  |  50 ++++++--
 .../servicecomb/router/VersionCompareUtilTest.java |   0
 .../src/test/resources/META-INF/spring/bean.xml    |   2 +-
 handlers/handler-router/pom.xml                    |   4 +
 .../servicecomb/router/cache/RouterRuleCache.java  | 122 ------------------
 .../router/custom/RouterHeaderFilterExt.java       |   3 +-
 .../router/custom/RouterInvokeFilter.java          |  23 +---
 .../router/custom/RouterServerListFilter.java      |  15 ++-
 .../custom/ServiceCombCanaryDistributer.java       |  19 +--
 .../serviceregistry/MockMicroserviceVersions.java  |   2 +-
 .../client/LocalServiceRegistryClientImpl.java     |   2 +-
 55 files changed, 488 insertions(+), 389 deletions(-)

diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
index 4ed0ecd..940a79b 100644
--- a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
+++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
@@ -20,6 +20,7 @@ package org.apache.servicecomb.samples;
 import org.apache.servicecomb.provider.pojo.RpcReference;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
@@ -34,4 +35,9 @@ public class ConsumerController {
   public String sayHello(@RequestParam("name") String name) {
     return providerService.sayHello(name);
   }
+
+  @GetMapping("/sayHelloCanary")
+  public String sayHelloCanary(@RequestParam("name") String name) {
+    return providerService.sayHelloCanary(name);
+  }
 }
diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
index f327412..176bcee 100644
--- a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
+++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
@@ -19,4 +19,6 @@ package org.apache.servicecomb.samples;
 
 public interface ProviderService {
   String sayHello(String name);
+
+  String sayHelloCanary(String name);
 }
diff --git a/demo/demo-cse-v1/consumer/src/main/resources/application.yml b/demo/demo-cse-v1/consumer/src/main/resources/application.yml
index d61d76b..acc9b81 100644
--- a/demo/demo-cse-v1/consumer/src/main/resources/application.yml
+++ b/demo/demo-cse-v1/consumer/src/main/resources/application.yml
@@ -21,7 +21,7 @@ servicecomb-config-order: 10
 
 servicecomb:
   service:
-    application: demo-cse-v1
+    application: demo-java-chassis-cse-v1
     name: consumer
     version: 0.0.1
     registry:
@@ -36,6 +36,33 @@ servicecomb:
   rest:
     address: 0.0.0.0:9092  # should be same with server.port to use web container
 
+  routeRule:
+    provider: |
+      - precedence: 1
+        match:
+          headers:
+            canary:
+              exact: new
+        route:
+          - weight: 20
+            tags:
+              version: 0.0.1
+          - weight: 80
+            tags:
+              version: 0.0.2
+      - precedence: 2
+        match:
+          headers:
+            canary:
+              exact: old
+        route:
+          - weight: 100
+            tags:
+              version: 0.0.1
+  router:
+    type: router
+    header: canary
+
   # Configure AK/SK credentials if needed. Default not enabled.
   credentials:
     akskEnabled: true
@@ -43,3 +70,5 @@ servicecomb:
     secretKey: ${CREDENTIALS_SK}
     akskCustomCipher: default
     project: cn-south-1
+
+
diff --git a/demo/demo-cse-v1/gateway/src/main/resources/application.yml b/demo/demo-cse-v1/gateway/src/main/resources/application.yml
index a64212b..9f8b8c0 100644
--- a/demo/demo-cse-v1/gateway/src/main/resources/application.yml
+++ b/demo/demo-cse-v1/gateway/src/main/resources/application.yml
@@ -21,7 +21,7 @@ servicecomb-config-order: 100
 
 servicecomb:
   service:
-    application: demo-cse-v1
+    application: demo-java-chassis-cse-v1
     name: gateway
     version: 0.0.1
     registry:
@@ -50,6 +50,10 @@ servicecomb:
               microserviceName: consumer
               versionRule: 0.0.0+
 
+  router:
+    type: router
+    header: canary
+
   # Configure AK/SK credentials if needed. Default not enabled.
   credentials:
     akskEnabled: true
diff --git a/demo/demo-cse-v1/pom.xml b/demo/demo-cse-v1/pom.xml
index f4dfcf9..f5f54e2 100644
--- a/demo/demo-cse-v1/pom.xml
+++ b/demo/demo-cse-v1/pom.xml
@@ -49,6 +49,7 @@
 
   <modules>
     <module>provider</module>
+    <module>provider-canary</module>
     <module>consumer</module>
     <module>gateway</module>
     <module>test-client</module>
diff --git a/demo/demo-cse-v1/pom.xml b/demo/demo-cse-v1/provider-canary/pom.xml
similarity index 63%
copy from demo/demo-cse-v1/pom.xml
copy to demo/demo-cse-v1/provider-canary/pom.xml
index f4dfcf9..af8d9b5 100644
--- a/demo/demo-cse-v1/pom.xml
+++ b/demo/demo-cse-v1/provider-canary/pom.xml
@@ -22,36 +22,30 @@
 
   <parent>
     <groupId>org.apache.servicecomb.demo</groupId>
-    <artifactId>demo-parent</artifactId>
+    <artifactId>demo-cse-v1</artifactId>
     <version>2.5.0-SNAPSHOT</version>
   </parent>
-  <artifactId>demo-cse-v1</artifactId>
-  <name>Java Chassis::Demo::CSE-V1</name>
-  <packaging>pom</packaging>
+
+  <artifactId>cse-v1-provider-canary</artifactId>
+  <name>Java Chassis::Demo::CSE-V1::PROVIDER CANARY</name>
+  <packaging>jar</packaging>
+
+  <properties>
+  </properties>
+
   <dependencies>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
-      <artifactId>solution-basic</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.servicecomb</groupId>
-      <artifactId>dashboard</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.servicecomb</groupId>
-      <artifactId>registry-service-center</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.servicecomb</groupId>
-      <artifactId>servicestage-environment</artifactId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
     </dependency>
   </dependencies>
 
-  <modules>
-    <module>provider</module>
-    <module>consumer</module>
-    <module>gateway</module>
-    <module>test-client</module>
-  </modules>
-
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
 </project>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java
similarity index 57%
copy from demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
copy to demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java
index bce1456..6542bce 100644
--- a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
+++ b/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java
@@ -17,23 +17,20 @@
 
 package org.apache.servicecomb.samples;
 
-import org.apache.servicecomb.demo.CategorizedTestCase;
-import org.apache.servicecomb.demo.TestMgr;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
 
-@Component
-public class HelloWorldIT implements CategorizedTestCase {
-  RestTemplate template = new RestTemplate();
-
-  @Override
-  public void testRestTransport() throws Exception {
-    testHelloWorld();
-  }
-
-  private void testHelloWorld() {
-    String result = template
-        .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", String.class);
-    TestMgr.check("\"Hello World\"", result);
+@SpringBootApplication
+@EnableServiceComb
+public class ProviderApplication {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ProviderApplication.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
   }
 }
diff --git a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderController.java
similarity index 87%
copy from demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
copy to demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderController.java
index 6eea777..d5b8e13 100644
--- a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
+++ b/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderController.java
@@ -28,6 +28,11 @@ public class ProviderController {
   // a very simple service to echo the request parameter
   @GetMapping("/sayHello")
   public String sayHello(@RequestParam("name") String name) {
-    return "Hello " + name;
+    return "Hello in canary " + name;
+  }
+
+  @GetMapping("/sayHelloCanary")
+  public String sayHelloCanary(@RequestParam("name") String name) {
+    return "Hello Canary in canary " + name;
   }
 }
diff --git a/demo/demo-cse-v1/provider/src/main/resources/application.yml b/demo/demo-cse-v1/provider-canary/src/main/resources/application.yml
similarity index 92%
copy from demo/demo-cse-v1/provider/src/main/resources/application.yml
copy to demo/demo-cse-v1/provider-canary/src/main/resources/application.yml
index f898e4f..81bf7aa 100644
--- a/demo/demo-cse-v1/provider/src/main/resources/application.yml
+++ b/demo/demo-cse-v1/provider-canary/src/main/resources/application.yml
@@ -20,9 +20,9 @@ servicecomb-config-order: 10
 
 servicecomb:
   service:
-    application: demo-cse-v1
+    application: demo-java-chassis-cse-v1
     name: provider
-    version: 0.0.1
+    version: 0.0.2
     registry:
       address: https://cse.cn-south-1.myhuaweicloud.com
       instance:
@@ -32,7 +32,7 @@ servicecomb:
       serverUri: https://cse.cn-south-1.myhuaweicloud.com
 
   rest:
-    address: 0.0.0.0:9093 # should be same with server.port to use web container
+    address: 0.0.0.0:9095
 
 # Configure AK/SK credentials if needed. Default not enabled.
   credentials:
diff --git a/governance/src/test/resources/META-INF/spring/bean.xml b/demo/demo-cse-v1/provider-canary/src/main/resources/log4j2.xml
similarity index 51%
copy from governance/src/test/resources/META-INF/spring/bean.xml
copy to demo/demo-cse-v1/provider-canary/src/main/resources/log4j2.xml
index 7d5c1b0..56fc9a0 100644
--- a/governance/src/test/resources/META-INF/spring/bean.xml
+++ b/demo/demo-cse-v1/provider-canary/src/main/resources/log4j2.xml
@@ -16,12 +16,30 @@
   ~ limitations under the License.
   -->
 
-<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xmlns:cse="http://www.huawei.com/schema/paas/cse/rpc"
-  xsi:schemaLocation="
-		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+<!--this is sample configuration, please modify as your wish -->
 
-  <context:component-scan base-package="com.huaweicloud.governance,org.apache.servicecomb.governance"/>
-</beans>
+<configuration>
+  <Properties>
+    <Property name="log_path">./user/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
index 6eea777..9e1c8f9 100644
--- a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
+++ b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
@@ -30,4 +30,9 @@ public class ProviderController {
   public String sayHello(@RequestParam("name") String name) {
     return "Hello " + name;
   }
+
+  @GetMapping("/sayHelloCanary")
+  public String sayHelloCanary(@RequestParam("name") String name) {
+    return "Hello Canary " + name;
+  }
 }
diff --git a/demo/demo-cse-v1/provider/src/main/resources/application.yml b/demo/demo-cse-v1/provider/src/main/resources/application.yml
index f898e4f..370c3cd 100644
--- a/demo/demo-cse-v1/provider/src/main/resources/application.yml
+++ b/demo/demo-cse-v1/provider/src/main/resources/application.yml
@@ -20,7 +20,7 @@ servicecomb-config-order: 10
 
 servicecomb:
   service:
-    application: demo-cse-v1
+    application: demo-java-chassis-cse-v1
     name: provider
     version: 0.0.1
     registry:
diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
index bce1456..124df77 100644
--- a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
+++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
@@ -19,9 +19,14 @@ package org.apache.servicecomb.samples;
 
 import org.apache.servicecomb.demo.CategorizedTestCase;
 import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
 import org.springframework.stereotype.Component;
+import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 
+
 @Component
 public class HelloWorldIT implements CategorizedTestCase {
   RestTemplate template = new RestTemplate();
@@ -29,11 +34,41 @@ public class HelloWorldIT implements CategorizedTestCase {
   @Override
   public void testRestTransport() throws Exception {
     testHelloWorld();
+    testHelloWorldCanary();
   }
 
   private void testHelloWorld() {
-    String result = template
-        .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", String.class);
-    TestMgr.check("\"Hello World\"", result);
+    for (int i = 0; i < 10; i++) {
+      MultiValueMap<String, String> headers = new HttpHeaders();
+      headers.add("canary", "old");
+      HttpEntity<Object> entity = new HttpEntity<>(headers);
+      String result = template
+          .exchange(Config.GATEWAY_URL + "/sayHello?name=World", HttpMethod.GET, entity, String.class).getBody();
+      TestMgr.check("\"Hello World\"", result);
+    }
+  }
+
+  private void testHelloWorldCanary() {
+    int oldCount = 0;
+    int newCount = 0;
+
+    for (int i = 0; i < 20; i++) {
+      MultiValueMap<String, String> headers = new HttpHeaders();
+      headers.add("canary", "new");
+      HttpEntity<Object> entity = new HttpEntity<>(headers);
+      String result = template
+          .exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", HttpMethod.GET, entity, String.class).getBody();
+      if (result.equals("\"Hello Canary World\"")) {
+        oldCount++;
+      } else if (result.equals("\"Hello Canary in canary World\"")) {
+        newCount++;
+      } else {
+        TestMgr.fail("not expected result testHelloWorldCanary");
+        return;
+      }
+    }
+
+    double ratio = oldCount / (float) (oldCount + newCount);
+    TestMgr.check(ratio > 0.1 && ratio < 0.3, true);
   }
 }
diff --git a/demo/demo-cse-v1/test-client/src/main/resources/application.yml b/demo/demo-cse-v1/test-client/src/main/resources/application.yml
index f81a28a..63c28aa 100644
--- a/demo/demo-cse-v1/test-client/src/main/resources/application.yml
+++ b/demo/demo-cse-v1/test-client/src/main/resources/application.yml
@@ -20,7 +20,7 @@ servicecomb-config-order: 10
 
 servicecomb:
   service:
-    application: demo-cse-v1
+    application: demo-java-chassis-cse-v1
     name: test-client
     version: 0.0.1
     registry:
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/Version.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/Version.java
similarity index 95%
rename from foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/Version.java
rename to foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/Version.java
index 5416024..e09ad62 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/Version.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/Version.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.registry.version;
+package org.apache.servicecomb.foundation.common;
 
 import java.util.Objects;
 
-import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang3.ArrayUtils;
 
 // short version is enough
 public class Version implements Comparable<Version> {
@@ -50,7 +50,7 @@ public class Version implements Comparable<Version> {
     }
 
     if (versions.length < 4) {
-      versions = (String[]) ArrayUtils.addAll(versions, ZERO);
+      versions = ArrayUtils.addAll(versions, ZERO);
     }
     this.major = parseNumber("major", version, versions[0]);
     this.minor = parseNumber("minor", version, versions[1]);
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceFactory.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceFactory.java
index a66328a..e4bc812 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceFactory.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceFactory.java
@@ -31,7 +31,7 @@ import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.registry.config.ConfigurePropertyUtils;
 import org.apache.servicecomb.registry.config.MicroservicePropertiesLoader;
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 
 public class MicroserviceFactory {
   public Microservice create() {
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersion.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersion.java
index 9972819..2aca65e 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersion.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersion.java
@@ -26,7 +26,7 @@ import org.apache.servicecomb.registry.api.event.DestroyMicroserviceVersionEvent
 import org.apache.servicecomb.registry.api.registry.Microservice;
 import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.registry.DiscoveryManager;
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 
 public class MicroserviceVersion {
   protected AppManager appManager;
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java
index 08f1fdd..dae01c7 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java
@@ -25,7 +25,7 @@ import org.apache.servicecomb.registry.api.registry.FindInstancesResponse;
 import org.apache.servicecomb.registry.api.registry.Microservice;
 import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 import org.apache.servicecomb.swagger.SwaggerUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRule.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRule.java
index 4c5283e..b5a3458 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRule.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRule.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.registry.version;
 
+import org.apache.servicecomb.foundation.common.Version;
+
 public abstract class VersionRule {
   private final String versionRule;
 
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleFixedParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleFixedParser.java
index ef4b100..80eecbb 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleFixedParser.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleFixedParser.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.registry.version;
 
+import org.apache.servicecomb.foundation.common.Version;
+
 // fixed, this should be the last parser
 // will not check version format
 public class VersionRuleFixedParser implements VersionRuleParser {
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleLatestParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleLatestParser.java
index 2565a9a..2714611 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleLatestParser.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleLatestParser.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.registry.version;
 
+import org.apache.servicecomb.foundation.common.Version;
 import org.apache.servicecomb.registry.definition.DefinitionConst;
 
 public class VersionRuleLatestParser implements VersionRuleParser {
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleRangeParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleRangeParser.java
index 047cfe8..0fcb889 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleRangeParser.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleRangeParser.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.registry.version;
 
+import org.apache.servicecomb.foundation.common.Version;
+
 // 1.0.0-2.0.0
 public class VersionRuleRangeParser implements VersionRuleParser {
   class RangeVersionRule extends VersionRule {
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleStartFromParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleStartFromParser.java
index 5a6c1d4..6d1bdd6 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleStartFromParser.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleStartFromParser.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.registry.version;
 
+import org.apache.servicecomb.foundation.common.Version;
+
 // 1.0.0+
 public class VersionRuleStartFromParser implements VersionRuleParser {
   class StartFromVersionRule extends VersionRule {
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionUtils.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionUtils.java
index 6ceea9d..8706a3d 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionUtils.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionUtils.java
@@ -20,6 +20,7 @@ package org.apache.servicecomb.registry.version;
 import java.util.Map;
 import java.util.Objects;
 
+import org.apache.servicecomb.foundation.common.Version;
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 
 public final class VersionUtils {
diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersion.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersion.java
index 3611536..1eb629d 100644
--- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersion.java
+++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersion.java
@@ -17,7 +17,7 @@
 
 package org.apache.servicecomb.registry.version;
 
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Rule;
diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRule.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRule.java
index db1c48a..6726de5 100644
--- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRule.java
+++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRule.java
@@ -17,8 +17,7 @@
 
 package org.apache.servicecomb.registry.version;
 
-import org.apache.servicecomb.registry.version.Version;
-import org.apache.servicecomb.registry.version.VersionRule;
+import org.apache.servicecomb.foundation.common.Version;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionUtils.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionUtils.java
index bb543de..1dd8e85 100644
--- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionUtils.java
+++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionUtils.java
@@ -19,8 +19,7 @@ package org.apache.servicecomb.registry.version;
 
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.servicecomb.registry.version.Version;
-import org.apache.servicecomb.registry.version.VersionUtils;
+import org.apache.servicecomb.foundation.common.Version;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/VersionConst.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/VersionConst.java
index 46c4a3b..f8df057 100644
--- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/VersionConst.java
+++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/VersionConst.java
@@ -17,7 +17,7 @@
 
 package org.apache.servicecomb.registry.version;
 
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 
 public interface VersionConst {
   Version v0 = new Version((short) 0, (short) 0, (short) 0, (short) 0);
diff --git a/governance/pom.xml b/governance/pom.xml
index f1038be..c19b036 100644
--- a/governance/pom.xml
+++ b/governance/pom.xml
@@ -77,5 +77,9 @@
       <artifactId>spring-boot-test</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>foundation-common</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/RouterFilter.java b/governance/src/main/java/org/apache/servicecomb/router/RouterFilter.java
similarity index 79%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/RouterFilter.java
rename to governance/src/main/java/org/apache/servicecomb/router/RouterFilter.java
index 56f45de..11eb821 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/RouterFilter.java
+++ b/governance/src/main/java/org/apache/servicecomb/router/RouterFilter.java
@@ -19,30 +19,30 @@ package org.apache.servicecomb.router;
 import java.util.List;
 import java.util.Map;
 
-import javax.validation.constraints.NotNull;
-
 import org.apache.servicecomb.router.cache.RouterRuleCache;
 import org.apache.servicecomb.router.distribute.RouterDistributor;
 import org.apache.servicecomb.router.match.RouterRuleMatcher;
 import org.apache.servicecomb.router.model.PolicyRuleItem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
-import com.netflix.loadbalancer.Server;
-
-
-/**
- * @Author GuoYl123
- * @Date 2019/10/16
- **/
+@Component
 public class RouterFilter {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(RouterFilter.class);
 
-  public static <T extends Server, E> List<T> getFilteredListOfServers(List<T> list,
-      String targetServiceName, @NotNull Map<String, String> headers, RouterDistributor<T, E> distributer) {
+  @Autowired
+  private RouterRuleMatcher routerRuleMatcher;
+
+  @Autowired
+  private RouterRuleCache routerRuleCache;
+
+  public <T, E> List<T> getFilteredListOfServers(List<T> list,
+      String targetServiceName, Map<String, String> headers, RouterDistributor<T, E> distributer) {
     if (CollectionUtils.isEmpty(list)) {
       return list;
     }
@@ -52,14 +52,14 @@ public class RouterFilter {
     /**
      * 1.init and cache
      */
-    if (!RouterRuleCache.doInit(targetServiceName)) {
+    if (!routerRuleCache.doInit(targetServiceName)) {
       LOGGER.debug("route management init failed");
       return list;
     }
     /**
      * 2.match rule
      */
-    PolicyRuleItem invokeRule = RouterRuleMatcher.getInstance().match(targetServiceName, headers);
+    PolicyRuleItem invokeRule = routerRuleMatcher.match(targetServiceName, headers);
 
     if (invokeRule == null) {
       LOGGER.debug("route management match rule failed");
diff --git a/governance/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java b/governance/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java
new file mode 100644
index 0000000..d4a162c
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java
@@ -0,0 +1,135 @@
+/*
+ * 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.router.cache;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent;
+import org.apache.servicecomb.governance.event.GovernanceEventManager;
+import org.apache.servicecomb.router.model.PolicyRuleItem;
+import org.apache.servicecomb.router.model.ServiceInfoCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.yaml.snakeyaml.TypeDescription;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+import org.yaml.snakeyaml.representer.Representer;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.eventbus.Subscribe;
+
+@Component
+public class RouterRuleCache {
+  private static final Logger LOGGER = LoggerFactory.getLogger(RouterRuleCache.class);
+
+  public static final String ROUTE_RULE_PREFIX = "servicecomb.routeRule.";
+
+  private static final String ROUTE_RULE = "servicecomb.routeRule.%s";
+
+  @Autowired
+  private Environment environment;
+
+  private final ConcurrentHashMap<String, ServiceInfoCache> serviceInfoCacheMap = new ConcurrentHashMap<>();
+
+  private final Object lock = new Object();
+
+  private final Representer representer = new Representer();
+
+  public RouterRuleCache() {
+    representer.getPropertyUtils().setSkipMissingProperties(true);
+    GovernanceEventManager.register(this);
+  }
+
+  /**
+   * cache and register callback
+   *
+   * return false when: 1. parsing error 2. rule is null
+   */
+  public boolean doInit(String targetServiceName) {
+    if (!isServerContainRule(targetServiceName)) {
+      return false;
+    }
+    if (!serviceInfoCacheMap.containsKey(targetServiceName)) {
+      synchronized (lock) {
+        if (serviceInfoCacheMap.containsKey(targetServiceName)) {
+          return true;
+        }
+        return addAllRule(targetServiceName, environment.getProperty(String.format(ROUTE_RULE, targetServiceName), ""));
+      }
+    }
+    return true;
+  }
+
+  @Subscribe
+  public void onConfigurationChangedEvent(GovernanceConfigurationChangedEvent event) {
+    for (String key : event.getChangedConfigurations()) {
+      if (key.startsWith(ROUTE_RULE_PREFIX)) {
+        serviceInfoCacheMap.remove(key.substring(ROUTE_RULE_PREFIX.length()));
+      }
+    }
+  }
+
+  private boolean addAllRule(String targetServiceName, String ruleStr) {
+    if (StringUtils.isEmpty(ruleStr)) {
+      return false;
+    }
+    List<PolicyRuleItem> policyRuleItemList;
+    try {
+      Yaml entityParser = new Yaml(
+          new Constructor(new TypeDescription(PolicyRuleItem[].class, PolicyRuleItem[].class)), representer);
+      policyRuleItemList = Arrays
+          .asList(entityParser.loadAs(ruleStr, PolicyRuleItem[].class));
+    } catch (Exception e) {
+      LOGGER.warn("Route management serialization for service {} failed: {}", targetServiceName, e.getMessage());
+      return false;
+    }
+    if (CollectionUtils.isEmpty(policyRuleItemList)) {
+      LOGGER.warn("Route management serialization for service {} is empty", targetServiceName);
+      return false;
+    }
+    ServiceInfoCache serviceInfoCache = new ServiceInfoCache(policyRuleItemList);
+    serviceInfoCacheMap.put(targetServiceName, serviceInfoCache);
+    return true;
+  }
+
+  /**
+   * if a server don't have rule , avoid registered too many callback , it may cause memory leak
+   */
+  private boolean isServerContainRule(String targetServiceName) {
+    return !StringUtils.isEmpty(environment.getProperty(String.format(ROUTE_RULE, targetServiceName), ""));
+  }
+
+  public ConcurrentHashMap<String, ServiceInfoCache> getServiceInfoCacheMap() {
+    return serviceInfoCacheMap;
+  }
+
+  @VisibleForTesting
+  void refresh() {
+    serviceInfoCacheMap.clear();
+  }
+
+  public void refresh(String targetServiceName) {
+    serviceInfoCacheMap.remove(targetServiceName);
+  }
+}
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java b/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
similarity index 88%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
rename to governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
index 9a86013..dd9b072 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
+++ b/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
@@ -24,24 +24,16 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import org.apache.servicecomb.router.cache.RouterRuleCache;
-import org.apache.servicecomb.router.custom.MicroserviceCache;
 import org.apache.servicecomb.router.model.PolicyRuleItem;
 import org.apache.servicecomb.router.model.RouteItem;
 import org.apache.servicecomb.router.model.TagItem;
 import org.apache.servicecomb.router.util.VersionCompareUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 
-import com.netflix.loadbalancer.Server;
-
-import io.vertx.ext.web.Route;
-
-/**
- * @Author GuoYl123
- * @Date 2019/10/17
- **/
-public abstract class AbstractRouterDistributor<T extends Server, E> implements
+public abstract class AbstractRouterDistributor<T, E> implements
     RouterDistributor<T, E> {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRouterDistributor.class);
@@ -54,13 +46,16 @@ public abstract class AbstractRouterDistributor<T extends Server, E> implements
 
   private Function<E, Map<String, String>> getProperties;
 
+  @Autowired
+  private RouterRuleCache routerRuleCache;
+
   @Override
   public List<T> distribute(String targetServiceName, List<T> list, PolicyRuleItem invokeRule) {
     //init LatestVersion
     initLatestVersion(targetServiceName, list);
 
     invokeRule.check(
-        RouterRuleCache.getServiceInfoCacheMap().get(targetServiceName).getLatestVersionTag());
+        routerRuleCache.getServiceInfoCacheMap().get(targetServiceName).getLatestVersionTag());
 
     // get tag list
     Map<TagItem, List<T>> versionServerMap = getDistributList(targetServiceName, list, invokeRule);
@@ -89,7 +84,7 @@ public abstract class AbstractRouterDistributor<T extends Server, E> implements
   }
 
   public TagItem getFiltedServerTagItem(PolicyRuleItem rule, String targetServiceName) {
-    return RouterRuleCache.getServiceInfoCacheMap().get(targetServiceName)
+    return routerRuleCache.getServiceInfoCacheMap().get(targetServiceName)
         .getNextInvokeVersion(rule);
   }
 
@@ -98,15 +93,11 @@ public abstract class AbstractRouterDistributor<T extends Server, E> implements
    * 2.establish map is a more complicate way than direct traversal, because of multiple matches.
    *
    * the method getProperties() contains other field that we don't need.
-   *
-   * @param serviceName
-   * @param list
-   * @return
    */
   private Map<TagItem, List<T>> getDistributList(String serviceName,
       List<T> list,
       PolicyRuleItem invokeRule) {
-    String latestV = RouterRuleCache.getServiceInfoCacheMap().get(serviceName).getLatestVersionTag()
+    String latestV = routerRuleCache.getServiceInfoCacheMap().get(serviceName).getLatestVersionTag()
         .getVersion();
     Map<TagItem, List<T>> versionServerMap = new HashMap<>();
     for (T server : list) {
@@ -156,16 +147,11 @@ public abstract class AbstractRouterDistributor<T extends Server, E> implements
       }
     }
     TagItem tagitem = new TagItem(latestVersion);
-    RouterRuleCache.getServiceInfoCacheMap().get(serviceName).setLatestVersionTag(tagitem);
+    routerRuleCache.getServiceInfoCacheMap().get(serviceName).setLatestVersionTag(tagitem);
   }
 
-  /**
-   * @param list
-   * @param targetServiceName
-   * @return
-   */
   public List<T> getLatestVersionList(List<T> list, String targetServiceName) {
-    String latestV = RouterRuleCache.getServiceInfoCacheMap().get(targetServiceName)
+    String latestV = routerRuleCache.getServiceInfoCacheMap().get(targetServiceName)
         .getLatestVersionTag().getVersion();
     return list.stream().filter(server ->
         getVersion.apply(getIns.apply(server)).equals(latestV)
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java b/governance/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java
rename to governance/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java b/governance/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java
rename to governance/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java b/governance/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java
similarity index 77%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java
rename to governance/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java
index f5b5546..b043bfc 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java
+++ b/governance/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java
@@ -17,28 +17,22 @@
 package org.apache.servicecomb.router.match;
 
 import java.util.Map;
+
 import org.apache.servicecomb.router.cache.RouterRuleCache;
 import org.apache.servicecomb.router.model.PolicyRuleItem;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
-/**
- * @Author GuoYl123
- * @Date 2019/10/17
- **/
+@Component
 public class RouterRuleMatcher {
+  @Autowired
+  private RouterRuleCache routerRuleCache;
 
-  private static RouterRuleMatcher instance = new RouterRuleMatcher();
-
-  private RouterRuleMatcher() {
+  public RouterRuleMatcher() {
   }
 
-  /**
-   * only match header
-   *
-   * @param serviceName
-   * @return
-   */
   public PolicyRuleItem match(String serviceName, Map<String, String> invokeHeader) {
-    for (PolicyRuleItem rule : RouterRuleCache.getServiceInfoCacheMap().get(serviceName)
+    for (PolicyRuleItem rule : routerRuleCache.getServiceInfoCacheMap().get(serviceName)
         .getAllrule()) {
       if (rule.getMatch() == null || rule.getMatch().match(invokeHeader)) {
         return rule;
@@ -46,8 +40,4 @@ public class RouterRuleMatcher {
     }
     return null;
   }
-
-  public static RouterRuleMatcher getInstance() {
-    return instance;
-  }
 }
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java b/governance/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java
rename to governance/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/Matcher.java b/governance/src/main/java/org/apache/servicecomb/router/model/Matcher.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/Matcher.java
rename to governance/src/main/java/org/apache/servicecomb/router/model/Matcher.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java b/governance/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java
rename to governance/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/RouteItem.java b/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/RouteItem.java
rename to governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java b/governance/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java
rename to governance/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/TagItem.java b/governance/src/main/java/org/apache/servicecomb/router/model/TagItem.java
similarity index 100%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/TagItem.java
rename to governance/src/main/java/org/apache/servicecomb/router/model/TagItem.java
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java b/governance/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java
similarity index 94%
rename from handlers/handler-router/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java
rename to governance/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java
index 2f8696b..1af7b52 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java
+++ b/governance/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java
@@ -16,7 +16,7 @@
  */
 package org.apache.servicecomb.router.util;
 
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 
 public class VersionCompareUtil {
   public static int compareVersion(String version1, String version2) {
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java b/governance/src/test/java/org/apache/servicecomb/router/ExampleDistributor.java
similarity index 67%
copy from handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java
copy to governance/src/test/java/org/apache/servicecomb/router/ExampleDistributor.java
index a3bb71c..38f0968 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java
+++ b/governance/src/test/java/org/apache/servicecomb/router/ExampleDistributor.java
@@ -14,23 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.router.custom;
 
-import java.util.Map;
+package org.apache.servicecomb.router;
 
-/**
- * @Author GuoYl123
- * @Date 2019/10/17
- **/
-public interface RouterHeaderFilterExt {
+import org.apache.servicecomb.router.distribute.AbstractRouterDistributor;
+import org.springframework.stereotype.Component;
 
-  default int getOrder() {
-    return 0;
+@Component
+public class ExampleDistributor extends AbstractRouterDistributor<ServiceIns, ServiceIns> {
+  public ExampleDistributor() {
+    init(a -> a, ServiceIns::getVersion, ServiceIns::getServerName, ServiceIns::getTags);
   }
-
-  default boolean enabled() {
-    return true;
-  }
-
-  Map<String, String> doFilter(Map<String, String> invokeHeader);
-}
+}
\ No newline at end of file
diff --git a/handlers/handler-router/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java
similarity index 59%
rename from handlers/handler-router/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java
rename to governance/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java
index e70251c..9d4d448 100644
--- a/handlers/handler-router/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java
+++ b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java
@@ -24,21 +24,23 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.servicecomb.router.cache.RouterRuleCache;
-import org.apache.servicecomb.router.distribute.AbstractRouterDistributor;
 import org.apache.servicecomb.router.distribute.RouterDistributor;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
-
-import com.netflix.config.DynamicPropertyFactory;
-import com.netflix.config.DynamicStringProperty;
-import com.netflix.loadbalancer.Server;
-
-import mockit.Expectations;
-
-/**
- * @author GuoYl123
- **/
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class)
 public class RouterDistributorTest {
+  private static final String TARGET_SERVICE_NAME = "test_server";
 
   private static final String RULE_STRING = ""
       + "      - precedence: 2 #优先级\n"
@@ -69,7 +71,41 @@ public class RouterDistributorTest {
       + "              version: 1\n"
       + "              app: a";
 
-  private static final String TARGET_SERVICE_NAME = "test_server";
+  @Autowired
+  private Environment environment;
+
+  @Autowired
+  private RouterFilter routerFilter;
+
+  @Autowired
+  private RouterDistributor<ServiceIns, ServiceIns> testDistributor;
+
+  private Map<String, Object> dynamicValues = new HashMap<>();
+
+  @Before
+  public void setUp() {
+    ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment;
+
+    if (configurableEnvironment.getPropertySources().contains("testDynamicChange")) {
+      configurableEnvironment.getPropertySources().remove("testDynamicChange");
+    }
+
+    configurableEnvironment.getPropertySources()
+        .addFirst(new EnumerablePropertySource<Map<String, Object>>("testDynamicChange", dynamicValues) {
+          @Override
+          public Object getProperty(String s) {
+            return this.getSource().get(s);
+          }
+
+          @Override
+          public String[] getPropertyNames() {
+            return this.getSource().keySet().toArray(new String[0]);
+          }
+        });
+
+    dynamicValues.put(RouterRuleCache.ROUTE_RULE_PREFIX + TARGET_SERVICE_NAME, RULE_STRING);
+  }
+
 
   @Test
   public void testHeaderIsEmpty() {
@@ -88,84 +124,34 @@ public class RouterDistributorTest {
     list.remove(1);
     List<ServiceIns> serverList = mainFilter(list, headerMap);
     Assert.assertEquals(1, serverList.size());
-    Assert.assertEquals("01", serverList.get(0).getHost());
+    Assert.assertEquals("01", serverList.get(0).getId());
   }
 
   @Test
   public void testVersionMatch() {
-    Map<String, String> headermap = new HashMap<>();
-    headermap.put("userId", "01");
-    headermap.put("appId", "01");
-    headermap.put("format", "json");
-    List<ServiceIns> serverList = mainFilter(getMockList(), headermap);
+    Map<String, String> headers = new HashMap<>();
+    headers.put("userId", "01");
+    headers.put("appId", "01");
+    headers.put("format", "json");
+    List<ServiceIns> serverList = mainFilter(getMockList(), headers);
     Assert.assertEquals(1, serverList.size());
-    Assert.assertEquals("02", serverList.get(0).getHost());
+    Assert.assertEquals("02", serverList.get(0).getId());
   }
 
   private List<ServiceIns> getMockList() {
     List<ServiceIns> serverList = new ArrayList<>();
-    ServiceIns ins1 = new ServiceIns("01");
+    ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME);
     ins1.setVersion("2.0");
-    ServiceIns ins2 = new ServiceIns("02");
+    ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME);
     ins2.addTags("app", "a");
     serverList.add(ins1);
     serverList.add(ins2);
     return serverList;
   }
 
-  private List<ServiceIns> mainFilter(List<ServiceIns> serverlist, Map<String, String> headermap) {
-    RouterDistributor<ServiceIns, ServiceIns> testDistributer = new TestDistributor();
-    DynamicPropertyFactory dpf = DynamicPropertyFactory.getInstance();
-    DynamicStringProperty rule = new DynamicStringProperty("", RULE_STRING);
-    new Expectations(dpf) {
-      {
-        dpf.getStringProperty(anyString, null, (Runnable) any);
-        result = rule;
-      }
-    };
-    RouterRuleCache.refresh();
-    return RouterFilter
-        .getFilteredListOfServers(serverlist, TARGET_SERVICE_NAME, headermap,
-            testDistributer);
-  }
-
-  static class ServiceIns extends Server {
-
-    String version = "1.1";
-
-    String serverName = TARGET_SERVICE_NAME;
-
-    Map<String, String> tags = new HashMap<>();
-
-    public ServiceIns(String id) {
-      super(id);
-    }
-
-    public String getVersion() {
-      return version;
-    }
-
-    public String getServerName() {
-      return serverName;
-    }
-
-    public Map<String, String> getTags() {
-      return tags;
-    }
-
-    public void setVersion(String version) {
-      this.version = version;
-    }
-
-    public void addTags(String key, String v) {
-      tags.put(key, v);
-    }
-  }
-
-  static class TestDistributor extends AbstractRouterDistributor<ServiceIns, ServiceIns> {
-
-    public TestDistributor() {
-      init(a -> a, ServiceIns::getVersion, ServiceIns::getServerName, ServiceIns::getTags);
-    }
+  private List<ServiceIns> mainFilter(List<ServiceIns> serverList, Map<String, String> headers) {
+    return routerFilter
+        .getFilteredListOfServers(serverList, TARGET_SERVICE_NAME, headers,
+            testDistributor);
   }
 }
diff --git a/handlers/handler-router/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java b/governance/src/test/java/org/apache/servicecomb/router/ServiceIns.java
similarity index 55%
copy from handlers/handler-router/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java
copy to governance/src/test/java/org/apache/servicecomb/router/ServiceIns.java
index 46ee61e..7600d09 100644
--- a/handlers/handler-router/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java
+++ b/governance/src/test/java/org/apache/servicecomb/router/ServiceIns.java
@@ -14,21 +14,47 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.servicecomb.router;
 
-import org.apache.servicecomb.router.util.VersionCompareUtil;
-import org.junit.Assert;
-import org.junit.Test;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ServiceIns {
+  String version = "1.1";
+
+  String serverName;
+
+  Map<String, String> tags = new HashMap<>();
+
+  private final String id;
+
+  public ServiceIns(String id, String serverName) {
+    this.id = id;
+    this.serverName = serverName;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public String getServerName() {
+    return serverName;
+  }
+
+  public Map<String, String> getTags() {
+    return tags;
+  }
 
-public class VersionCompareUtilTest {
+  public void setVersion(String version) {
+    this.version = version;
+  }
 
-  @Test
-  public void testVersion() {
-    Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0") > 0);
-    Assert.assertEquals(0, VersionCompareUtil.compareVersion("0.0.0", "0.0.0"));
-    Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.0", "0.0.1") < 0);
-    Assert.assertEquals(0, VersionCompareUtil.compareVersion("0.0.0", "0.0.0.0"));
-    Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0.0") > 0);
-    Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0.0") > 0);
+  public void addTags(String key, String v) {
+    tags.put(key, v);
   }
 }
diff --git a/handlers/handler-router/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java b/governance/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java
similarity index 100%
rename from handlers/handler-router/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java
rename to governance/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java
diff --git a/governance/src/test/resources/META-INF/spring/bean.xml b/governance/src/test/resources/META-INF/spring/bean.xml
index 7d5c1b0..69f5237 100644
--- a/governance/src/test/resources/META-INF/spring/bean.xml
+++ b/governance/src/test/resources/META-INF/spring/bean.xml
@@ -23,5 +23,5 @@
 		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
-  <context:component-scan base-package="com.huaweicloud.governance,org.apache.servicecomb.governance"/>
+  <context:component-scan base-package="org.apache.servicecomb.router,org.apache.servicecomb.governance"/>
 </beans>
diff --git a/handlers/handler-router/pom.xml b/handlers/handler-router/pom.xml
index ba19323..b8f895e 100644
--- a/handlers/handler-router/pom.xml
+++ b/handlers/handler-router/pom.xml
@@ -56,6 +56,10 @@
     </dependency>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
+      <artifactId>servicecomb-governance</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
       <artifactId>handler-loadbalance</artifactId>
     </dependency>
   </dependencies>
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java
deleted file mode 100644
index 941a8ac..0000000
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java
+++ /dev/null
@@ -1,122 +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.router.cache;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.servicecomb.config.YAMLUtil;
-import org.apache.servicecomb.router.model.PolicyRuleItem;
-import org.apache.servicecomb.router.model.ServiceInfoCache;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.util.CollectionUtils;
-
-import com.google.common.collect.Interner;
-import com.google.common.collect.Interners;
-import com.netflix.config.DynamicPropertyFactory;
-import com.netflix.config.DynamicStringProperty;
-
-/**
- * @Author GuoYl123
- * @Date 2019/10/17
- **/
-public class RouterRuleCache {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(RouterRuleCache.class);
-
-  private static ConcurrentHashMap<String, ServiceInfoCache> serviceInfoCacheMap = new ConcurrentHashMap<>();
-
-  private static final String ROUTE_RULE = "servicecomb.routeRule.%s";
-
-  private static Interner<String> servicePool = Interners.newWeakInterner();
-
-  /**
-   * cache and register callback return false when: 1. parsing error 2. rule is null
-   *
-   * @param targetServiceName
-   * @return
-   */
-  public static boolean doInit(String targetServiceName) {
-    if (!isServerContainRule(targetServiceName)) {
-      return false;
-    }
-    if (!serviceInfoCacheMap.containsKey(targetServiceName)) {
-      synchronized (servicePool.intern(targetServiceName)) {
-        if (serviceInfoCacheMap.containsKey(targetServiceName)) {
-          return true;
-        }
-        //Yaml not thread-safe
-        DynamicStringProperty ruleStr = DynamicPropertyFactory.getInstance().getStringProperty(
-            String.format(ROUTE_RULE, targetServiceName), null, () -> {
-              refresh(targetServiceName);
-              DynamicStringProperty tepRuleStr = DynamicPropertyFactory.getInstance()
-                  .getStringProperty(String.format(ROUTE_RULE, targetServiceName), null);
-              addAllRule(targetServiceName, tepRuleStr.get());
-            });
-        return addAllRule(targetServiceName, ruleStr.get());
-      }
-    }
-    return true;
-  }
-
-  private static boolean addAllRule(String targetServiceName, String ruleStr) {
-    if (StringUtils.isEmpty(ruleStr)) {
-      return false;
-    }
-    List<PolicyRuleItem> policyRuleItemList;
-    try {
-      policyRuleItemList = Arrays
-          .asList(YAMLUtil.parserObject(ruleStr, PolicyRuleItem[].class));
-    } catch (Exception e) {
-      LOGGER.error("route management Serialization failed: {}", e.getMessage());
-      return false;
-    }
-    if (CollectionUtils.isEmpty(policyRuleItemList)) {
-      return false;
-    }
-    ServiceInfoCache serviceInfoCache = new ServiceInfoCache(policyRuleItemList);
-    serviceInfoCacheMap.put(targetServiceName, serviceInfoCache);
-    return true;
-  }
-
-  /**
-   * if a server don't have rule , avoid registered too many callback , it may cause memory leak
-   *
-   * @param targetServiceName
-   * @return
-   */
-  public static boolean isServerContainRule(String targetServiceName) {
-    DynamicStringProperty lookFor = DynamicPropertyFactory.getInstance()
-        .getStringProperty(String.format(ROUTE_RULE, targetServiceName), null);
-    return !StringUtils.isEmpty(lookFor.get());
-  }
-
-  public static ConcurrentHashMap<String, ServiceInfoCache> getServiceInfoCacheMap() {
-    return serviceInfoCacheMap;
-  }
-
-  public static void refresh() {
-    serviceInfoCacheMap = new ConcurrentHashMap<>();
-  }
-
-  public static void refresh(String targetServiceName) {
-    serviceInfoCacheMap.remove(targetServiceName);
-  }
-}
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java
index a3bb71c..7951850 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java
+++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java
@@ -19,8 +19,7 @@ package org.apache.servicecomb.router.custom;
 import java.util.Map;
 
 /**
- * @Author GuoYl123
- * @Date 2019/10/17
+ * allow users to filter not necessary headers in request.
  **/
 public interface RouterHeaderFilterExt {
 
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 5d1fb19..b40bf54 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
@@ -27,7 +27,6 @@ import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.foundation.common.utils.JsonUtils;
 import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
-import org.apache.servicecomb.router.cache.RouterRuleCache;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -43,8 +42,6 @@ public class RouterInvokeFilter implements HttpServerFilter {
 
   private static final String SERVICECOMB_ROUTER_HEADER = "servicecomb.router.header";
 
-  private static final String ROUTER_HEADER = "X-RouterContext";
-
   private static List<String> allHeader = new ArrayList<>();
 
 
@@ -58,23 +55,21 @@ public class RouterInvokeFilter implements HttpServerFilter {
     return true;
   }
 
-  /**
-   * pass through headers
-   *
-   * @param invocation
-   * @param httpServletRequestEx
-   * @return
-   */
   @Override
   public Response afterReceiveRequest(Invocation invocation,
       HttpServletRequestEx httpServletRequestEx) {
+    if (!StringUtils.isEmpty(invocation.getContext(RouterServerListFilter.ROUTER_HEADER))) {
+      return null;
+    }
+
     if (!isHaveHeadersRule()) {
       return null;
     }
     if (loadHeaders()) {
       Map<String, String> headerMap = getHeaderMap(httpServletRequestEx);
       try {
-        invocation.addContext(ROUTER_HEADER, JsonUtils.OBJ_MAPPER.writeValueAsString(headerMap));
+        invocation
+            .addContext(RouterServerListFilter.ROUTER_HEADER, JsonUtils.OBJ_MAPPER.writeValueAsString(headerMap));
       } catch (JsonProcessingException e) {
         LOGGER.error("canary context serialization failed");
       }
@@ -124,12 +119,6 @@ public class RouterInvokeFilter implements HttpServerFilter {
     return true;
   }
 
-  /**
-   * get header from request
-   *
-   * @param httpServletRequestEx
-   * @return
-   */
   private Map<String, String> getHeaderMap(HttpServletRequestEx httpServletRequestEx) {
     Map<String, String> headerMap = new HashMap<>();
     allHeader.forEach(headerKey -> {
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java
index 5e1b443..2776c01 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java
+++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java
@@ -21,13 +21,14 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.common.utils.JsonUtils;
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.loadbalance.ServerListFilterExt;
 import org.apache.servicecomb.loadbalance.ServiceCombServer;
+import org.apache.servicecomb.registry.api.registry.Microservice;
 import org.apache.servicecomb.router.RouterFilter;
 import org.apache.servicecomb.router.distribute.RouterDistributor;
-import org.apache.servicecomb.registry.api.registry.Microservice;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,9 +44,13 @@ public class RouterServerListFilter implements ServerListFilterExt {
 
   private static final String TYPE_ROUTER = "router";
 
-  private static final String ROUTER_HEADER = "X-RouterContext";
+  public static final String ROUTER_HEADER = "X-RouterContext";
+
+  @SuppressWarnings("unchecked")
+  private RouterDistributor<ServiceCombServer, Microservice> routerDistributor = BeanUtils
+      .getBean(RouterDistributor.class);
 
-  RouterDistributor<ServiceCombServer, Microservice> distributer = new ServiceCombCanaryDistributer();
+  private RouterFilter routerFilter = BeanUtils.getBean(RouterFilter.class);
 
   @Override
   public boolean enabled() {
@@ -59,9 +64,9 @@ public class RouterServerListFilter implements ServerListFilterExt {
     String targetServiceName = invocation.getMicroserviceName();
     Map<String, String> headers = addHeaders(invocation);
     headers = filterHeaders(headers);
-    return RouterFilter
+    return routerFilter
         .getFilteredListOfServers(list, targetServiceName, headers,
-            distributer);
+            routerDistributor);
   }
 
   private Map<String, String> filterHeaders(Map<String, String> headers) {
diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombCanaryDistributer.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombCanaryDistributer.java
index a49275b..1bde975 100644
--- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombCanaryDistributer.java
+++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombCanaryDistributer.java
@@ -17,18 +17,19 @@
 package org.apache.servicecomb.router.custom;
 
 import org.apache.servicecomb.loadbalance.ServiceCombServer;
-import org.apache.servicecomb.router.distribute.AbstractRouterDistributor;
 import org.apache.servicecomb.registry.api.registry.Microservice;
+import org.apache.servicecomb.router.distribute.AbstractRouterDistributor;
+import org.springframework.stereotype.Component;
 
+@Component
 public class ServiceCombCanaryDistributer extends
     AbstractRouterDistributor<ServiceCombServer, Microservice> {
 
-    public ServiceCombCanaryDistributer() {
-        init(server -> MicroserviceCache.getInstance()
-                        .getService(server.getInstance().getServiceId()),
-                Microservice::getVersion,
-                Microservice::getServiceName,
-                Microservice::getProperties);
-    }
-
+  public ServiceCombCanaryDistributer() {
+    init(server -> MicroserviceCache.getInstance()
+            .getService(server.getInstance().getServiceId()),
+        Microservice::getVersion,
+        Microservice::getServiceName,
+        Microservice::getProperties);
+  }
 }
diff --git a/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/MockMicroserviceVersions.java b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/MockMicroserviceVersions.java
index 42dff91..a56b4f3 100644
--- a/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/MockMicroserviceVersions.java
+++ b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/MockMicroserviceVersions.java
@@ -31,7 +31,7 @@ import org.apache.servicecomb.registry.consumer.AppManager;
 import org.apache.servicecomb.registry.consumer.MicroserviceVersion;
 import org.apache.servicecomb.registry.consumer.MicroserviceVersionRule;
 import org.apache.servicecomb.registry.consumer.MicroserviceVersions;
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 
diff --git a/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
index f2827b1..55e68b7 100644
--- a/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
+++ b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
@@ -39,7 +39,7 @@ import org.apache.servicecomb.registry.api.registry.Microservice;
 import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus;
 import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
-import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.foundation.common.Version;
 import org.apache.servicecomb.registry.version.VersionRule;
 import org.apache.servicecomb.registry.version.VersionRuleUtils;
 import org.apache.servicecomb.registry.version.VersionUtils;