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 2023/02/06 09:06:33 UTC

[servicecomb-java-chassis] 01/02: [SCB-2767]add test case for edge service and solve related problems

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 76f2fd4aa022381b8feb5f60035b94482c636317
Author: liubao <bi...@qq.com>
AuthorDate: Sat Feb 4 17:59:44 2023 +0800

    [SCB-2767]add test case for edge service and solve related problems
---
 demo/demo-filter/filter-client/pom.xml             |  18 +-
 ...TestRetrySchema.java => RetryClientSchema.java} |  38 ++--
 .../src/main/resources/certificates/server.p12     | Bin 4541 -> 0 bytes
 .../src/main/resources/certificates/trust.jks      | Bin 1828 -> 0 bytes
 .../src/main/resources/microservice.yaml           |  23 +--
 .../{filter-client => filter-edge}/pom.xml         |  28 ++-
 .../servicecomb/demo/filter/FilterEdge.java}       |  24 ++-
 .../filter-edge/src/main/resources/log4j2.xml      |  29 +++
 .../src/main/resources/microservice.yaml           |  47 ++---
 .../servicecomb/demo/filter/FilterServer.java      |  22 ++-
 .../src/main/resources/certificates/server.p12     | Bin 4541 -> 0 bytes
 .../src/main/resources/certificates/trust.jks      | Bin 1828 -> 0 bytes
 .../src/main/resources/microservice.yaml           |   4 +-
 demo/demo-filter/filter-tests/pom.xml              | 214 +++++++++++++++++++++
 .../servicecomb/demo/filter/FilterTests.java}      |  24 ++-
 .../filter/retry/TestRetrySchemaFromClient.java}   |  11 +-
 .../filter/retry/TestRetrySchemaFromEdge.java}     |  31 ++-
 .../filter-tests/src/main/resources/log4j2.xml     |  29 +++
 .../src/main/resources/microservice.yaml           |   2 +-
 .../filterEdge/RetryClientSchema.yaml              |  32 +++
 .../filter-tests/src/main/resources/registry.yaml  |   9 +
 .../demo/filter/retry/FilterTestsIT.java}          |   8 +-
 demo/demo-filter/pom.xml                           |   2 +
 .../edge/core/AbstractEdgeDispatcher.java          |   5 +
 .../edge/core/DefaultEdgeDispatcher.java           |   4 -
 .../edge/core/EdgeServerCodecFilter.java           |   4 +-
 .../edge/core/URLMappedEdgeDispatcher.java         |  28 ++-
 27 files changed, 530 insertions(+), 106 deletions(-)

diff --git a/demo/demo-filter/filter-client/pom.xml b/demo/demo-filter/filter-client/pom.xml
index 80005ffaf..908beb3ab 100644
--- a/demo/demo-filter/filter-client/pom.xml
+++ b/demo/demo-filter/filter-client/pom.xml
@@ -47,18 +47,28 @@
     <demo.main>org.apache.servicecomb.demo.filter.FilterClient</demo.main>
   </properties>
 
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
   <profiles>
     <profile>
       <id>docker</id>
-      <properties>
-        <demo.service.name>filter-server</demo.service.name>
-      </properties>
       <build>
         <plugins>
           <plugin>
             <groupId>io.fabric8</groupId>
             <artifactId>docker-maven-plugin</artifactId>
           </plugin>
+          <plugin>
+            <groupId>org.commonjava.maven.plugins</groupId>
+            <artifactId>directory-maven-plugin</artifactId>
+          </plugin>
           <plugin>
             <groupId>com.github.odavid.maven.plugins</groupId>
             <artifactId>mixin-maven-plugin</artifactId>
@@ -66,7 +76,7 @@
               <mixins>
                 <mixin>
                   <groupId>org.apache.servicecomb.demo</groupId>
-                  <artifactId>docker-run-config</artifactId>
+                  <artifactId>docker-build-config</artifactId>
                   <version>${project.version}</version>
                 </mixin>
               </mixins>
diff --git a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/RetryClientSchema.java
similarity index 56%
copy from demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java
copy to demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/RetryClientSchema.java
index 0ee6a7fc3..f8e65e5ff 100644
--- a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java
+++ b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/RetryClientSchema.java
@@ -18,18 +18,18 @@ package org.apache.servicecomb.demo.filter.retry;
 
 import java.util.concurrent.CompletableFuture;
 
-import org.apache.servicecomb.demo.CategorizedTestCase;
-import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
-import org.springframework.stereotype.Component;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.client.RestTemplate;
 
