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 2018/08/01 10:10:19 UTC

[incubator-servicecomb-java-chassis] 05/06: [SCB-790] create base integration test mechanism, and base test case: 1.deploy edge 2.deploy standalone producer 3.run test case with different consumer/transport/producer combination 4.stop producer 5.stop edge

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/incubator-servicecomb-java-chassis.git

commit 5cfc19af59eaefa8767ba3413d021ee42f763bdb
Author: wujimin <wu...@huawei.com>
AuthorDate: Tue Jul 31 11:36:27 2018 +0800

    [SCB-790] create base integration test mechanism, and base test case:
    1.deploy edge
    2.deploy standalone producer
    3.run test case with different consumer/transport/producer combination
    4.stop producer
    5.stop edge
---
 integration-tests/it-common-service/enable-it-jar  |   0
 integration-tests/it-common-service/pom.xml        |  41 +++++
 .../apache/servicecomb/it/CommonServiceMain.java   |  23 +++
 integration-tests/it-common/enable-it-jar          |   0
 integration-tests/it-common/pom.xml                |  37 ++++
 .../org/apache/servicecomb/it/CommandReceiver.java |  97 ++++++++++
 .../org/apache/servicecomb/it/ITBootListener.java  |  82 +++++++++
 .../java/org/apache/servicecomb/it/ITMain.java     |  27 +++
 .../java/org/apache/servicecomb/it/ITUtils.java    | 123 +++++++++++++
 .../it-common/src/main/resources/logback.xml       |  29 +++
 .../it-common/src/main/resources/microservice.yaml |  46 +++++
 integration-tests/it-consumer/pom.xml              |  46 +++++
 .../org/apache/servicecomb/it/ConsumerMain.java    | 135 ++++++++++++++
 .../org/apache/servicecomb/it/ResultPrinter.java   |  65 +++++++
 .../servicecomb/it/deploy/DeployDefinition.java    |  86 +++++++++
 .../org/apache/servicecomb/it/deploy/Deploys.java  | 192 ++++++++++++++++++++
 .../servicecomb/it/deploy/MicroserviceDeploy.java  |  71 ++++++++
 .../it/deploy/MicroserviceDeployDefinition.java    |  56 ++++++
 .../apache/servicecomb/it/deploy/NormalDeploy.java | 114 ++++++++++++
 .../servicecomb/it/deploy/SubProcessLogger.java    |  68 +++++++
 .../it/extend/engine/ITClientHttpRequest.java      |  43 +++++
 .../extend/engine/ITClientHttpRequestFactory.java  |  36 ++++
 .../servicecomb/it/extend/engine/ITInvoker.java    |  69 ++++++++
 .../apache/servicecomb/it/junit/ITJUnitUtils.java  | 102 +++++++++++
 .../apache/servicecomb/it/junit/SCBFailure.java    |  37 ++++
 .../it/testcase/base/TestDataTypePojo.java         |  66 +++++++
 .../it/testcase/base/TestDataTypeRest.java         |  94 ++++++++++
 .../servicecomb/it/testcase/base/TestDownload.java | 142 +++++++++++++++
 .../servicecomb/it/testcase/base/TestGeneric.java  |  26 +++
 .../it/testcase/support/DataTypePojoIntf.java      |  22 +++
 .../it/testcase/support/DataTypeRestIntf.java      |  30 ++++
 .../it/testcase/support/DownloadSchemaIntf.java    |  39 +++++
 .../it/testcase/support/ProducerDevMode.java       |  22 +++
 .../src/main/resources/microservice.yaml           |  19 ++
 .../java/org/apache/servicecomb/it/TestMain.java   |  30 ++++
 integration-tests/it-edge/enable-it-jar            |   0
 integration-tests/it-edge/pom.xml                  |  53 ++++++
 .../apache/servicecomb/it/authentication/Auth.java |  24 +++
 .../servicecomb/it/authentication/encrypt/Hcr.java |  39 +++++
 .../org/apache/servicecomb/it/edge/EdgeConst.java  |  20 +++
 .../apache/servicecomb/it/edge/EdgeDispatcher.java |  58 ++++++
 .../org/apache/servicecomb/it/edge/EdgeMain.java   |  26 +++
 .../servicecomb/it/edge/encrypt/Encrypt.java       |  28 +++
 .../it/edge/encrypt/EncryptContext.java            |  46 +++++
 .../it/edge/encrypt/EncryptEdgeDispatcher.java     | 114 ++++++++++++
 .../it/edge/encrypt/EncryptEdgeInvocation.java     |  34 ++++
 .../it/edge/encrypt/filter/DecodeBodyFilter.java   |  66 +++++++
 .../encrypt/filter/EdgeSignatureRequestFilter.java |  67 +++++++
 .../filter/EdgeSignatureResponseFilter.java        |  76 ++++++++
 .../it/edge/encrypt/filter/UserIdFilter.java       |  46 +++++
 .../servicecomb/it/edge/handler/AuthHandler.java   |  74 ++++++++
 ...servicecomb.common.rest.filter.HttpServerFilter |  21 +++
 ...cecomb.transport.rest.vertx.VertxHttpDispatcher |  19 ++
 .../src/main/resources/config/cse.handler.xml      |  20 +++
 .../it-edge/src/main/resources/microservice.yaml   |  48 +++++
 integration-tests/it-producer/enable-it-jar        |   0
 integration-tests/it-producer/pom.xml              |  41 +++++
 .../apache/servicecomb/it/BaseProducerMain.java    |  23 +++
 .../servicecomb/it/schema/DataTypeJaxrs.java       |  74 ++++++++
 .../apache/servicecomb/it/schema/DataTypePojo.java |  42 +++++
 .../servicecomb/it/schema/DataTypeSpringmvc.java   |  64 +++++++
 .../servicecomb/it/schema/DownloadSchema.java      | 195 +++++++++++++++++++++
 .../src/main/resources/microservice.yaml           |  20 +++
 integration-tests/pom.xml                          |  35 ++++
 64 files changed, 3488 insertions(+)