-@Component
-public class TestRetrySchema implements CategorizedTestCase {
+@RestSchema(schemaId = "RetryClientSchema")
+@RequestMapping(path = "/retry", produces = MediaType.APPLICATION_JSON_VALUE)
+public class RetryClientSchema {
   interface RetrySchemaInf {
-    boolean successWhenRetry();
-
     CompletableFuture<Boolean> successWhenRetryAsync();
   }
 
@@ -38,24 +38,14 @@ public class TestRetrySchema implements CategorizedTestCase {
 
   RestTemplate restTemplate = RestTemplateBuilder.create();
 
-  private static final String SERVER = "servicecomb://filterServer";
-
-  @Override
-  public void testAllTransport() throws Exception {
-    testRetryGovernanceRestTemplate();
-    testRetryGovernanceRpc();
-  }
-
-  private void testRetryGovernanceRpc() throws Exception {
-    TestMgr.check(retrySchemaInf.successWhenRetry(), true);
-    TestMgr.check(retrySchemaInf.successWhenRetry(), true);
-
-    TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true);
-    TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true);
+  @GetMapping(path = "/governance/successWhenRetry")
+  public boolean successWhenRetry() {
+    return restTemplate.getForObject("servicecomb://filterServer/retry/governance/successWhenRetry",
+        Boolean.class);
   }
 
-  private void testRetryGovernanceRestTemplate() {
-    TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true);
-    TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true);
+  @GetMapping(path = "/governance/successWhenRetryAsync")
+  public CompletableFuture<Boolean> successWhenRetryAsync() {
+    return retrySchemaInf.successWhenRetryAsync();
   }
 }
diff --git a/demo/demo-filter/filter-client/src/main/resources/certificates/server.p12 b/demo/demo-filter/filter-client/src/main/resources/certificates/server.p12
deleted file mode 100644
index 631313ec6..000000000
Binary files a/demo/demo-filter/filter-client/src/main/resources/certificates/server.p12 and /dev/null differ
diff --git a/demo/demo-filter/filter-client/src/main/resources/certificates/trust.jks b/demo/demo-filter/filter-client/src/main/resources/certificates/trust.jks
deleted file mode 100644
index 57aeff733..000000000
Binary files a/demo/demo-filter/filter-client/src/main/resources/certificates/trust.jks and /dev/null differ
diff --git a/demo/demo-filter/filter-client/src/main/resources/microservice.yaml b/demo/demo-filter/filter-client/src/main/resources/microservice.yaml
index a5b83259d..287adcf67 100644
--- a/demo/demo-filter/filter-client/src/main/resources/microservice.yaml
+++ b/demo/demo-filter/filter-client/src/main/resources/microservice.yaml
@@ -35,6 +35,13 @@ servicecomb:
           interval: 90
         watch: true
 
+  rest:
+    address: 0.0.0.0:8082
+    server:
+      compression: true
+  highway:
+    address: 0.0.0.0:7072
+
   filter-chains:
     enabled: true
   invocation:
@@ -50,19 +57,3 @@ servicecomb:
     retry-governance: |
       maxAttempts: 2
       retryOnResponseStatus: [500]
-
-
-#########SSL options
-ssl.protocols: TLSv1.2
-ssl.authPeer: true
-ssl.checkCN.host: false
-
-#########certificates config
-ssl.trustStore: trust.jks
-ssl.trustStoreType: JKS
-ssl.trustStoreValue: Changeme_123
-ssl.keyStore: server.p12
-ssl.keyStoreType: PKCS12
-ssl.keyStoreValue: Changeme_123
-ssl.crl: revoke.crl
-ssl.sslCustomClass: org.apache.servicecomb.demo.DemoSSLCustom
diff --git a/demo/demo-filter/filter-client/pom.xml b/demo/demo-filter/filter-edge/pom.xml
similarity index 77%
copy from demo/demo-filter/filter-client/pom.xml
copy to demo/demo-filter/filter-edge/pom.xml
index 80005ffaf..3c96c3deb 100644
--- a/demo/demo-filter/filter-client/pom.xml
+++ b/demo/demo-filter/filter-edge/pom.xml
@@ -25,8 +25,8 @@
     <artifactId>demo-filter</artifactId>
     <version>3.0.0-SNAPSHOT</version>
   </parent>
-  <artifactId>filter-client</artifactId>
-  <name>Java Chassis::Demo::Filter::Client</name>
+  <artifactId>filter-edge</artifactId>
+  <name>Java Chassis::Demo::Filter::Edge</name>
 
   <dependencies>
     <dependency>
@@ -37,6 +37,10 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>solution-basic</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>edge-core</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>foundation-test-scaffolding</artifactId>
@@ -44,21 +48,31 @@
   </dependencies>
 
   <properties>
-    <demo.main>org.apache.servicecomb.demo.filter.FilterClient</demo.main>
+    <demo.main>org.apache.servicecomb.demo.filter.FilterEdge</demo.main>
   </properties>
 
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
   <profiles>
     <profile>
       <id>docker</id>
-      <properties>
-        <demo.service.name>filter-server</demo.service.name>
-      </properties>
       <build>
         <plugins>
           <plugin>
             <groupId>io.fabric8</groupId>
             <artifactId>docker-maven-plugin</artifactId>
           </plugin>
+          <plugin>
+            <groupId>org.commonjava.maven.plugins</groupId>
+            <artifactId>directory-maven-plugin</artifactId>
+          </plugin>
           <plugin>
             <groupId>com.github.odavid.maven.plugins</groupId>
             <artifactId>mixin-maven-plugin</artifactId>
@@ -66,7 +80,7 @@
               <mixins>
                 <mixin>
                   <groupId>org.apache.servicecomb.demo</groupId>
-                  <artifactId>docker-run-config</artifactId>
+                  <artifactId>docker-build-config</artifactId>
                   <version>${project.version}</version>
                 </mixin>
               </mixins>
diff --git a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java b/demo/demo-filter/filter-edge/src/main/java/org/apache/servicecomb/demo/filter/FilterEdge.java
similarity index 61%
copy from demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java
copy to demo/demo-filter/filter-edge/src/main/java/org/apache/servicecomb/demo/filter/FilterEdge.java
index 186c289f3..170140c3f 100644
--- a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java
+++ b/demo/demo-filter/filter-edge/src/main/java/org/apache/servicecomb/demo/filter/FilterEdge.java
@@ -17,13 +17,33 @@
 
 package org.apache.servicecomb.demo.filter;
 
+import org.apache.servicecomb.demo.CategorizedTestCaseRunner;
+import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.boot.WebApplicationType;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 
 @EnableServiceComb