diff --git a/integration-tests/it-common-service/enable-it-jar b/integration-tests/it-common-service/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-common-service/pom.xml b/integration-tests/it-common-service/pom.xml
new file mode 100644
index 0000000..48ac9f0
--- /dev/null
+++ b/integration-tests/it-common-service/pom.xml
@@ -0,0 +1,41 @@
+<?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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>integration-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>it-common-service</artifactId>
+  <name>Java Chassis::IT::CommonService</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>it-common</artifactId>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <it.main>org.apache.servicecomb.it.CommonServiceMain</it.main>
+  </properties>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-common-service/src/main/java/org/apache/servicecomb/it/CommonServiceMain.java b/integration-tests/it-common-service/src/main/java/org/apache/servicecomb/it/CommonServiceMain.java
new file mode 100644
index 0000000..7dfb147
--- /dev/null
+++ b/integration-tests/it-common-service/src/main/java/org/apache/servicecomb/it/CommonServiceMain.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it;
+
+public class CommonServiceMain {
+  public static void main(String[] args) {
+    ITMain.main(args);
+  }
+}
diff --git a/integration-tests/it-common/enable-it-jar b/integration-tests/it-common/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-common/pom.xml b/integration-tests/it-common/pom.xml
new file mode 100644
index 0000000..653b800
--- /dev/null
+++ b/integration-tests/it-common/pom.xml
@@ -0,0 +1,37 @@
+<?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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>integration-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>it-common</artifactId>
+  <name>Java Chassis::IT::Common</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/CommandReceiver.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/CommandReceiver.java
new file mode 100644
index 0000000..08c6bbb
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/CommandReceiver.java
@@ -0,0 +1,97 @@
+/*
+ * 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.it;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+
+public class CommandReceiver {
+  private static final Logger LOGGER = LoggerFactory.getLogger(CommandReceiver.class);
+
+  public CommandReceiver() {
+    Thread thread = new Thread(this::run, "it-command-receiver");
+    thread.setDaemon(true);
+    thread.start();
+  }
+
+  public void run() {
+    try {
+      doRun();
+    } catch (Throwable e) {
+      e.printStackTrace();
+    }
+  }
+
+  private void doRun() throws IOException {
+    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+    String line;
+    while ((line = reader.readLine()) != null) {
+      try {
+        JsonNode cmd = JsonUtils.OBJ_MAPPER.readTree(line);
+        dispatchCommand(cmd);
+      } catch (Throwable e) {
+        LOGGER.error("Failed to execute command: {}", line, e);
+      }
+    }
+    reader.close();
+  }
+
+  private void dispatchCommand(JsonNode cmd) {
+    LOGGER.info("dispatch command: {}", cmd);
+    if (TextNode.class.isInstance(cmd)) {
+      onStringCommand(cmd.asText());
+      return;
+    }
+
+    throw new UnsupportedOperationException(cmd.toString());
+  }
+
+  protected void onStringCommand(String command) {
+    switch (command) {
+      case "ms-stop":
+        stop();
+        break;
+      default:
+        throw new UnsupportedOperationException(command);
+    }
+  }
+
+  protected void stop() {
+    new Thread(() -> {
+      for (; ; ) {
+        SCBEngine.getInstance().destroy();
+        if (ITBootListener.isDone() && SCBStatus.DOWN.equals(SCBEngine.getInstance().getStatus())) {
+          LOGGER.info("succeed to close " + RegistryUtils.getMicroservice().getServiceName());
+          break;
+        }
+        ITUtils.forceWait(TimeUnit.SECONDS, 1);
+      }
+    }, "it-stop").start();
+  }
+}
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITBootListener.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITBootListener.java
new file mode 100644
index 0000000..185fb80
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITBootListener.java
@@ -0,0 +1,82 @@
+/*
+ * 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.it;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.servicecomb.core.BootListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.DynamicPropertyFactory;
+
+@Component
+public class ITBootListener implements BootListener {
+  private static final Logger LOGGER = LoggerFactory.getLogger(ITBootListener.class);
+
+  private static boolean done;
+
+  public static boolean isDone() {
+    return done;
+  }
+
+  @Override
+  public void onBootEvent(BootEvent event) {
+    if (!EventType.BEFORE_HANDLER.equals(event.getEventType())) {
+      return;
+    }
+
+    selectPort("servicecomb.rest.address");
+    selectPort("servicecomb.highway.address");
+    done = true;
+  }
+
+  protected void selectPort(String cfgKey) {
+    String endpoint = DynamicPropertyFactory.getInstance().getStringProperty(cfgKey, null).get();
+    if (endpoint == null) {
+      return;
+    }
+
+    URI uri = URI.create("http://" + endpoint);
+    if (uri.getPort() == 0) {
+      int port = getRandomPort();
+      try {
+        ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory
+            .getBackingConfigurationSource();
+        endpoint = new URIBuilder("http://" + endpoint).setPort(port).build().toString().substring(7);
+        config.getConfiguration(0).setProperty(cfgKey, endpoint);
+        LOGGER.info("change {} to {}.", cfgKey, endpoint);
+      } catch (URISyntaxException e) {
+        throw new IllegalStateException("Failed to build endpoint.", e);
+      }
+    }
+  }
+
+  protected int getRandomPort() {
+    try (ServerSocket serverSocket = new ServerSocket(0)) {
+      return serverSocket.getLocalPort();
+    } catch (IOException e) {
+      throw new IllegalStateException("Failed to get random port.", e);
+    }
+  }
+}
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITMain.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITMain.java
new file mode 100644
index 0000000..7be9a46
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITMain.java
@@ -0,0 +1,27 @@
+/*
+ * 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.it;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+
+public class ITMain {
+  public static void main(String[] args) {
+    new CommandReceiver();
+
+    BeanUtils.init();
+  }
+}
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITUtils.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITUtils.java
new file mode 100644
index 0000000..ada728b
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITUtils.java
@@ -0,0 +1,123 @@
+/*
+ * 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.it;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.reflect.MethodUtils;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersionRule;
+import org.apache.servicecomb.serviceregistry.task.event.PeriodicPullEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ITUtils {
+  private static final Logger LOGGER = LoggerFactory.getLogger(ITUtils.class);
+
+  private ITUtils() {
+  }
+
+  public static void forceWait(TimeUnit timeUnit, long timeout) {
+    try {
+      timeUnit.sleep(timeout);
+    } catch (InterruptedException e) {
+      // eat the exception
+    }
+  }
+
+  public static void waitBootFinished() {
+    for (; ; ) {
+      if (SCBEngine.getInstance().getStatus().equals(SCBStatus.UP)) {
+        return;
+      }
+
+      forceWait(TimeUnit.MILLISECONDS, 100);
+    }
+  }
+
+  public static Map<String, MicroserviceInstance> waitMicroserviceReadyAndLimit(String appId, String microserviceName,
+      String strVersionRule, int minInstanceCount) {
+    Map<String, MicroserviceInstance> instances = waitMicroserviceReady(appId,
+        microserviceName,
+        strVersionRule,
+        minInstanceCount);
+    return instances.values()
+        .stream()
+        .sorted(Comparator.comparing(MicroserviceInstance::getInstanceId))
+        .limit(minInstanceCount)
+        .collect(Collectors.toMap(MicroserviceInstance::getInstanceId, Function.identity()));
+  }
+
+  public static Map<String, MicroserviceInstance> waitMicroserviceReady(String appId, String microserviceName,
+      String strVersionRule, int minInstanceCount) {
+    LOGGER.info("waiting for microservice online. appId={}, name={}, minInstanceCount={}",
+        appId,
+        microserviceName,
+        minInstanceCount);
+
+    Map<String, MicroserviceInstance> instances;
+    for (;;) {
+      MicroserviceVersionRule microserviceVersionRule = RegistryUtils.getServiceRegistry()
+          .getAppManager()
+          .getOrCreateMicroserviceVersionRule(appId, microserviceName, strVersionRule);
+      instances = microserviceVersionRule.getInstances();
+      if (instances.size() >= minInstanceCount) {
+        break;
+      }
+
+      LOGGER.info(
+          "waiting for microservice online. appId={}, name={}, expect minInstanceCount={}, real instanceCount={}.",
+          appId,
+          microserviceName,
+          minInstanceCount,
+          instances.size());
+      // pull at once
+      EventManager.getEventBus().post(new PeriodicPullEvent());
+      forceWait(TimeUnit.SECONDS, 1);
+    }
+
+    LOGGER.info("microservice already online. appId={}, name={}, instanceCount={}",
+        appId,
+        microserviceName,
+        minInstanceCount);
+    return instances;
+  }
+
+  public static void invokeExactStaticMethod(final Class<?>[] classes, final String methodName, Object... args) {
+    for (Class<?> cls : classes) {
+      invokeExactStaticMethod(cls, methodName, args);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> T invokeExactStaticMethod(final Class<?> cls, final String methodName, Object... args) {
+    try {
+      return (T) MethodUtils.invokeExactStaticMethod(cls, methodName, args);
+    } catch (Throwable e) {
+      throw new IllegalStateException(String.format("Failed to invoke, class=%s, method=%s", cls.getName(), methodName),
+          e);
+    }
+  }
+}
diff --git a/integration-tests/it-common/src/main/resources/logback.xml b/integration-tests/it-common/src/main/resources/logback.xml
new file mode 100644
index 0000000..dfdfa92
--- /dev/null
+++ b/integration-tests/it-common/src/main/resources/logback.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 scan="true">
+  <jmxConfigurator/>
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d [%level] [%thread] - %msg (%F:%L\)%n</pattern>
+    </encoder>
+  </appender>
+  <root level="WARN">
+    <appender-ref ref="STDOUT"/>
+  </root>
+</configuration>
\ No newline at end of file
diff --git a/integration-tests/it-common/src/main/resources/microservice.yaml b/integration-tests/it-common/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..d4a11c7
--- /dev/null
+++ b/integration-tests/it-common/src/main/resources/microservice.yaml
@@ -0,0 +1,46 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+servicecomb-config-order: -10000
+
+APPLICATION_ID: integration-test
+service_description:
+  name: $invalid-name-must-be-overridden
+  version: 1.0.0
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  request:
+    # 10 minute
+    timeout: 600000
+  rest:
+    address: 0.0.0.0:0
+    server:
+      thread-count: 8
+    client:
+      thread-count: 8
+      connection:
+        maxPoolSize: 30
+  highway:
+    address: 0.0.0.0:0
+    server:
+      thread-count: 8
+    client:
+      thread-count: 8
+  uploads:
+    directory: target
\ No newline at end of file
diff --git a/integration-tests/it-consumer/pom.xml b/integration-tests/it-consumer/pom.xml
new file mode 100644
index 0000000..9821cab
--- /dev/null
+++ b/integration-tests/it-consumer/pom.xml
@@ -0,0 +1,46 @@
+<?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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>integration-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>it-consumer</artifactId>
+  <name>Java Chassis::IT::Consumer</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>it-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+      <version>3.3.9</version>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <it.main>org.apache.servicecomb.it.ConsumerMain</it.main>
+  </properties>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
new file mode 100644
index 0000000..ded64d1
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.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.it;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.servicecomb.core.Const;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.it.deploy.Deploys;
+import org.apache.servicecomb.it.junit.ITJUnitUtils;
+import org.apache.servicecomb.it.testcase.base.TestDataTypePojo;
+import org.apache.servicecomb.it.testcase.base.TestDataTypeRest;
+import org.apache.servicecomb.it.testcase.support.ProducerDevMode;
+import org.apache.servicecomb.transport.highway.HighwayTransport;
+
+
+public class ConsumerMain {
+  private static ResultPrinter resultPrinter = new ResultPrinter();
+
+  private static Deploys deploys = new Deploys();
+
+  private static List<String> transports;
+
+  public static boolean autoExit = true;
+
+  public static void main(String[] args) throws Throwable {
+    BeanUtils.init();
+    ITUtils.waitBootFinished();
+
+    deploys.init();
+    run();
+
+    SCBEngine.getInstance().destroy();
+    resultPrinter.print();
+
+    if (autoExit) {
+      System.exit(0);
+    }
+  }
+
+  protected static void run() throws Throwable {
+    // deploy edge/zuul
+    // if not ready, will start a new instance and wait for ready
+    deploys.getEdge().ensureReady();
+    // deploys.getZuul().ensureReady(zuul);
+
+    // 1.base test case
+    //   include all extension point abnormal scenes test case
+
+    // deploy standalone base-producer
+    //   only run one case for "any" transport
+    //   run highway
+    //   run rest
+    //   run native restTemplate to edge/zuul
+    // stop standalone base-producer
+    transports = Arrays.asList(HighwayTransport.NAME, Const.RESTFUL);
+    testStandalone();
+
+    transports = Arrays.asList(Const.RESTFUL);
+    // deploy tomcat base-producer
+    //   run vertx-servlet
+    //   run native restTemplate to edge/zuul
+    // stop tomcat base-producer
+
+    // deploy spring boot base-producer
+    //   run vertx-servlet
+    //   run native restTemplate to edge/zuul
+    // stop spring boot base-producer
+
+    // 2.complex test case
+    //   1)start new producer version
+    //     consumer/edge/zuul should ......
+    //   2)delete new producer version
+    //     consumer/edge/zuul should ......
+    //   ......
+
+    // 3.deploy development mode producer
+    // ......
+
+    deploys.getEdge().stop();
+  }
+
+  private static void testStandalone() throws Throwable {
+    deploys.getBaseProducer().ensureReady();
+    ITJUnitUtils.addParent("standalone");
+
+    testDataType();
+
+    ITJUnitUtils.getParents().pop();
+    deploys.getBaseProducer().stop();
+  }
+
+  private static void testDataType() {
+    testDataType(ProducerDevMode.Pojo, TestDataTypePojo.class);
+    testDataType(ProducerDevMode.Jaxrs, TestDataTypeRest.class);
+    testDataType(ProducerDevMode.Springmvc, TestDataTypeRest.class);
+
+    ITJUnitUtils.getParents().push("edge");
+//    runEdge();
+    ITJUnitUtils.getParents().pop();
+
+    ITJUnitUtils.getParents().push("zuul");
+//    runEdge();
+    ITJUnitUtils.getParents().pop();
+  }
+
+  private static void testDataType(ProducerDevMode producerDevMode, Class<?>... classes) {
+    ITJUnitUtils.addParent(producerDevMode.name());
+    for (String transport : transports) {
+      ITJUnitUtils.addParent(transport);
+
+      ITUtils.invokeExactStaticMethod(classes, "init", transport, producerDevMode);
+      ITJUnitUtils.run(classes);
+
+      ITJUnitUtils.getParents().pop();
+    }
+    ITJUnitUtils.getParents().pop();
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ResultPrinter.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ResultPrinter.java
new file mode 100644
index 0000000..2a35762
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ResultPrinter.java
@@ -0,0 +1,65 @@
+/*
+ * 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.it;
+
+import org.apache.servicecomb.it.junit.ITJUnitUtils;
+import org.apache.servicecomb.it.junit.SCBFailure;
+
+public class ResultPrinter {
+  private long start = System.currentTimeMillis();
+
+  public String formatTotalTime() {
+    long totalTime = System.currentTimeMillis() - start;
+    long hour = 0;
+    long minute = 0;
+    long second = 0;
+    second = totalTime / 1000;
+    if (totalTime <= 1000 && totalTime > 0) {
+      second = 1;
+    }
+    if (second > 60) {
+      minute = second / 60;
+      second = second % 60;
+    }
+    if (minute > 60) {
+      hour = minute / 60;
+      minute = minute % 60;
+    }
+    // 转换时分秒 00:00:00
+    String duration =
+        (hour >= 10 ? hour : "0" + hour) + ":" + (minute >= 10 ? minute : "0" + minute) + ":" + (second >= 10 ? second
+            : "0" + second);
+    return duration;
+  }
+
+  public void print() {
+    StringBuilder sb = new StringBuilder();
+    String totalTime = formatTotalTime();
+    for (SCBFailure failure : ITJUnitUtils.getFailures()) {
+      sb.append(String.format("%s, %s\n"
+              + "%s\n",
+          failure.getParents(),
+          failure.getTestHeader(),
+          failure.getTrace()));
+    }
+    sb.append(String.format("\nrun count:%d, failed count: %d, totalTime: %s.\n",
+        ITJUnitUtils.getRunCount(),
+        ITJUnitUtils.getFailures().size(),
+        totalTime));
+    System.out.println(sb.toString());
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/DeployDefinition.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/DeployDefinition.java
new file mode 100644
index 0000000..dfdc158
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/DeployDefinition.java
@@ -0,0 +1,86 @@
+/*
+ * 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.it.deploy;
+
+import io.vertx.core.json.Json;
+
+public class DeployDefinition {
+  protected String deployName;
+
+  protected String displayName;
+
+  /**
+   * <pre>
+   * edge as the example:
+   *  support:
+   *  1.absolute path: /home/xxx/it-edge/it-edge-1.0.0.jar
+   *  2.relate to work dir:
+   *      if work dir is /home/xxx
+   *      cmd is it-edge/it-edge-1.0.0.jar
+   *  3.run in ide, cmd is it-edge/it-edge-1.0.0.jar
+   *      will try: integration-tests/target/it-edge/it-edge-1.0.0.jar
+   *  4.run in ide, cmd is it-edge
+   *      will try: integration-tests/target/it-edge/it-edge-1.0.0.jar
+   *  </pre>
+   */
+  protected String cmd;
+
+  protected String[] args;
+
+  public String getDeployName() {
+    return deployName;
+  }
+
+  public void setDeployName(String deployName) {
+    this.deployName = deployName;
+  }
+
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
+  public String getCmd() {
+    return cmd;
+  }
+
+  public void setCmd(String cmd) {
+    this.cmd = cmd;
+  }
+
+  public String[] getArgs() {
+    return args;
+  }
+
+  public void setArgs(String[] args) {
+    this.args = args;
+  }
+
+  public void init() {
+    if (displayName == null) {
+      displayName = deployName;
+    }
+  }
+
+  @Override
+  public String toString() {
+    return Json.encodePrettily(this);
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/Deploys.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/Deploys.java
new file mode 100644
index 0000000..aae0dad
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/Deploys.java
@@ -0,0 +1,192 @@
+/*
+ * 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.it.deploy;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Deploys {
+  private static final Logger LOGGER = LoggerFactory.getLogger(Deploys.class);
+
+  private static final String DEFAULT_MICROSERVICE_VERSION = "1.0.0";
+
+  private String pomVersion;
+
+  public MicroserviceDeploy edge;
+
+  public MicroserviceDeploy baseProducer;
+
+  public MicroserviceDeploy zuul;
+
+  public MicroserviceDeploy getEdge() {
+    return edge;
+  }
+
+  public MicroserviceDeploy getZuul() {
+    return zuul;
+  }
+
+  public MicroserviceDeploy getBaseProducer() {
+    return baseProducer;
+  }
+
+  public void init() throws Throwable {
+    initPomVersion();
+    LOGGER.info("test version: {}", pomVersion);
+
+    initEdge();
+    initBaseProducer();
+//    initZuul();
+  }
+
+  public void setPomVersion(String pomVersion) {
+    this.pomVersion = pomVersion;
+  }
+
+  private void initPomVersion() throws Throwable {
+    // already set manually
+    if (pomVersion != null) {
+      return;
+    }
+
+    // already package to jar
+    pomVersion = Deploys.class.getPackage().getImplementationVersion();
+    if (pomVersion != null) {
+      return;
+    }
+
+    // run in ide
+    MavenXpp3Reader reader = new MavenXpp3Reader();
+    Model model = reader.read(new FileReader("pom.xml"));
+    pomVersion = model.getVersion();
+    if (pomVersion != null) {
+      return;
+    }
+
+    if (model.getParent() == null) {
+      throw new IllegalStateException("can not find pom ServiceComb version");
+    }
+
+    pomVersion = model.getParent().getVersion();
+    if (pomVersion != null) {
+      return;
+    }
+
+    throw new IllegalStateException("can not find pom ServiceComb version");
+  }
+
+  private void initDeployDefinition(DeployDefinition deployDefinition) {
+    deployDefinition.init();
+    doInitDeployDefinition(deployDefinition);
+    LOGGER.info("definition of {} is: {}", deployDefinition.getDeployName(), deployDefinition);
+  }
+
+  private void doInitDeployDefinition(DeployDefinition deployDefinition) {
+    // absolute path or relate to current work dir
+    File cmd = new File(deployDefinition.getCmd());
+    if (cmd.exists() && cmd.isFile()) {
+      deployDefinition.setCmd(cmd.getAbsolutePath());
+      return;
+    }
+
+    // run in ide
+    File workDir = new File("integration-tests");
+    if (initDeployDefinition(deployDefinition, workDir)) {
+      return;
+    }
+
+    // run "mvn install"
+    workDir = new File("..").getAbsoluteFile();
+    if (initDeployDefinition(deployDefinition, workDir)) {
+      return;
+    }
+
+    throw new IllegalStateException(String
+        .format("can not find deploy cmd, work dir: %s, definition: %s", new File("").getAbsolutePath(),
+            deployDefinition));
+  }
+
+  private boolean initDeployDefinition(DeployDefinition deployDefinition, File workDir) {
+    // deployDefinition.getCmd() is it-edge/target/it-edge-1.0.0.jar
+    File cmd = new File(workDir, deployDefinition.getCmd());
+    if (cmd.exists() && cmd.isFile()) {
+      deployDefinition.setCmd(cmd.getAbsolutePath());
+      return true;
+    }
+
+    // deployDefinition.getCmd() is it-edge
+    // change it-edge to it-edge/it-edge-1.0.0.jar
+    cmd = new File(workDir, String.format("%s/target/%s-%s.jar",
+        deployDefinition.getCmd(),
+        deployDefinition.getCmd(),
+        pomVersion));
+    if (cmd.exists()) {
+      try {
+        deployDefinition.setCmd(cmd.getCanonicalPath());
+      } catch (IOException e) {
+        throw new IllegalStateException("Failed to getCanonicalPath of " + cmd.getAbsolutePath(), e);
+      }
+      return true;
+    }
+
+    return false;
+  }
+
+  private void initBaseProducer() {
+    MicroserviceDeployDefinition baseProducerDefinition = new MicroserviceDeployDefinition();
+    baseProducerDefinition.setDeployName("baseProducer");
+    baseProducerDefinition.setCmd("it-producer");
+    baseProducerDefinition.setArgs(new String[] {});
+    baseProducerDefinition.setAppId("integration-test");
+    baseProducerDefinition.setMicroserviceName("it-producer");
+    baseProducerDefinition.setVersion(DEFAULT_MICROSERVICE_VERSION);
+
+    initDeployDefinition(baseProducerDefinition);
+
+    baseProducer = new MicroserviceDeploy(baseProducerDefinition);
+  }
+
+  private void initEdge() {
+    MicroserviceDeployDefinition edgeDefinition = new MicroserviceDeployDefinition();
+    edgeDefinition.setDeployName("edge");
+    edgeDefinition.setCmd("it-edge");
+    edgeDefinition.setArgs(new String[] {});
+    edgeDefinition.setAppId("integration-test");
+    edgeDefinition.setMicroserviceName("it-edge");
+    edgeDefinition.setVersion(DEFAULT_MICROSERVICE_VERSION);
+
+    initDeployDefinition(edgeDefinition);
+
+    edge = new MicroserviceDeploy(edgeDefinition);
+  }
+
+  //  private void initZuul() {
+  //    MicroserviceDeployDefinition zuulDefinition = new MicroserviceDeployDefinition();
+  //    zuulDefinition.setDeployName("zuul");
+  //    zuulDefinition.setCmd("it-zuul");
+  //
+  //    initDeployDefinition(zuulDefinition);
+  //
+  //    zuul = new MicroserviceDeploy(zuulDefinition);
+  //  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeploy.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeploy.java
new file mode 100644
index 0000000..0276882
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeploy.java
@@ -0,0 +1,71 @@
+/*
+ * 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.it.deploy;
+
+import org.apache.servicecomb.it.ITUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersionRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MicroserviceDeploy extends NormalDeploy {
+  private static final Logger LOGGER = LoggerFactory.getLogger(MicroserviceDeploy.class);
+
+  private MicroserviceDeployDefinition microserviceDeployDefinition;
+
+  public MicroserviceDeploy(DeployDefinition deployDefinition) {
+    super(deployDefinition);
+    this.microserviceDeployDefinition = (MicroserviceDeployDefinition) deployDefinition;
+  }
+
+  @Override
+  public void deploy() throws Throwable {
+    super.deploy();
+  }
+
+  @Override
+  protected String[] createCmds() {
+    return new String[] {"java", "-jar", deployDefinition.getCmd()};
+  }
+
+  public void ensureReady() throws Throwable {
+    MicroserviceVersionRule microserviceVersionRule = RegistryUtils.getServiceRegistry().getAppManager()
+        .getOrCreateMicroserviceVersionRule(microserviceDeployDefinition.getAppId(),
+            microserviceDeployDefinition.getMicroserviceName(),
+            microserviceDeployDefinition.getVersion());
+    if (microserviceVersionRule.getInstances().size() > 0) {
+      LOGGER.info("{} already ready.", microserviceDeployDefinition.getDisplayName());
+      return;
+    }
+
+    deploy();
+    ITUtils.waitMicroserviceReady(microserviceDeployDefinition.getAppId(),
+        microserviceDeployDefinition.getMicroserviceName(),
+        microserviceDeployDefinition.getVersion(),
+        1);
+  }
+
+  @Override
+  public void stop() {
+    if (subProcess == null) {
+      return;
+    }
+
+    sendCommand("ms-stop");
+    waitStop();
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeployDefinition.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeployDefinition.java
new file mode 100644
index 0000000..42d8d9e
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeployDefinition.java
@@ -0,0 +1,56 @@
+/*
+ * 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.it.deploy;
+
+public class MicroserviceDeployDefinition extends DeployDefinition {
+  private String appId;
+
+  private String microserviceName;
+
+  private String version;
+
+  public String getAppId() {
+    return appId;
+  }
+
+  public void setAppId(String appId) {
+    this.appId = appId;
+  }
+
+  public String getMicroserviceName() {
+    return microserviceName;
+  }
+
+  public void setMicroserviceName(String microserviceName) {
+    this.microserviceName = microserviceName;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  @Override
+  public void init() {
+    if (displayName == null) {
+      displayName = microserviceName + "-" + version;
+    }
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/NormalDeploy.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/NormalDeploy.java
new file mode 100644
index 0000000..f750f1e
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/NormalDeploy.java
@@ -0,0 +1,114 @@
+/*
+ * 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.it.deploy;
+
+
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NormalDeploy {
+  private static final Logger LOGGER = LoggerFactory.getLogger(NormalDeploy.class);
+
+  protected DeployDefinition deployDefinition;
+
+  protected Process subProcess;
+
+  protected BufferedWriter subProcessCommandWriter;
+
+  protected SubProcessLogger subProcessLogger;
+
+  public NormalDeploy(DeployDefinition deployDefinition) {
+    this.deployDefinition = deployDefinition;
+  }
+
+  public void deploy() throws Throwable {
+    String[] cmds = createCmds();
+    cmds = ArrayUtils.addAll(cmds, deployDefinition.getArgs());
+    cmds = ArrayUtils.addAll(cmds,
+        "-DselfController=" + RegistryUtils.getMicroserviceInstance().getInstanceId());
+
+    subProcess = createProcessBuilder(cmds).start();
+    subProcessCommandWriter = new BufferedWriter(new OutputStreamWriter(subProcess.getOutputStream()));
+    subProcessLogger = new SubProcessLogger(deployDefinition.getDisplayName(), subProcess.getInputStream());
+  }
+
+  protected String[] createCmds() {
+    return new String[] {deployDefinition.getCmd()};
+  }
+
+  protected ProcessBuilder createProcessBuilder(String[] cmds) {
+    return new ProcessBuilder(cmds).redirectErrorStream(true);
+  }
+
+  public void sendCommand(Object command) {
+    String strCmd = null;
+    try {
+      strCmd = JsonUtils.writeValueAsString(command);
+      subProcessCommandWriter.write(strCmd + "\n");
+      subProcessCommandWriter.flush();
+    } catch (Throwable e) {
+      LOGGER.error("Failed to send command, displayName={}, command={}", deployDefinition.getDisplayName(), strCmd, e);
+    }
+  }
+
+  protected void afterStop() {
+    IOUtils.closeQuietly(subProcessCommandWriter);
+    subProcessCommandWriter = null;
+
+    IOUtils.closeQuietly(subProcessLogger);
+    subProcessLogger = null;
+  }
+
+  public void waitStop() {
+    if (subProcess == null) {
+      LOGGER.info("Ignore, already stop, displayName={}.", deployDefinition.getDisplayName());
+      return;
+    }
+
+    for (; ; ) {
+      try {
+        subProcess.waitFor();
+        break;
+      } catch (InterruptedException e) {
+        LOGGER.info("Ignore InterruptedException, try to wait stop again, displayName={}.",
+            deployDefinition.getDisplayName());
+      }
+    }
+    subProcess = null;
+    afterStop();
+
+    LOGGER.info("finished stop {}.", deployDefinition.getDisplayName());
+  }
+
+  public void stop() {
+    if (subProcess == null) {
+      LOGGER.info("Ignore, already stop, displayName={}.", deployDefinition.getDisplayName());
+      return;
+    }
+
+    subProcess.destroy();
+    subProcess = null;
+    afterStop();
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/SubProcessLogger.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/SubProcessLogger.java
new file mode 100644
index 0000000..0189eef
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/SubProcessLogger.java
@@ -0,0 +1,68 @@
+/*
+ * 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.it.deploy;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SubProcessLogger implements Closeable {
+  private static final Logger LOGGER = LoggerFactory.getLogger(SubProcessLogger.class);
+
+  private final String displayName;
+
+  private BufferedReader reader;
+
+  private Thread thread;
+
+  public SubProcessLogger(String displayName, InputStream inputStream) {
+    this.displayName = displayName;
+
+    BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
+    this.reader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+    thread = new Thread(this::run, "SubProcessLogger-" + displayName);
+    thread.start();
+  }
+
+  private void run() {
+    try {
+      doRun();
+    } catch (IOException e) {
+      LOGGER.error("Failed to read log.", e);
+    }
+  }
+
+  private void doRun() throws IOException {
+    String line;
+    while ((line = reader.readLine()) != null) {
+      System.out.print(String.format("[%s] ", displayName));
+      System.out.println(line);
+    }
+  }
+
+  @Override
+  public void close() throws IOException {
+    reader.close();
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequest.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequest.java
new file mode 100644
index 0000000..567e487
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.it.extend.engine;
+
+import java.net.URI;
+
+import org.apache.servicecomb.core.CseContext;
+import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
+import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpRequest;
+import org.springframework.http.HttpMethod;
+
+public class ITClientHttpRequest extends CseClientHttpRequest {
+  private String transport;
+
+  public ITClientHttpRequest(URI uri, HttpMethod method, String transport) {
+    super(uri, method);
+    this.transport = transport;
+  }
+
+  @Override
+  protected ReferenceConfig findReferenceConfig(String microserviceName) {
+    ReferenceConfig referenceConfig = CseContext.getInstance().getConsumerProviderManager()
+        .createReferenceConfig(microserviceName);
+    if (transport != null) {
+      referenceConfig.setTransport(transport);
+    }
+    return referenceConfig;
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequestFactory.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequestFactory.java
new file mode 100644
index 0000000..5ec5ba6
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequestFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.it.extend.engine;
+
+import java.net.URI;
+
+import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpRequestFactory;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.ClientHttpRequest;
+
+public class ITClientHttpRequestFactory extends CseClientHttpRequestFactory {
+  private String transport;
+
+  public void setTransport(String transport) {
+    this.transport = transport;
+  }
+
+  @Override
+  public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
+    return new ITClientHttpRequest(uri, httpMethod, transport);
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITInvoker.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITInvoker.java
new file mode 100644
index 0000000..eea40b9
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITInvoker.java
@@ -0,0 +1,69 @@
+/*
+ * 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.it.extend.engine;
+
+import java.lang.reflect.Proxy;
+
+import org.apache.servicecomb.core.CseContext;
+import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
+import org.apache.servicecomb.provider.pojo.Invoker;
+
+/**
+ * allow set transport, that makes integration test easier
+ */
+public class ITInvoker extends Invoker {
+  public static <T> T createProxy(String microserviceName, String schemaId, String transport, Class<?> consumerIntf) {
+    ITInvoker invoker = new ITInvoker(microserviceName, schemaId, transport, consumerIntf);
+    return invoker.getProxy();
+  }
+
+  private String transport;
+
+  private Object proxy;
+
+  public ITInvoker(String microserviceName, String schemaId, String transport, Class<?> consumerIntf) {
+    super(microserviceName, schemaId, consumerIntf);
+    this.transport = transport;
+    this.proxy = Proxy.newProxyInstance(consumerIntf.getClassLoader(), new Class<?>[] {consumerIntf}, this);
+  }
+
+  public String getMicroserviceName() {
+    return microserviceName;
+  }
+
+  public String getSchemaId() {
+    return schemaId;
+  }
+
+  public String getTransport() {
+    return transport;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T> T getProxy() {
+    return (T) proxy;
+  }
+
+  @Override
+  protected ReferenceConfig findReferenceConfig() {
+    ReferenceConfig referenceConfig = CseContext.getInstance()
+        .getConsumerProviderManager()
+        .createReferenceConfig(microserviceName);
+    referenceConfig.setTransport(transport);
+    return referenceConfig;
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/ITJUnitUtils.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/ITJUnitUtils.java
new file mode 100644
index 0000000..fc9a2b2
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/ITJUnitUtils.java
@@ -0,0 +1,102 @@
+/*
+ * 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.it.junit;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.servicecomb.foundation.common.utils.JvmUtils;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+import com.google.common.reflect.ClassPath;
+
+public final class ITJUnitUtils {
+  private static ClassLoader classLoader = JvmUtils.findClassLoader();
+
+  private static JUnitCore jUnitCore = new JUnitCore();
+
+  private static Stack<String> parents = new Stack<>();
+
+  private static List<SCBFailure> failures = new ArrayList<>();
+
+  private static AtomicInteger runCount = new AtomicInteger();
+
+  static {
+    jUnitCore.addListener(new RunListener() {
+      @Override
+      public void testFailure(Failure failure) {
+        SCBFailure scbFailure = new SCBFailure(failure.getDescription(), failure.getException());
+        failures.add(scbFailure);
+        System.out.println(scbFailure.toString());
+      }
+    });
+  }
+
+  private ITJUnitUtils() {
+  }
+
+  public static int getRunCount() {
+    return runCount.get();
+  }
+
+  public static Stack<String> getParents() {
+    return parents;
+  }
+
+  public static void addParent(String name) {
+    parents.add(name);
+  }
+
+  public static void popParent() {
+    parents.pop();
+  }
+
+  public static List<String> cloneParents() {
+    return new ArrayList<>(parents);
+  }
+
+  public static List<SCBFailure> getFailures() {
+    return failures;
+  }
+
+  public static void runFromPackage(String packageName) {
+    Class<?>[] classes = findAllClassInPackage(packageName);
+    run(classes);
+  }
+
+  public static void run(Class<?>... classes) {
+    Result result = jUnitCore.run(classes);
+    runCount.addAndGet(result.getRunCount());
+  }
+
+  public static Class<?>[] findAllClassInPackage(String packageName) {
+    try {
+      return ClassPath.from(classLoader)
+          .getTopLevelClassesRecursive(packageName).stream()
+          .map(clsInfo -> clsInfo.load())
+          .toArray(Class[]::new);
+    } catch (IOException e) {
+      throw new IllegalStateException("failed to find all classes in package " + packageName, e);
+    }
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/SCBFailure.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/SCBFailure.java
new file mode 100644
index 0000000..faa3c23
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/SCBFailure.java
@@ -0,0 +1,37 @@
+/*
+ * 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.it.junit;
+
+import java.util.List;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+
+public class SCBFailure extends Failure {
+  private static final long serialVersionUID = 6467681668616080232L;
+
+  private List<String> parents;
+
+  public SCBFailure(Description description, Throwable thrownException) {
+    super(description, thrownException);
+    parents = ITJUnitUtils.cloneParents();
+  }
+
+  public List<String> getParents() {
+    return parents;
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypePojo.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypePojo.java
new file mode 100644
index 0000000..a7d660e
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypePojo.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it.testcase.base;
+
+import org.apache.servicecomb.it.extend.engine.ITClientHttpRequestFactory;
+import org.apache.servicecomb.it.extend.engine.ITInvoker;
+import org.apache.servicecomb.it.testcase.support.DataTypePojoIntf;
+import org.apache.servicecomb.it.testcase.support.ProducerDevMode;
+import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.web.client.RestTemplate;
+
+public class TestDataTypePojo {
+  private static DataTypePojoIntf dataTypePojoIntf;
+
+  private static ITClientHttpRequestFactory clientHttpRequestFactory = new ITClientHttpRequestFactory();
+
+  private static RestTemplate restTemplate = new CseRestTemplate();
+
+  private static String urlPrefix;
+
+  private static String transport;
+
+  static {
+    restTemplate.setRequestFactory(clientHttpRequestFactory);
+  }
+
+  public static void init(String transport, ProducerDevMode producerDevMode) {
+    TestDataTypePojo.transport = transport;
+    dataTypePojoIntf = ITInvoker.createProxy("it-producer", "dataTypePojo", transport, DataTypePojoIntf.class);
+
+    clientHttpRequestFactory.setTransport(transport);
+
+    urlPrefix = "cse://it-producer/v1/dataType" + producerDevMode.name();
+  }
+
+  @Test
+  public void checkTransport_intf() {
+    Assert.assertEquals(transport, dataTypePojoIntf.checkTransport());
+  }
+
+  @Test
+  public void checkTransport_rt() {
+    Assert.assertEquals(transport, restTemplate.postForObject(urlPrefix + "/checkTransport", "", String.class));
+  }
+
+  @Test
+  public void intBody_intf() {
+    Assert.assertEquals(10, dataTypePojoIntf.intBody(10));
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypeRest.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypeRest.java
new file mode 100644
index 0000000..72d8c5d
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypeRest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it.testcase.base;
+
+import org.apache.servicecomb.it.extend.engine.ITClientHttpRequestFactory;
+import org.apache.servicecomb.it.extend.engine.ITInvoker;
+import org.apache.servicecomb.it.testcase.support.DataTypeRestIntf;
+import org.apache.servicecomb.it.testcase.support.ProducerDevMode;
+import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.web.client.RestTemplate;
+
+public class TestDataTypeRest {
+  private static DataTypeRestIntf dataTypeIntf;
+
+  private static ITClientHttpRequestFactory clientHttpRequestFactory = new ITClientHttpRequestFactory();
+
+  private static RestTemplate restTemplate = new CseRestTemplate();
+
+  private static String urlPrefix;
+
+  private static String transport;
+
+  static {
+    restTemplate.setRequestFactory(clientHttpRequestFactory);
+  }
+
+  public static void init(String transport, ProducerDevMode producerDevMode) {
+    TestDataTypeRest.transport = transport;
+    dataTypeIntf = ITInvoker
+        .createProxy("it-producer", "dataType" + producerDevMode.name(), transport, DataTypeRestIntf.class);
+
+    clientHttpRequestFactory.setTransport(transport);
+
+    urlPrefix = "cse://it-producer/v1/dataType" + producerDevMode.name();
+  }
+
+  @Test
+  public void checkTransport_intf() {
+    Assert.assertEquals(transport, dataTypeIntf.checkTransport());
+  }
+
+  @Test
+  public void checkTransport_rt() {
+    Assert.assertEquals(transport, restTemplate.getForObject(urlPrefix + "/checkTransport", String.class));
+  }
+
+  @Test
+  public void intPath_intf() {
+    int expect = 10;
+    Assert.assertEquals(expect, dataTypeIntf.intPath(expect));
+  }
+
+  @Test
+  public void intPath_rt() {
+    int expect = 10;
+    Assert.assertEquals(expect, (int) restTemplate.getForObject(urlPrefix + "/intPath/" + expect, int.class));
+  }
+
+  @Test
+  public void intQuery() {
+    Assert.assertEquals(10, dataTypeIntf.intQuery(10));
+  }
+
+  @Test
+  public void intHeader() {
+    Assert.assertEquals(10, dataTypeIntf.intHeader(10));
+  }
+
+  @Test
+  public void intCookie() {
+    Assert.assertEquals(10, dataTypeIntf.intCookie(10));
+  }
+
+  @Test
+  public void intBody() {
+    Assert.assertEquals(10, dataTypeIntf.intBody(10));
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDownload.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDownload.java
new file mode 100644
index 0000000..b84c0a4
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDownload.java
@@ -0,0 +1,142 @@
+/*
+ * 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.it.testcase.base;
+
+import org.apache.servicecomb.it.testcase.support.DownloadSchemaIntf;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDownload {
+  private static DownloadSchemaIntf intf = Invoker
+      .createProxy("it-producer", "download", DownloadSchemaIntf.class);
+
+  static int x;
+
+  @Test
+  public void test1() {
+    x++;
+    System.out.println("test" + x);
+//    intf.tempFileEntity("abc");
+  }
+
+  @Test
+  public void test2() {
+    x++;
+    System.out.println("test2");
+    Assert.assertEquals(x, x + 1);
+  }
+//  private File dir = new File("target/download");
+//
+//
+//  private RestTemplate restTemplate = new CseRestTemplate();
+//
+//  private String prefix = "cse://springmvc/download";
+//
+//  private List<CompletableFuture<?>> futures = new ArrayList<>();
+//
+//  private String content = "file content";
+//
+//  public TestDownload() {
+//    FileUtils.deleteQuietly(dir);
+//  }
+//
+//  private String readFileToString(File file) {
+//    try {
+//      return FileUtils.readFileToString(file);
+//    } catch (IOException e) {
+//      return "read file failed:" + e.getMessage();
+//    }
+//  }
+//
+//  private CompletableFuture<File> checkFile(ReadStreamPart part) {
+//    CompletableFuture<File> future = part.saveToFile("target/download/"
+//        + UUID.randomUUID().toString()
+//        + "-"
+//        + part.getSubmittedFileName());
+//    return checkFuture(future);
+//  }
+//
+//  private <T> CompletableFuture<T> checkFuture(CompletableFuture<T> future) {
+//    Error error = new Error();
+//    future.whenComplete((result, e) -> {
+//      Object value = result;
+//      if (File.class.isInstance(value)) {
+//        File file = (File) value;
+//        value = readFileToString(file);
+//        file.delete();
+//      } else if (byte[].class.isInstance(value)) {
+//        value = new String((byte[]) value);
+//      }
+//
+//      TestMgr.check(content, value, error);
+//    });
+//
+//    return future;
+//  }
+//
+//  private ReadStreamPart templateGet(String methodPath) {
+//    return restTemplate
+//        .getForObject(prefix + "/" + methodPath + "?content={content}",
+//            ReadStreamPart.class,
+//            content);
+//  }
+//
+//  public void runRest() {
+//    futures.add(checkFile(intf.tempFileEntity(content)));
+//    futures.add(checkFuture(templateGet("tempFileEntity").saveAsBytes()));
+//
+//    futures.add(checkFile(intf.tempFilePart(content)));
+//    futures.add(checkFuture(templateGet("tempFilePart").saveAsString()));
+//
+//    futures.add(checkFile(intf.file(content)));
+//    futures.add(checkFuture(templateGet("file").saveAsString()));
+//
+//    {
+//      ReadStreamPart part = intf.chineseAndSpaceFile(content);
+//      TestMgr.check("测 试.test.txt", part.getSubmittedFileName());
+//      futures.add(checkFile(part));
+//
+//      part = templateGet("chineseAndSpaceFile");
+//      TestMgr.check("测 试.test.txt", part.getSubmittedFileName());
+//      futures.add(checkFuture(part.saveAsString()));
+//    }
+//
+//    futures.add(checkFile(intf.resource(content)));
+//    futures.add(checkFuture(templateGet("resource").saveAsString()));
+//
+//    futures.add(checkFile(intf.entityResource(content)));
+//    futures.add(checkFuture(templateGet("entityResource").saveAsString()));
+//
+//    futures.add(checkFile(intf.entityInputStream(content)));
+//    futures.add(checkFuture(templateGet("entityInputStream").saveAsString()));
+//
+//    futures.add(checkFile(intf.bytes(content)));
+//    futures.add(checkFuture(templateGet("bytes").saveAsString()));
+//
+//    futures.add(checkFile(intf.netInputStream(content)));
+//    futures.add(checkFuture(templateGet("netInputStream").saveAsString()));
+//
+//    try {
+//      CompletableFuture
+//          .allOf(futures.toArray(new CompletableFuture[futures.size()]))
+//          .get();
+//    } catch (InterruptedException | ExecutionException e1) {
+//      TestMgr.failed("test download failed.", e1);
+//    }
+//  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestGeneric.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestGeneric.java
new file mode 100644
index 0000000..4c85af1
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestGeneric.java
@@ -0,0 +1,26 @@
+/*
+ * 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.it.testcase.base;
+
+import org.junit.Test;
+
+public class TestGeneric {
+  @Test
+  public void test() {
+
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypePojoIntf.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypePojoIntf.java
new file mode 100644
index 0000000..7146279
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypePojoIntf.java
@@ -0,0 +1,22 @@
+package org.apache.servicecomb.it.testcase.support;/*
+ * 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.
+ */
+
+public interface DataTypePojoIntf {
+  String checkTransport();
+
+  int intBody(int input);
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypeRestIntf.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypeRestIntf.java
new file mode 100644
index 0000000..3a794b9
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypeRestIntf.java
@@ -0,0 +1,30 @@
+package org.apache.servicecomb.it.testcase.support;/*
+ * 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.
+ */
+
+public interface DataTypeRestIntf {
+  String checkTransport();
+
+  int intPath(int input);
+
+  int intQuery(int input);
+
+  int intHeader(int input);
+
+  int intCookie(int input);
+
+  int intBody(int input);
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DownloadSchemaIntf.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DownloadSchemaIntf.java
new file mode 100644
index 0000000..9bc373f
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DownloadSchemaIntf.java
@@ -0,0 +1,39 @@
+/*
+ * 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.it.testcase.support;
+
+import org.apache.servicecomb.foundation.vertx.http.ReadStreamPart;
+
+public interface DownloadSchemaIntf {
+  ReadStreamPart tempFileEntity(String content);
+
+  ReadStreamPart tempFilePart(String content);
+
+  ReadStreamPart file(String content);
+
+  ReadStreamPart chineseAndSpaceFile(String content);
+
+  ReadStreamPart resource(String content);
+
+  ReadStreamPart entityResource(String content);
+
+  ReadStreamPart entityInputStream(String content);
+
+  ReadStreamPart bytes(String content);
+
+  ReadStreamPart netInputStream(String content);
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/ProducerDevMode.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/ProducerDevMode.java
new file mode 100644
index 0000000..c264293
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/ProducerDevMode.java
@@ -0,0 +1,22 @@
+package org.apache.servicecomb.it.testcase.support;/*
+ * 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.
+ */
+
+public enum ProducerDevMode {
+  Pojo,
+  Jaxrs,
+  Springmvc
+}
diff --git a/integration-tests/it-consumer/src/main/resources/microservice.yaml b/integration-tests/it-consumer/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..387fcb3
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/resources/microservice.yaml
@@ -0,0 +1,19 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+service_description:
+  name: it-consumer
diff --git a/integration-tests/it-consumer/src/test/java/org/apache/servicecomb/it/TestMain.java b/integration-tests/it-consumer/src/test/java/org/apache/servicecomb/it/TestMain.java
new file mode 100644
index 0000000..ce4b42f
--- /dev/null
+++ b/integration-tests/it-consumer/src/test/java/org/apache/servicecomb/it/TestMain.java
@@ -0,0 +1,30 @@
+/*
+ * 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.it;
+
+import org.apache.servicecomb.it.junit.ITJUnitUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestMain {
+  @Test
+  public void testMain() throws Throwable {
+    ConsumerMain.autoExit = false;
+    ConsumerMain.main(new String[] {});
+    Assert.assertTrue(ITJUnitUtils.getFailures().isEmpty());
+  }
+}
diff --git a/integration-tests/it-edge/enable-it-jar b/integration-tests/it-edge/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-edge/pom.xml b/integration-tests/it-edge/pom.xml
new file mode 100644
index 0000000..6ac4123
--- /dev/null
+++ b/integration-tests/it-edge/pom.xml
@@ -0,0 +1,53 @@
+<?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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>integration-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>it-edge</artifactId>
+  <name>Java Chassis::IT::Edge</name>
+
+  <properties>
+    <it.main>org.apache.servicecomb.it.edge.EdgeMain</it.main>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>it-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>edge-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>handler-loadbalance</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-pojo</artifactId>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/Auth.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/Auth.java
new file mode 100644
index 0000000..6718069
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/Auth.java
@@ -0,0 +1,24 @@
+/*
+ * 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.it.authentication;
+
+import java.util.concurrent.CompletableFuture;
+
+public interface Auth {
+  CompletableFuture<Boolean> auth(String info);
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/encrypt/Hcr.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/encrypt/Hcr.java
new file mode 100644
index 0000000..c219b0e
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/encrypt/Hcr.java
@@ -0,0 +1,39 @@
+/*
+ * 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.it.authentication.encrypt;
+
+public class Hcr {
+  private String bodyKey;
+
+  private String signatureKey;
+
+  public String getBodyKey() {
+    return bodyKey;
+  }
+
+  public void setBodyKey(String bodyKey) {
+    this.bodyKey = bodyKey;
+  }
+
+  public String getSignatureKey() {
+    return signatureKey;
+  }
+
+  public void setSignatureKey(String signatureKey) {
+    this.signatureKey = signatureKey;
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeConst.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeConst.java
new file mode 100644
index 0000000..a8d1b52
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeConst.java
@@ -0,0 +1,20 @@
+package org.apache.servicecomb.it.edge;/*
+ * 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.
+ */
+
+public interface EdgeConst {
+  String ENCRYPT_CONTEXT = "encryptContext";
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeDispatcher.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeDispatcher.java
new file mode 100644
index 0000000..7770c7c
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeDispatcher.java
@@ -0,0 +1,58 @@
+/*
+ * 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.it.edge;
+
+import java.util.Map;
+
+import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher;
+import org.apache.servicecomb.edge.core.CompatiblePathVersionMapper;
+import org.apache.servicecomb.edge.core.EdgeInvocation;
+
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.CookieHandler;
+
+public class EdgeDispatcher extends AbstractEdgeDispatcher {
+  private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper();
+
+  @Override
+  public int getOrder() {
+    return 10000;
+  }
+
+  @Override
+  public void init(Router router) {
+    String regex = "/api/([^\\\\/]+)/([^\\\\/]+)/(.*)";
+    router.routeWithRegex(regex).handler(CookieHandler.create());
+    router.routeWithRegex(regex).handler(createBodyHandler());
+    router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest);
+  }
+
+  protected void onRequest(RoutingContext context) {
+    Map<String, String> pathParams = context.pathParams();
+    String microserviceName = pathParams.get("param0");
+    String pathVersion = pathParams.get("param1");
+    String path = context.request().path().substring(5 + microserviceName.length());
+
+    EdgeInvocation edgeInvocation = new EdgeInvocation();
+    edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule());
+
+    edgeInvocation.init(microserviceName, context, path, httpServerFilters);
+    edgeInvocation.edgeInvoke();
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeMain.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeMain.java
new file mode 100644
index 0000000..3a042c6
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeMain.java
@@ -0,0 +1,26 @@
+/*
+ * 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.it.edge;
+
+import org.apache.servicecomb.it.ITMain;
+
+public class EdgeMain {
+  public static void main(String[] args) {
+    ITMain.main(args);
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/Encrypt.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/Encrypt.java
new file mode 100644
index 0000000..cacc213
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/Encrypt.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.it.edge.encrypt;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+
+public interface Encrypt {
+  CompletableFuture<String> queryUserId(String serviceToken);
+
+  CompletableFuture<Hcr> queryHcr(String hcrId);
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptContext.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptContext.java
new file mode 100644
index 0000000..0f03796
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptContext.java
@@ -0,0 +1,46 @@
+/*
+ * 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.it.edge.encrypt;
+
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+
+public class EncryptContext {
+  private Hcr hcr;
+
+  private String userId;
+
+  public EncryptContext(Hcr hcr, String userId) {
+    this.hcr = hcr;
+    this.userId = userId;
+  }
+
+  public Hcr getHcr() {
+    return hcr;
+  }
+
+  public void setHcr(Hcr hcr) {
+    this.hcr = hcr;
+  }
+
+  public String getUserId() {
+    return userId;
+  }
+
+  public void setUserId(String userId) {
+    this.userId = userId;
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeDispatcher.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeDispatcher.java
new file mode 100644
index 0000000..6c2bca7
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeDispatcher.java
@@ -0,0 +1,114 @@
+/*
+ * 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.it.edge.encrypt;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher;
+import org.apache.servicecomb.edge.core.CompatiblePathVersionMapper;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.vertx.core.http.HttpServerRequest;
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.CookieHandler;
+
+public class EncryptEdgeDispatcher extends AbstractEdgeDispatcher {
+  private static final Logger LOGGER = LoggerFactory.getLogger(EncryptEdgeDispatcher.class);
+
+  private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper();
+
+  private Encrypt encrypt = Invoker.createProxy("auth", "encrypt", Encrypt.class);
+
+  private String prefix = "encryptApi";
+
+  @Override
+  public int getOrder() {
+    return 10000;
+  }
+
+  @Override
+  public void init(Router router) {
+    {
+      String regex = "/" + prefix + "/([^\\\\/]+)/([^\\\\/]+)/(.*)";
+      router.routeWithRegex(regex).handler(CookieHandler.create());
+      router.routeWithRegex(regex).handler(createBodyHandler());
+      router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest);
+    }
+  }
+
+  protected void onRequest(RoutingContext context) {
+    HttpServerRequest httpServerRequest = context.request();
+
+    // queryUserId always success
+    CompletableFuture<String> userIdFuture = queryUserId(httpServerRequest);
+    queryHcr(httpServerRequest).thenCombine(userIdFuture, (hcr, userId) -> {
+      // hcr and userId all success
+      routeToBackend(context, hcr, userId);
+      return null;
+    }).whenComplete((v, e) -> {
+      // failed to query hcr
+      if (e != null) {
+        context.response().end("failed to query hcr: " + e.getMessage());
+        return;
+      }
+    });
+  }
+
+  private CompletableFuture<String> queryUserId(HttpServerRequest httpServerRequest) {
+    String serviceToken = httpServerRequest.getParam("serviceToken");
+    if (serviceToken == null) {
+      // no need to query userId
+      return CompletableFuture.completedFuture(null);
+    }
+
+    CompletableFuture<String> future = new CompletableFuture<>();
+    encrypt.queryUserId(serviceToken).whenComplete((userId, e) -> {
+      if (e != null) {
+        // treat as success, just userId is null
+        LOGGER.error("Failed to query userId, serviceToken={}.", serviceToken, e);
+      }
+
+      future.complete(userId);
+    });
+
+    return future;
+  }
+
+  private CompletableFuture<Hcr> queryHcr(HttpServerRequest httpServerRequest) {
+    String hcrId = httpServerRequest.getParam("hcrId");
+    return encrypt.queryHcr(hcrId);
+  }
+
+  private void routeToBackend(RoutingContext context, Hcr hcr, String userId) {
+    Map<String, String> pathParams = context.pathParams();
+    String microserviceName = pathParams.get("param0");
+    String pathVersion = pathParams.get("param1");
+    String path = context.request().path().substring(prefix.length() + 1);
+
+    EncryptEdgeInvocation edgeInvocation = new EncryptEdgeInvocation(new EncryptContext(hcr, userId));
+    edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule());
+
+    edgeInvocation.init(microserviceName, context, path, httpServerFilters);
+    edgeInvocation.edgeInvoke();
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeInvocation.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeInvocation.java
new file mode 100644
index 0000000..c9d2c92
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeInvocation.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it.edge.encrypt;
+
+import org.apache.servicecomb.edge.core.EdgeInvocation;
+
+public class EncryptEdgeInvocation extends EdgeInvocation {
+  private EncryptContext encryptContext;
+
+  public EncryptEdgeInvocation(EncryptContext encryptContext) {
+    this.encryptContext = encryptContext;
+  }
+
+  @Override
+  protected void createInvocation() {
+    super.createInvocation();
+
+    invocation.getHandlerContext().put("encryptContext", encryptContext);
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/DecodeBodyFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/DecodeBodyFilter.java
new file mode 100644
index 0000000..00f3974
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/DecodeBodyFilter.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it.edge.encrypt.filter;
+
+import java.util.Map;
+
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+public class DecodeBodyFilter implements HttpServerFilter {
+  private JavaType bodyType = TypeFactory.defaultInstance().constructMapType(Map.class, String.class, String[].class);
+
+  @Override
+  public int getOrder() {
+    return -9000;
+  }
+
+  @Override
+  public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+    EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+    if (encryptContext == null) {
+      return null;
+    }
+    Hcr hcr = encryptContext.getHcr();
+
+    String encodedBody = requestEx.getParameter("body");
+    if (encodedBody == null) {
+      return null;
+    }
+
+    encodedBody = encodedBody.substring(hcr.getBodyKey().length());
+
+    try {
+      Map<String, String[]> decodedBody = RestObjectMapperFactory.getRestObjectMapper()
+          .readValue(encodedBody, bodyType);
+      requestEx.getParameterMap().putAll(decodedBody);
+    } catch (Throwable e) {
+      // should be a meaning exception response
+      return Response.producerFailResp(e);
+    }
+    return null;
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureRequestFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureRequestFilter.java
new file mode 100644
index 0000000..3eb6090
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureRequestFilter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.it.edge.encrypt.filter;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+public class EdgeSignatureRequestFilter implements HttpServerFilter {
+  private static final Logger LOGGER = LoggerFactory.getLogger(EdgeSignatureRequestFilter.class);
+
+  @Override
+  public int getOrder() {
+    return -10000;
+  }
+
+  @Override
+  public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+    EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+    if (encryptContext == null) {
+      return null;
+    }
+    Hcr hcr = encryptContext.getHcr();
+
+    // signature for query and form
+    List<String> names = Collections.list(requestEx.getParameterNames());
+    names.sort(Comparator.naturalOrder());
+
+    Hasher hasher = Hashing.sha256().newHasher();
+    hasher.putString(hcr.getSignatureKey(), StandardCharsets.UTF_8);
+    for (String name : names) {
+      hasher.putString(name, StandardCharsets.UTF_8);
+      hasher.putString(requestEx.getParameter(name), StandardCharsets.UTF_8);
+    }
+    LOGGER.info("afterReceiveRequest signature: {}", hasher.hash().toString());
+
+    return null;
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java
new file mode 100644
index 0000000..b625135
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java
@@ -0,0 +1,76 @@
+/*
+ * 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.it.edge.encrypt.filter;
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+import io.vertx.core.buffer.Buffer;
+
+public class EdgeSignatureResponseFilter implements HttpServerFilter {
+  private static final Logger LOGGER = LoggerFactory.getLogger(EdgeSignatureResponseFilter.class);
+
+  @Override
+  public int getOrder() {
+    return 10000;
+  }
+
+  @Override
+  public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+    return null;
+  }
+
+  @Override
+  public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
+    if (invocation == null) {
+      return;
+    }
+
+    EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+    if (encryptContext == null) {
+      return;
+    }
+    Hcr hcr = encryptContext.getHcr();
+
+    // bad practice: it's better to set signature in response header
+    Buffer bodyBuffer = responseEx.getBodyBuffer();
+    String body = bodyBuffer.toString();
+    if (body.endsWith("}")) {
+      Hasher hasher = Hashing.sha256().newHasher();
+      hasher.putString(hcr.getSignatureKey(), StandardCharsets.UTF_8);
+      hasher.putString(body, StandardCharsets.UTF_8);
+      String signature = hasher.hash().toString();
+      LOGGER.info("beforeSendResponse signature: {}", signature);
+
+      body = body.substring(0, body.length() - 1) + ",\"signature\":\"" + signature + "\"}";
+      responseEx.setBodyBuffer(Buffer.buffer(body));
+    }
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/UserIdFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/UserIdFilter.java
new file mode 100644
index 0000000..083dd69
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/UserIdFilter.java
@@ -0,0 +1,46 @@
+/*
+ * 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.it.edge.encrypt.filter;
+
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+public class UserIdFilter implements HttpServerFilter {
+  @Override
+  public int getOrder() {
+    return -8000;
+  }
+
+  @Override
+  public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+    EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+    if (encryptContext == null) {
+      return null;
+    }
+
+    String userId = encryptContext.getUserId();
+    if (userId != null) {
+      requestEx.setParameter("userId", userId);
+    }
+
+    return null;
+  }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/handler/AuthHandler.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/handler/AuthHandler.java
new file mode 100644
index 0000000..691d27c
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/handler/AuthHandler.java
@@ -0,0 +1,74 @@
+/*
+ * 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.it.edge.handler;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.servicecomb.core.Handler;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.definition.MicroserviceMeta;
+import org.apache.servicecomb.it.authentication.Auth;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AuthHandler implements Handler {
+  private static Logger LOGGER = LoggerFactory.getLogger(AuthHandler.class);
+
+  private static Auth auth;
+
+  static {
+    auth = Invoker.createProxy("auth", "auth", Auth.class);
+  }
+
+  @Override
+  public void init(MicroserviceMeta microserviceMeta, InvocationType invocationType) {
+  }
+
+  @Override
+  public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception {
+    if (invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT) != null) {
+      invocation.next(asyncResp);
+      return;
+    }
+
+    auth.auth("").whenComplete((succ, e) -> doHandle(invocation, asyncResp, succ, e));
+  }
+
+  protected void doHandle(Invocation invocation, AsyncResponse asyncResp, Boolean authSucc, Throwable authException) {
+    if (authException != null) {
+      asyncResp.consumerFail(new InvocationException(Status.UNAUTHORIZED, (Object) authException.getMessage()));
+      return;
+    }
+
+    if (!authSucc) {
+      asyncResp.consumerFail(new InvocationException(Status.UNAUTHORIZED, (Object) "auth failed"));
+    }
+
+    LOGGER.debug("auth success.");
+    try {
+      invocation.next(asyncResp);
+    } catch (Throwable e) {
+      asyncResp.consumerFail(e);
+    }
+  }
+}
diff --git a/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
new file mode 100644
index 0000000..a0e033d
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.it.edge.encrypt.filter.EdgeSignatureRequestFilter
+org.apache.servicecomb.it.edge.encrypt.filter.DecodeBodyFilter
+org.apache.servicecomb.it.edge.encrypt.filter.UserIdFilter
+org.apache.servicecomb.it.edge.encrypt.filter.EdgeSignatureResponseFilter
\ No newline at end of file
diff --git a/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
new file mode 100644
index 0000000..66f422f
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.it.edge.EdgeDispatcher
+org.apache.servicecomb.it.edge.encrypt.EncryptEdgeDispatcher
diff --git a/integration-tests/it-edge/src/main/resources/config/cse.handler.xml b/integration-tests/it-edge/src/main/resources/config/cse.handler.xml
new file mode 100644
index 0000000..c9027e7
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/config/cse.handler.xml
@@ -0,0 +1,20 @@
+<!--
+  ~ 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.
+  -->
+
+<config>
+  <handler id="auth" class="org.apache.servicecomb.it.edge.handler.AuthHandler"/>
+</config>
diff --git a/integration-tests/it-edge/src/main/resources/microservice.yaml b/integration-tests/it-edge/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..b57a630
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/microservice.yaml
@@ -0,0 +1,48 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+service_description:
+  name: it-edge
+
+servicecomb:
+  handler:
+    chain:
+      Consumer:
+        default: auth,loadbalance
+        service:
+          it-auth: loadbalance
+  http:
+    dispatcher:
+      edge:
+        default:
+          enabled: true
+          prefix: rest
+          withVersion: true
+          prefixSegmentCount: 1
+        url:
+          enabled: true
+          mappings:
+            businessV1:
+              prefixSegmentCount: 1
+              path: "/url/business/v1/.*"
+              microserviceName: business
+              versionRule: 1.0.0-2.0.0
+            businessV2:
+              prefixSegmentCount: 1
+              path: "/url/business/v2/.*"
+              microserviceName: business
+              versionRule: 2.0.0-3.0.0
diff --git a/integration-tests/it-producer/enable-it-jar b/integration-tests/it-producer/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-producer/pom.xml b/integration-tests/it-producer/pom.xml
new file mode 100644
index 0000000..2739a43
--- /dev/null
+++ b/integration-tests/it-producer/pom.xml
@@ -0,0 +1,41 @@
+<?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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>integration-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>it-producer</artifactId>
+  <name>Java Chassis::IT::Producer</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>it-common</artifactId>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <it.main>org.apache.servicecomb.it.BaseProducerMain</it.main>
+  </properties>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/BaseProducerMain.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/BaseProducerMain.java
new file mode 100644
index 0000000..37c7191
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/BaseProducerMain.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it;
+
+public class BaseProducerMain {
+  public static void main(String[] args) {
+    ITMain.main(args);
+  }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeJaxrs.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeJaxrs.java
new file mode 100644
index 0000000..b9b7b13
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeJaxrs.java
@@ -0,0 +1,74 @@
+/*
+ * 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.it.schema;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+
+@RestSchema(schemaId = "dataTypeJaxrs")
+@Path("/v1/dataTypeJaxrs")
+public class DataTypeJaxrs {
+  private DataTypePojo pojo = new DataTypePojo();
+
+  public void test(HttpServletRequest request, HttpServletResponse response) {
+
+  }
+
+  @Path("checkTransport")
+  @GET
+  public String checkTransport(HttpServletRequest request) {
+    return pojo.checkTransport(request);
+  }
+
+  @Path("intPath/{input}")
+  @GET
+  public int intPath(@PathParam("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @Path("intQuery")
+  @GET
+  public int intQuery(@QueryParam("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @Path("intHeader")
+  @GET
+  public int intHeader(@HeaderParam("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @Path("intCookie")
+  @GET
+  public int intCookie(@CookieParam("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @Path("intBody")
+  @GET
+  public int intBody(int input) {
+    return pojo.intBody(input);
+  }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypePojo.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypePojo.java
new file mode 100644
index 0000000..9027573
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypePojo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.it.schema;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.servicecomb.core.Const;
+import org.apache.servicecomb.provider.pojo.RpcSchema;
+import org.apache.servicecomb.provider.rest.common.InvocationToHttpServletRequest;
+import org.apache.servicecomb.transport.highway.HighwayTransport;
+
+import io.swagger.annotations.SwaggerDefinition;
+
+@RpcSchema(schemaId = "dataTypePojo")
+@SwaggerDefinition(basePath = "/v1/dataTypePojo")
+public class DataTypePojo {
+  public String checkTransport(HttpServletRequest request) {
+    if (InvocationToHttpServletRequest.class.isInstance(request)) {
+      return HighwayTransport.NAME;
+    }
+
+    return Const.RESTFUL;
+  }
+
+  public int intBody(int input) {
+    return input;
+  }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeSpringmvc.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeSpringmvc.java
new file mode 100644
index 0000000..19104b7
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeSpringmvc.java
@@ -0,0 +1,64 @@
+/*
+ * 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.it.schema;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "dataTypeSpringmvc")
+@RequestMapping(path = "/v1/dataTypeSpringmvc")
+public class DataTypeSpringmvc {
+  private DataTypePojo pojo = new DataTypePojo();
+
+  @GetMapping(path = "checkTransport")
+  public String checkTransport(HttpServletRequest request) {
+    return pojo.checkTransport(request);
+  }
+
+  @GetMapping("intPath/{input}")
+  public int intPath(@PathVariable("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @GetMapping("intQuery")
+  public int intQuery(@RequestParam("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @GetMapping("intHeader")
+  public int intHeader(@RequestHeader("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @GetMapping("intCookie")
+  public int intCookie(@CookieValue("input") int input) {
+    return pojo.intBody(input);
+  }
+
+  @GetMapping("intBody")
+  public int intBody(@RequestBody int input) {
+    return pojo.intBody(input);
+  }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
new file mode 100644
index 0000000..6ea0442
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
@@ -0,0 +1,195 @@
+/*
+ * 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.it.schema;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.UUID;
+
+import javax.servlet.http.Part;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.bootstrap.HttpServer;
+import org.apache.http.impl.bootstrap.ServerBootstrap;
+import org.apache.servicecomb.core.BootListener;
+import org.apache.servicecomb.foundation.common.part.FilePart;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+@RestSchema(schemaId = "download")
+@RequestMapping(path = "/base/v1//download")
+public class DownloadSchema implements BootListener {
+  File tempDir = new File("target/downloadTemp");
+
+  HttpServer server;
+
+  public DownloadSchema() throws IOException {
+    FileUtils.deleteQuietly(tempDir);
+    FileUtils.forceMkdir(tempDir);
+
+    // for download from net stream case
+    server = ServerBootstrap
+        .bootstrap()
+        .setListenerPort(9000)
+        .registerHandler("/download/netInputStream", (req, resp, context) -> {
+          String uri = req.getRequestLine().getUri();
+          String query = URI.create(uri).getQuery();
+          int idx = query.indexOf('=');
+          String content = query.substring(idx + 1);
+          content = URLDecoder.decode(content, StandardCharsets.UTF_8.name());
+          resp.setEntity(new StringEntity(content, StandardCharsets.UTF_8.name()));
+        }).create();
+    server.start();
+  }
+
+  @Override
+  public void onBootEvent(BootEvent event) {
+    if (EventType.AFTER_CLOSE.equals(event.getEventType())) {
+      server.stop();
+    }
+  }
+
+  protected File createTempFile(String content) throws IOException {
+    return createTempFile(null, content);
+  }
+
+  protected File createTempFile(String name, String content) throws IOException {
+    if (name == null) {
+      name = "download-" + UUID.randomUUID().toString() + ".txt";
+    }
+    File file = new File(tempDir, name);
+    FileUtils.write(file, content);
+    return file;
+  }
+
+  // customize HttpHeaders.CONTENT_DISPOSITION to be "attachment;filename=tempFileEntity.txt"
+  @GetMapping(path = "/tempFileEntity")
+  public ResponseEntity<Part> tempFileEntity(String content) throws IOException {
+    File file = createTempFile(content);
+
+    return ResponseEntity
+        .ok()
+        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=tempFileEntity.txt")
+        .body(new FilePart(null, file)
+            .setDeleteAfterFinished(true));
+  }
+
+  // generate HttpHeaders.CONTENT_DISPOSITION to be "attachment;filename=tempFilePart.txt" automatically
+  @GetMapping(path = "/tempFilePart")
+  public Part tempFilePart(String content) throws IOException {
+    File file = createTempFile(content);
+
+    return new FilePart(null, file)
+        .setDeleteAfterFinished(true)
+        .setSubmittedFileName("tempFilePart.txt");
+  }
+
+  @GetMapping(path = "/file")
+  public File file(String content) throws IOException {
+    return createTempFile("file.txt", content);
+  }
+
+  @GetMapping(path = "/chineseAndSpaceFile")
+  public Part chineseAndSpaceFile(String content) throws IOException {
+    File file = createTempFile(content);
+    return new FilePart(null, file)
+        .setDeleteAfterFinished(true)
+        .setSubmittedFileName("测 试.test.txt");
+  }
+
+  @GetMapping(path = "/resource")
+  @ApiResponses({
+      @ApiResponse(code = 200, response = File.class, message = ""),
+  })
+  public Resource resource(String content) throws IOException {
+    return new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)) {
+      @Override
+      public String getFilename() {
+        return "resource.txt";
+      }
+    };
+  }
+
+  @GetMapping(path = "/entityResource")
+  @ApiResponses({
+      @ApiResponse(code = 200, response = File.class, message = ""),
+  })
+  public ResponseEntity<Resource> entityResource(String content) throws IOException {
+    return ResponseEntity
+        .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=entityResource.txt")
+        .body(new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)));
+  }
+
+  @GetMapping(path = "/entityInputStream")
+  @ApiResponses({
+      @ApiResponse(code = 200, response = File.class, message = ""),
+  })
+  public ResponseEntity<InputStream> entityInputStream(String content) throws IOException {
+    return ResponseEntity
+        .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=entityInputStream.txt")
+        .body(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
+  }
+
+  @GetMapping(path = "/bytes")
+  @ApiResponses({
+      @ApiResponse(code = 200, response = File.class, message = ""),
+  })
+  public ResponseEntity<byte[]> bytes(String content) throws IOException {
+    return ResponseEntity
+        .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=bytes.txt")
+        .body(content.getBytes(StandardCharsets.UTF_8));
+  }
+
+  @GetMapping(path = "/netInputStream")
+  @ApiResponses({
+      @ApiResponse(code = 200, response = File.class, message = ""),
+  })
+  public ResponseEntity<InputStream> netInputStream(String content) throws IOException {
+    URL url = new URL("http://localhost:9000/download/netInputStream?content="
+        + URLEncoder.encode(content, StandardCharsets.UTF_8.name()));
+    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+    return ResponseEntity
+        .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=netInputStream.txt")
+        .body(conn.getInputStream());
+  }
+}
diff --git a/integration-tests/it-producer/src/main/resources/microservice.yaml b/integration-tests/it-producer/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..102722d
--- /dev/null
+++ b/integration-tests/it-producer/src/main/resources/microservice.yaml
@@ -0,0 +1,20 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+service_description:
+  name: it-producer
+
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 078405a..9089eef 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -42,11 +42,25 @@
     <module>spring-pojo-tests</module>
     <module>dynamic-config-tests</module>
     <module>spring-pojo-connection-limit-test</module>
+
+    <module>it-common</module>
+    <module>it-producer</module>
+    <module>it-edge</module>
+    <module>it-common-service</module>
+
+    <!--must be the last one-->
+    <module>it-consumer</module>
   </modules>
 
   <dependencyManagement>
     <dependencies>
       <dependency>
+        <groupId>org.apache.servicecomb.tests</groupId>
+        <artifactId>it-common</artifactId>
+        <version>1.1.0-SNAPSHOT</version>
+      </dependency>
+
+      <dependency>
         <groupId>org.apache.servicecomb.demo</groupId>
         <artifactId>demo-schema</artifactId>
         <version>1.1.0-SNAPSHOT</version>
@@ -123,6 +137,27 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>metrics-core</artifactId>
     </dependency>
+
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-core</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-all</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>foundation-test-scaffolding</artifactId>
+      <scope>compile</scope>
+    </dependency>
   </dependencies>
 
   <profiles>