-public class FilterServer {
+public class FilterEdge {
+  private static final Logger LOGGER = LoggerFactory.getLogger(FilterEdge.class);
+
   public static void main(String[] args) throws Exception {
-    new SpringApplicationBuilder(FilterServer.class).web(WebApplicationType.NONE).run(args);
+    try {
+      new SpringApplicationBuilder(FilterEdge.class).web(WebApplicationType.NONE).run(args);
+
+      run();
+    } catch (Throwable e) {
+      TestMgr.check("success", "failed");
+      LOGGER.error("-------------- test failed -------------");
+      LOGGER.error("", e);
+      LOGGER.error("-------------- test failed -------------");
+    }
+    TestMgr.summary();
+  }
+
+  public static void run() throws Exception {
+    CategorizedTestCaseRunner.runCategorizedTestCase("filterEdge");
   }
 }
diff --git a/demo/demo-filter/filter-edge/src/main/resources/log4j2.xml b/demo/demo-filter/filter-edge/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..ea906df40
--- /dev/null
+++ b/demo/demo-filter/filter-edge/src/main/resources/log4j2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<Configuration status="INFO">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="[%d][%t][%p]%m [%c:%L]%n" />
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="INFO">
+            <AppenderRef ref="Console" />
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/demo/demo-filter/filter-client/src/main/resources/microservice.yaml b/demo/demo-filter/filter-edge/src/main/resources/microservice.yaml
similarity index 69%
copy from demo/demo-filter/filter-client/src/main/resources/microservice.yaml
copy to demo/demo-filter/filter-edge/src/main/resources/microservice.yaml
index a5b83259d..af5218948 100644
--- a/demo/demo-filter/filter-client/src/main/resources/microservice.yaml
+++ b/demo/demo-filter/filter-edge/src/main/resources/microservice.yaml
@@ -18,7 +18,7 @@
 servicecomb:
   service:
     application: filtertest
-    name: filterClient
+    name: filterEdge
     version: 0.0.1
 
     registry:
@@ -35,34 +35,29 @@ servicecomb:
           interval: 90
         watch: true
 
+  rest:
+    address: 0.0.0.0:9090
+    server:
+      compression: true
+
   filter-chains:
     enabled: true
   invocation:
     exception:
       print-stack-trace: true
-  # test governance retry
-  matchGroup:
-    retry-governance: |
-      matches:
-        - apiPath:
-            prefix: "/retry/governance/"
-  retry:
-    retry-governance: |
-      maxAttempts: 2
-      retryOnResponseStatus: [500]
-
-
-#########SSL options
-ssl.protocols: TLSv1.2
-ssl.authPeer: true
-ssl.checkCN.host: false
 
-#########certificates config
-ssl.trustStore: trust.jks
-ssl.trustStoreType: JKS
-ssl.trustStoreValue: Changeme_123
-ssl.keyStore: server.p12
-ssl.keyStoreType: PKCS12
-ssl.keyStoreValue: Changeme_123
-ssl.crl: revoke.crl
-ssl.sslCustomClass: org.apache.servicecomb.demo.DemoSSLCustom
+  http:
+    dispatcher:
+      edge:
+        default:
+          enabled: true
+          prefix: service
+          withVersion: false
+          prefixSegmentCount: 2
+        url:
+          enabled: true
+          mappings:
+            filterClient:
+              prefixSegmentCount: 0
+              path: "/retry/.*"
+              microserviceName: filterClient
diff --git a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java
index 186c289f3..2f3e0d270 100644
--- a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java
+++ b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java
@@ -17,13 +17,33 @@
 
 package org.apache.servicecomb.demo.filter;
 
+import org.apache.servicecomb.demo.CategorizedTestCaseRunner;
+import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.boot.WebApplicationType;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 
 @EnableServiceComb
 public class FilterServer {
+  private static final Logger LOGGER = LoggerFactory.getLogger(FilterServer.class);
+
   public static void main(String[] args) throws Exception {
-    new SpringApplicationBuilder(FilterServer.class).web(WebApplicationType.NONE).run(args);
+    try {
+      new SpringApplicationBuilder(FilterServer.class).web(WebApplicationType.NONE).run(args);
+
+      run();
+    } catch (Throwable e) {
+      TestMgr.check("success", "failed");
+      LOGGER.error("-------------- test failed -------------");
+      LOGGER.error("", e);
+      LOGGER.error("-------------- test failed -------------");
+    }
+    TestMgr.summary();
+  }
+
+  public static void run() throws Exception {
+    CategorizedTestCaseRunner.runCategorizedTestCase("filterServer");
   }
 }
diff --git a/demo/demo-filter/filter-server/src/main/resources/certificates/server.p12 b/demo/demo-filter/filter-server/src/main/resources/certificates/server.p12
deleted file mode 100644
index 631313ec6..000000000
Binary files a/demo/demo-filter/filter-server/src/main/resources/certificates/server.p12 and /dev/null differ
diff --git a/demo/demo-filter/filter-server/src/main/resources/certificates/trust.jks b/demo/demo-filter/filter-server/src/main/resources/certificates/trust.jks
deleted file mode 100644
index 57aeff733..000000000
Binary files a/demo/demo-filter/filter-server/src/main/resources/certificates/trust.jks and /dev/null differ
diff --git a/demo/demo-filter/filter-server/src/main/resources/microservice.yaml b/demo/demo-filter/filter-server/src/main/resources/microservice.yaml
index b33c96230..d81475cda 100644
--- a/demo/demo-filter/filter-server/src/main/resources/microservice.yaml
+++ b/demo/demo-filter/filter-server/src/main/resources/microservice.yaml
@@ -37,11 +37,11 @@ servicecomb:
       autodiscovery: true
 
   rest:
-    address: 0.0.0.0:8080?sslEnabled=false
+    address: 0.0.0.0:8080
     server:
       compression: true
   highway:
-    address: 0.0.0.0:7070?sslEnabled=true
+    address: 0.0.0.0:7070
 
   filter-chains:
     enabled: true
diff --git a/demo/demo-filter/filter-tests/pom.xml b/demo/demo-filter/filter-tests/pom.xml
new file mode 100644
index 000000000..987c76b71
--- /dev/null
+++ b/demo/demo-filter/filter-tests/pom.xml
@@ -0,0 +1,214 @@
+<?xml version="1.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.
+  -->
+
+<project
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+  xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-filter</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>filter-tests</artifactId>
+  <name>Java Chassis::Demo::Filter::Client</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.demo</groupId>
+      <artifactId>demo-schema</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>registry-local</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>solution-basic</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>foundation-test-scaffolding</artifactId>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <demo.main>org.apache.servicecomb.demo.filter.FilterTests</demo.main>
+  </properties>
+
+  <profiles>
+    <profile>
+      <id>docker</id>
+      <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>io.fabric8</groupId>
+              <artifactId>docker-maven-plugin</artifactId>
+              <configuration>
+                <images>
+                  <image>
+                    <name>servicecomb/service-center</name>
+                    <alias>service30100</alias>
+                    <run>
+                      <namingStrategy>alias</namingStrategy>
+                      <wait>
+                        <log>server is ready</log>
+                        <tcp>
+                          <ports>
+                            <port>30100</port>
+                          </ports>
+                        </tcp>
+                        <time>60000</time>
+                      </wait>
+                      <ports>
+                        <port>30100:30100</port>
+                      </ports>
+                    </run>
+                  </image>
+                  <image>
+                    <name>filter-server:${project.version}</name>
+                    <alias>filter-server</alias>
+                    <run>
+                      <namingStrategy>alias</namingStrategy>
+                      <env>
+                        <JAVA_OPTS>
+                          -Dservicecomb.service.registry.address=http://service30100:30100
+                        </JAVA_OPTS>
+                        <JAR_PATH>/maven/maven/filter-server-${project.version}.jar</JAR_PATH>
+                      </env>
+                      <links>
+                        <link>service30100:service30100</link>
+                      </links>
+                      <wait>
+                        <log>Register microservice instance success</log>
+                        <tcp>
+                          <ports>
+                            <port>8080</port>
+                          </ports>
+                        </tcp>
+                        <time>120000</time>
+                      </wait>
+                      <ports>
+                        <port>8080:8080</port>
+                      </ports>
+                    </run>
+                  </image>
+                  <image>
+                    <name>filter-client:${project.version}</name>
+                    <alias>filter-client</alias>
+                    <run>
+                      <namingStrategy>alias</namingStrategy>
+                      <env>
+                        <JAVA_OPTS>
+                          -Dservicecomb.service.registry.address=http://service30100:30100
+                        </JAVA_OPTS>
+                        <JAR_PATH>/maven/maven/filter-client-${project.version}.jar</JAR_PATH>
+                      </env>
+                      <links>
+                        <link>service30100:service30100</link>
+                      </links>
+                      <wait>
+                        <log>Register microservice instance success</log>
+                        <tcp>
+                          <ports>
+                            <port>8082</port>
+                          </ports>
+                        </tcp>
+                        <time>120000</time>
+                      </wait>
+                      <ports>
+                        <port>8082:8082</port>
+                      </ports>
+                    </run>
+                  </image>
+                  <image>
+                    <name>filter-edge:${project.version}</name>
+                    <alias>filter-edge</alias>
+                    <run>
+                      <namingStrategy>alias</namingStrategy>
+                      <env>
+                        <JAVA_OPTS>
+                          -Dservicecomb.service.registry.address=http://service30100:30100
+                          -Dservicecomb.service.publishAddress=${docker.hostname}
+                        </JAVA_OPTS>
+                        <JAR_PATH>/maven/maven/filter-edge-${project.version}.jar</JAR_PATH>
+                      </env>
+                      <links>
+                        <link>service30100:service30100</link>
+                      </links>
+                      <wait>
+                        <log>Register microservice instance success</log>
+                        <tcp>
+                          <ports>
+                            <port>9090</port>
+                          </ports>
+                        </tcp>
+                        <time>120000</time>
+                      </wait>
+                      <ports>
+                        <port>9090:9090</port>
+                      </ports>
+                    </run>
+                  </image>
+                </images>
+              </configuration>
+              <executions>
+                <execution>
+                  <id>start</id>
+                  <phase>pre-integration-test</phase>
+                  <goals>
+                    <goal>start</goal>
+                  </goals>
+                </execution>
+                <execution>
+                  <id>stop</id>
+                  <phase>post-integration-test</phase>
+                  <goals>
+                    <goal>stop</goal>
+                  </goals>
+                </execution>
+              </executions>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+
+        <plugins>
+          <plugin>
+            <groupId>io.fabric8</groupId>
+            <artifactId>docker-maven-plugin</artifactId>
+          </plugin>
+          <plugin>
+            <groupId>com.github.odavid.maven.plugins</groupId>
+            <artifactId>mixin-maven-plugin</artifactId>
+            <configuration>
+              <mixins>
+                <mixin>
+                  <groupId>org.apache.servicecomb.demo</groupId>
+                  <artifactId>docker-run-config</artifactId>
+                  <version>${project.version}</version>
+                </mixin>
+              </mixins>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/FilterTests.java
similarity index 59%
copy from demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java
copy to demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/FilterTests.java
index 186c289f3..382bedcd2 100644
--- a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java
+++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/FilterTests.java
@@ -17,13 +17,33 @@
 
 package org.apache.servicecomb.demo.filter;
 
+import org.apache.servicecomb.demo.CategorizedTestCaseRunner;
+import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.boot.WebApplicationType;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 
 @EnableServiceComb
-public class FilterServer {
+public class FilterTests {
+  private static final Logger LOGGER = LoggerFactory.getLogger(FilterTests.class);
+
   public static void main(String[] args) throws Exception {
-    new SpringApplicationBuilder(FilterServer.class).web(WebApplicationType.NONE).run(args);
+    try {
+      new SpringApplicationBuilder(FilterTests.class).web(WebApplicationType.NONE).run(args);
+
+      run();
+    } catch (Throwable e) {
+      TestMgr.check("success", "failed");
+      LOGGER.error("-------------- test failed -------------");
+      LOGGER.error("", e);
+      LOGGER.error("-------------- test failed -------------");
+    }
+    TestMgr.summary();
+  }
+
+  public static void run() throws Exception {
+    CategorizedTestCaseRunner.runCategorizedTestCase("filterTests");
   }
 }
diff --git a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchemaFromClient.java
similarity index 87%
copy from demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java
copy to demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchemaFromClient.java
index 0ee6a7fc3..954bf8b8f 100644
--- a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java
+++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchemaFromClient.java
@@ -26,19 +26,24 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
 @Component
-public class TestRetrySchema implements CategorizedTestCase {
+public class TestRetrySchemaFromClient implements CategorizedTestCase {
   interface RetrySchemaInf {
     boolean successWhenRetry();
 
     CompletableFuture<Boolean> successWhenRetryAsync();
   }
 
-  @RpcReference(microserviceName = "filterServer", schemaId = "RetrySchema")
+  @RpcReference(microserviceName = "filterClient", schemaId = "RetryClientSchema")
   private RetrySchemaInf retrySchemaInf;
 
   RestTemplate restTemplate = RestTemplateBuilder.create();
 
-  private static final String SERVER = "servicecomb://filterServer";
+  private static final String SERVER = "servicecomb://filterClient";
+
+  @Override
+  public String getMicroserviceName() {
+    return "filterClient";
+  }
 
   @Override
   public void testAllTransport() throws Exception {
diff --git a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchemaFromEdge.java
similarity index 62%
rename from demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java
rename to demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchemaFromEdge.java
index 0ee6a7fc3..0d7f50700 100644
--- a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchema.java
+++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/retry/TestRetrySchemaFromEdge.java
@@ -26,22 +26,32 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
 @Component
-public class TestRetrySchema implements CategorizedTestCase {
+public class TestRetrySchemaFromEdge implements CategorizedTestCase {
   interface RetrySchemaInf {
     boolean successWhenRetry();
 
     CompletableFuture<Boolean> successWhenRetryAsync();
   }
 
-  @RpcReference(microserviceName = "filterServer", schemaId = "RetrySchema")
+  @RpcReference(microserviceName = "filterEdge", schemaId = "RetryClientSchema")
   private RetrySchemaInf retrySchemaInf;
 
   RestTemplate restTemplate = RestTemplateBuilder.create();
 
-  private static final String SERVER = "servicecomb://filterServer";
+  RestTemplate springRestTemplate = new RestTemplate();
+
+  private static final String SERVER = "servicecomb://filterEdge";
+
+  private static final String EDGE_SERVER = "http://127.0.0.1:9090";
 
   @Override
-  public void testAllTransport() throws Exception {
+  public String getMicroserviceName() {
+    return "filterEdge";
+  }
+
+  @Override
+  public void testRestTransport() throws Exception {
+    testRetryGovernanceFromEdgeDefaultDispatcher();
     testRetryGovernanceRestTemplate();
     testRetryGovernanceRpc();
   }
@@ -55,7 +65,16 @@ public class TestRetrySchema implements CategorizedTestCase {
   }
 
   private void testRetryGovernanceRestTemplate() {
-    TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true);
-    TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true);
+    TestMgr.check(restTemplate.getForObject(
+        SERVER + "/retry/governance/successWhenRetry", boolean.class), true);
+    TestMgr.check(restTemplate.getForObject(
+        SERVER + "/retry/governance/successWhenRetry", boolean.class), true);
+  }
+
+  private void testRetryGovernanceFromEdgeDefaultDispatcher() {
+    TestMgr.check(springRestTemplate.getForObject(
+        EDGE_SERVER + "/service/filterClient/retry/governance/successWhenRetry", boolean.class), true);
+    TestMgr.check(springRestTemplate.getForObject(
+        EDGE_SERVER + "/service/filterClient/retry/governance/successWhenRetry", boolean.class), true);
   }
 }
diff --git a/demo/demo-filter/filter-tests/src/main/resources/log4j2.xml b/demo/demo-filter/filter-tests/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..ea906df40
--- /dev/null
+++ b/demo/demo-filter/filter-tests/src/main/resources/log4j2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<Configuration status="INFO">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="[%d][%t][%p]%m [%c:%L]%n" />
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="INFO">
+            <AppenderRef ref="Console" />
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/demo/demo-filter/filter-client/src/main/resources/microservice.yaml b/demo/demo-filter/filter-tests/src/main/resources/microservice.yaml
similarity index 98%
copy from demo/demo-filter/filter-client/src/main/resources/microservice.yaml
copy to demo/demo-filter/filter-tests/src/main/resources/microservice.yaml
index a5b83259d..9f7a7c176 100644
--- a/demo/demo-filter/filter-client/src/main/resources/microservice.yaml
+++ b/demo/demo-filter/filter-tests/src/main/resources/microservice.yaml
@@ -18,7 +18,7 @@
 servicecomb:
   service:
     application: filtertest
-    name: filterClient
+    name: filterTests
     version: 0.0.1
 
     registry:
diff --git a/demo/demo-filter/filter-tests/src/main/resources/microservices/filterEdge/RetryClientSchema.yaml b/demo/demo-filter/filter-tests/src/main/resources/microservices/filterEdge/RetryClientSchema.yaml
new file mode 100644
index 000000000..0c59267ce
--- /dev/null
+++ b/demo/demo-filter/filter-tests/src/main/resources/microservices/filterEdge/RetryClientSchema.yaml
@@ -0,0 +1,32 @@
+---
+swagger: "2.0"
+info:
+  version: "1.0.0"
+  title: "swagger definition for org.apache.servicecomb.demo.filter.retry.RetryClientSchema"
+  x-java-interface: "gen.swagger.RetryClientSchemaIntf"
+basePath: "/retry"
+schemes:
+- "http"
+consumes:
+- "application/json"
+produces:
+- "application/json"
+paths:
+  /governance/successWhenRetry:
+    get:
+      operationId: "successWhenRetry"
+      parameters: []
+      responses:
+        "200":
+          description: "response of 200"
+          schema:
+            type: "boolean"
+  /governance/successWhenRetryAsync:
+    get:
+      operationId: "successWhenRetryAsync"
+      parameters: []
+      responses:
+        "200":
+          description: "response of 200"
+          schema:
+            type: "boolean"
diff --git a/demo/demo-filter/filter-tests/src/main/resources/registry.yaml b/demo/demo-filter/filter-tests/src/main/resources/registry.yaml
new file mode 100644
index 000000000..122fbd346
--- /dev/null
+++ b/demo/demo-filter/filter-tests/src/main/resources/registry.yaml
@@ -0,0 +1,9 @@
+filterEdge:
+  - id: "001"
+    version: "1.0"
+    appid: filtertest
+    schemaIds:
+      - RetryClientSchema
+    instances:
+      - endpoints:
+          - rest://127.0.0.1:9090
diff --git a/demo/demo-filter/filter-client/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterClientIT.java b/demo/demo-filter/filter-tests/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterTestsIT.java
similarity index 90%
rename from demo/demo-filter/filter-client/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterClientIT.java
rename to demo/demo-filter/filter-tests/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterTestsIT.java
index ccb369ae1..d09de401c 100644
--- a/demo/demo-filter/filter-client/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterClientIT.java
+++ b/demo/demo-filter/filter-tests/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterTestsIT.java
@@ -18,7 +18,7 @@
 package org.apache.servicecomb.demo.filter.retry;
 
 import org.apache.servicecomb.demo.TestMgr;
-import org.apache.servicecomb.demo.filter.FilterClient;
+import org.apache.servicecomb.demo.filter.FilterTests;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -27,8 +27,8 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 @ExtendWith(SpringExtension.class)
-@SpringBootTest(classes = FilterClient.class)
-public class FilterClientIT {
+@SpringBootTest(classes = FilterTests.class)
+public class FilterTestsIT {
 
   @BeforeEach
   public void setUp() {
@@ -37,7 +37,7 @@ public class FilterClientIT {
 
   @Test
   public void clientGetsNoError() throws Exception {
-    FilterClient.run();
+    FilterTests.run();
 
     Assertions.assertTrue(TestMgr.errors().isEmpty());
   }
diff --git a/demo/demo-filter/pom.xml b/demo/demo-filter/pom.xml
index cf07bf6a5..ba46509fe 100644
--- a/demo/demo-filter/pom.xml
+++ b/demo/demo-filter/pom.xml
@@ -30,6 +30,8 @@
   <modules>
     <module>filter-server</module>
     <module>filter-client</module>
+    <module>filter-edge</module>
+    <module>filter-tests</module>
   </modules>
   <dependencies>
     <dependency>
diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java
index 7cdc43ea0..fbbbea7d4 100644
--- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java
+++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java
@@ -21,6 +21,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
+import org.apache.servicecomb.core.SCBEngine;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.apache.servicecomb.transport.rest.vertx.AbstractVertxHttpDispatcher;
 import org.slf4j.Logger;
@@ -38,6 +39,10 @@ public abstract class AbstractEdgeDispatcher extends AbstractVertxHttpDispatcher
     return new EdgeInvocation();
   }
 
+  protected boolean isFilterChainEnabled() {
+    return SCBEngine.getInstance().isFilterChainEnabled();
+  }
+
   protected void onFailure(RoutingContext context) {
     LOGGER.error("edge server failed.", context.failure());
     HttpServerResponse response = context.response();
diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java
index 07b87e9b6..dde4dc8a6 100644
--- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java
+++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java
@@ -101,10 +101,6 @@ public class DefaultEdgeDispatcher extends AbstractEdgeDispatcher {
     requestByHandler(context, microserviceName, versionRule, path);
   }
 
-  protected boolean isFilterChainEnabled() {
-    return SCBEngine.getInstance().isFilterChainEnabled();
-  }
-
   @Nullable
   private String extractMicroserviceName(RoutingContext context) {
     return context.pathParam(MICROSERVICE_NAME);
diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
index ee6a1753b..a41a3e361 100644
--- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
+++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
@@ -21,7 +21,6 @@ import java.util.concurrent.CompletableFuture;
 import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter;
-import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
@@ -48,7 +47,8 @@ public class EdgeServerCodecFilter extends RestServerCodecFilter {
 
   @Override
   public boolean isEnabledForTransport(String transport) {
-    return Const.RESTFUL.equals(transport);
+    // For edge service, this filter executed before load balancer and transport is always null.
+    return true;
   }
 
   @Override
diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java
index baac1b221..d192d0cec 100644
--- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java
+++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java
@@ -20,17 +20,23 @@ package org.apache.servicecomb.edge.core;
 import java.util.HashMap;
 import java.util.Map;
 
-import com.google.common.annotations.VisibleForTesting;
-import io.vertx.ext.web.handler.PlatformHandler;
+import org.apache.servicecomb.common.rest.RestProducerInvocationFlow;
+import org.apache.servicecomb.core.invocation.InvocationCreator;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
+import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest;
+import org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse;
 import org.apache.servicecomb.transport.rest.vertx.RestBodyHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.netflix.config.ConcurrentCompositeConfiguration;
 import com.netflix.config.DynamicPropertyFactory;
 
 import io.vertx.ext.web.Router;
 import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.PlatformHandler;
 
 /**
  * Provide a URL mapping based dispatcher. Users configure witch URL patterns dispatch to a target service.
@@ -120,6 +126,24 @@ public class URLMappedEdgeDispatcher extends AbstractEdgeDispatcher {
 
     String path = Utils.findActualPath(context.request().path(), configurationItem.getPrefixSegmentCount());
 
+    if (isFilterChainEnabled()) {
+      requestByFilter(context, configurationItem, path);
+      return;
+    }
+
+    requestByHandler(context, configurationItem, path);
+  }
+
+  protected void requestByFilter(RoutingContext context, URLMappedConfigurationItem configurationItem, String path) {
+    HttpServletRequestEx requestEx = new VertxServerRequestToHttpServletRequest(context);
+    HttpServletResponseEx responseEx = new VertxServerResponseToHttpServletResponse(context.response());
+    InvocationCreator creator = new EdgeInvocationCreator(context, requestEx, responseEx,
+        configurationItem.getMicroserviceName(), configurationItem.getVersionRule(), path);
+    new RestProducerInvocationFlow(creator, requestEx, responseEx)
+        .run();
+  }
+
+  private void requestByHandler(RoutingContext context, URLMappedConfigurationItem configurationItem, String path) {
     EdgeInvocation edgeInvocation = createEdgeInvocation();
     if (configurationItem.getVersionRule() != null) {
       edgeInvocation.setVersionRule(configurationItem.getVersionRule());