You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2020/11/13 07:49:20 UTC

[servicecomb-samples] branch master updated: move perf demo from java-chassis to samples (#60)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new d25fda1  move perf demo from java-chassis to samples (#60)
d25fda1 is described below

commit d25fda103212117a36cfd42d4bdd18b3607ae10b
Author: bao liu <bi...@qq.com>
AuthorDate: Fri Nov 13 15:49:13 2020 +0800

    move perf demo from java-chassis to samples (#60)
---
 java-chassis-perfermance/README.md                 |  45 +++++++
 java-chassis-perfermance/pom.xml                   | 136 +++++++++++++++++++++
 .../org/apache/servicecomb/demo/perf/Code.java     |  74 +++++++++++
 .../org/apache/servicecomb/demo/perf/Impl.java     |  81 ++++++++++++
 .../org/apache/servicecomb/demo/perf/Intf.java     |  26 ++++
 .../servicecomb/demo/perf/PerfConfiguration.java   | 133 ++++++++++++++++++++
 .../apache/servicecomb/demo/perf/PerfConsumer.java | 101 +++++++++++++++
 .../org/apache/servicecomb/demo/perf/PerfMain.java |  40 ++++++
 .../servicecomb/demo/perf/RedisClientUtils.java    |  74 +++++++++++
 .../apache/servicecomb/demo/perf/RedisSession.java |  71 +++++++++++
 .../src/main/resources/logback.xml                 |  29 +++++
 .../src/main/resources/microservice.yaml           |  79 ++++++++++++
 12 files changed, 889 insertions(+)

diff --git a/java-chassis-perfermance/README.md b/java-chassis-perfermance/README.md
new file mode 100644
index 0000000..00062ab
--- /dev/null
+++ b/java-chassis-perfermance/README.md
@@ -0,0 +1,45 @@
+suppose jar named perf.jar
+1.copy perf.jar to different directory
+
+2.create microservice.yaml in each directory
+# change microserviceName to be perf1/perf2/perf3, and so on
+service_description:
+  name: perf1
+cse:
+  references:
+    # use which transport to invoke
+    transport: rest
+    
+# sync mode consumer count
+sync-count: 10
+# async mode consumer count
+async-count: 20
+# use sync mode or not
+# sync: /v1/syncQuery/{id}?step={step}&all={all}&fromDB={fromDB}
+# async:/v1/asyncQuery/{id}?step={step}&all={all}&fromDB={fromDB}
+sync: false
+# producer microserviceName
+producer: perf1
+id: 1
+# every producer determine:
+#   1)if step equals all, then this is final step, direct return or query from db
+#   2)otherwise inc step and invoke next microservice
+#   3)if self name if perf1, then next microservice is perf2
+step: 1
+all: 1
+fromDB: false
+response-size: 1
+
+# redis parameter
+redis:
+  client:
+    count: 8
+  host:
+  port:
+  password: 
+  
+3.start producers
+java -jar perf.jar
+
+4.start consumer
+java -jar perf.jar -c
\ No newline at end of file
diff --git a/java-chassis-perfermance/pom.xml b/java-chassis-perfermance/pom.xml
new file mode 100644
index 0000000..c64ff59
--- /dev/null
+++ b/java-chassis-perfermance/pom.xml
@@ -0,0 +1,136 @@
+<?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">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.servicecomb.samples.performance</groupId>
+  <artifactId>performance-application</artifactId>
+  <version>2.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>Java Chassis::Demo::Perf</name>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <servicecomb.version>2.1.2</servicecomb.version>
+    <demo.main>org.apache.servicecomb.demo.perf.PerfMain</demo.main>
+    <vertx.version>3.8.3</vertx.version>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.mybatis</groupId>
+        <artifactId>mybatis</artifactId>
+        <version>3.4.5</version>
+      </dependency>
+      <dependency>
+        <groupId>org.mybatis</groupId>
+        <artifactId>mybatis-spring</artifactId>
+        <version>1.3.0</version>
+      </dependency>
+      <dependency>
+        <groupId>mysql</groupId>
+        <artifactId>mysql-connector-java</artifactId>
+        <version>5.1.46</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.servicecomb</groupId>
+        <artifactId>java-chassis-dependencies</artifactId>
+        <version>${servicecomb.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>registry-service-center</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-pojo</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-springmvc</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-rest-vertx</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-highway</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>inspector</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>io.vertx</groupId>
+      <artifactId>vertx-redis-client</artifactId>
+      <version>${vertx.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>metrics-core</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.1</version>
+          <configuration>
+            <source>1.8</source>
+            <target>1.8</target>
+            <compilerArgument>-parameters</compilerArgument>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-maven-plugin</artifactId>
+          <version>2.1.6.RELEASE</version>
+          <executions>
+            <execution>
+              <goals>
+                <goal>repackage</goal>
+              </goals>
+              <configuration>
+                <mainClass>${main.class}</mainClass>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
\ No newline at end of file
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Code.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Code.java
new file mode 100644
index 0000000..92a93c2
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Code.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.demo.perf;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+
+// git log --author="wujimin" --pretty=tformat:%s --shortstat --since ==2017-9-1
+public class Code {
+  static File file = new File("d:/work/git/incubator-servicecomb-java-chassis/0218.txt");
+
+  public static void main(String[] args) throws IOException {
+    List<String> lines = FileUtils.readLines(file, StandardCharsets.UTF_8);
+
+    int totalAdd = 0;
+    int totalDel = 0;
+    List<String> output = new ArrayList<>();
+    System.out.println(lines.size());
+    for (int idx = 0; idx < lines.size(); ) {
+      String msg = lines.get(idx);
+
+      // skip a empty line
+      idx += 2;
+      // 2 files changed, 2 insertions(+), 2 deletions(-)
+      String line = lines.get(idx);
+      idx++;
+//      System.out.println(idx + ": " + msg);
+
+      int add = 0;
+      int delete = 0;
+      for (String part : line.split(",")) {
+        String key = " insertions(+)";
+        int matchIdx = part.indexOf(key);
+        if (matchIdx > 0) {
+          add = Integer.valueOf(part.substring(0, matchIdx).trim());
+          continue;
+        }
+
+        key = " deletions(-)";
+        matchIdx = part.indexOf(key);
+        if (matchIdx > 0) {
+          delete = Integer.valueOf(part.substring(0, matchIdx).trim());
+          continue;
+        }
+      }
+
+      totalAdd += add;
+      totalDel += delete;
+      output.add(String.format("%d | %d | %s", add, delete, msg));
+    }
+
+    output.add(String.format("summary, add: %d, del: %s", totalAdd, totalDel));
+    System.out.println(String.join("\n", output));
+  }
+}
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Impl.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Impl.java
new file mode 100644
index 0000000..e2505ed
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Impl.java
@@ -0,0 +1,81 @@
+/*
+ * 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.demo.perf;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "impl")
+@RequestMapping(path = "/v1")
+public class Impl {
+  private Intf intf;
+
+  @Value(value = "${service_description.name}")
+  public void setSelfMicroserviceName(String selfMicroserviceName) {
+    // self: perf-1/perf-a
+    // next: perf-2/perf-b
+    char last = selfMicroserviceName.charAt(selfMicroserviceName.length() - 1);
+    String nextMicroserviceName =
+        selfMicroserviceName.substring(0, selfMicroserviceName.length() - 1) + (char) (last + 1);
+    intf = Invoker.createProxy(nextMicroserviceName,
+        "impl",
+        Intf.class);
+  }
+
+  @GetMapping(path = "/syncQuery/{id}")
+  public String syncQuery(@PathVariable(name = "id") String id,
+      @RequestParam(name = "step") int step, @RequestParam(name = "all") int all,
+      @RequestParam(name = "fromDB") boolean fromDB) {
+    if (step == all) {
+      if (fromDB) {
+        return RedisClientUtils.syncQuery(id);
+      }
+
+      return buildFromMemoryResponse(id);
+    }
+
+    return intf.syncQuery(id, step + 1, all, fromDB);
+  }
+
+  public String buildFromMemoryResponse(String id) {
+    return PerfConfiguration.buildResponse("memory", id);
+  }
+
+  @GetMapping(path = "/asyncQuery/{id}")
+  public CompletableFuture<String> asyncQuery(@PathVariable(name = "id") String id,
+      @RequestParam(name = "step") int step, @RequestParam(name = "all") int all,
+      @RequestParam(name = "fromDB") boolean fromDB) {
+    if (step == all) {
+      if (fromDB) {
+        return RedisClientUtils.asyncQuery(id);
+      }
+
+      CompletableFuture<String> future = new CompletableFuture<>();
+      future.complete(buildFromMemoryResponse(id));
+      return future;
+    }
+
+    return intf.asyncQuery(id, step + 1, all, fromDB);
+  }
+}
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Intf.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Intf.java
new file mode 100644
index 0000000..c671fda
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/Intf.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.demo.perf;
+
+import java.util.concurrent.CompletableFuture;
+
+public interface Intf {
+  String syncQuery(String id, int step, int all, boolean fromDB);
+
+  CompletableFuture<String> asyncQuery(String id, int step, int all, boolean fromDB);
+}
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfConfiguration.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfConfiguration.java
new file mode 100644
index 0000000..8d750b0
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfConfiguration.java
@@ -0,0 +1,133 @@
+/*
+ * 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.demo.perf;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import com.google.common.base.Strings;
+
+@Component
+public class PerfConfiguration {
+  public static int syncCount;
+
+  public static int asyncCount;
+
+  public static boolean sync;
+
+  public static String producer;
+
+  public static String id;
+
+  public static int step;
+
+  public static int all;
+
+  public static boolean fromDB;
+
+  public static int responseSize;
+
+  public static String responseData;
+
+  public static int redisClientCount;
+
+  public static String redisHost;
+
+  public static int redisPort;
+
+  public static String redisPassword;
+
+  public static String buildResponse(String from, String id) {
+    return new StringBuilder(64 + PerfConfiguration.responseData.length())
+        .append(id)
+        .append(" from ")
+        .append(from)
+        .append(": ")
+        .append(PerfConfiguration.responseData)
+        .toString();
+  }
+
+  @Value(value = "${response-size}")
+  public void setResponseSize(int responseSize) {
+    PerfConfiguration.responseSize = responseSize;
+    PerfConfiguration.responseData = Strings.repeat("a", responseSize);
+  }
+
+  @Value(value = "${sync-count}")
+  public void setSyncCount(int syncCount) {
+    PerfConfiguration.syncCount = syncCount;
+  }
+
+  @Value(value = "${async-count}")
+  public void setAsyncCount(int asyncCount) {
+    PerfConfiguration.asyncCount = asyncCount;
+  }
+
+  @Value(value = "${sync}")
+  public void setSync(boolean sync) {
+    PerfConfiguration.sync = sync;
+  }
+
+  @Value(value = "${producer}")
+  public void setProducer(String producer) {
+    PerfConfiguration.producer = producer;
+  }
+
+  @Value(value = "${id}")
+  public void setId(String id) {
+    PerfConfiguration.id = id;
+  }
+
+  @Value(value = "${step}")
+  public void setStep(int step) {
+    PerfConfiguration.step = step;
+  }
+
+  @Value(value = "${all}")
+  public void setAll(int all) {
+    PerfConfiguration.all = all;
+  }
+
+  @Value(value = "${fromDB}")
+  public void setFromDB(boolean fromDB) {
+    PerfConfiguration.fromDB = fromDB;
+  }
+
+  @Value(value = "${redis.client.count}")
+  public void setRedisClientCount(int redisClientCount) {
+    PerfConfiguration.redisClientCount = redisClientCount;
+  }
+
+  @Value(value = "${redis.host}")
+  public void setRedisHost(String redisHost) {
+    PerfConfiguration.redisHost = redisHost;
+  }
+
+  @Value(value = "${redis.port}")
+  public void setRedisPort(int redisPort) {
+    PerfConfiguration.redisPort = redisPort;
+  }
+
+  @Value(value = "${redis.password:}")
+  public void setRedisPassword(String redisPassword) {
+    if (StringUtils.isEmpty(redisPassword)) {
+      return;
+    }
+    PerfConfiguration.redisPassword = redisPassword;
+  }
+}
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfConsumer.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfConsumer.java
new file mode 100644
index 0000000..a73b768
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfConsumer.java
@@ -0,0 +1,101 @@
+/*
+ * 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.demo.perf;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PerfConsumer {
+  private static final Logger LOGGER = LoggerFactory.getLogger(PerfConsumer.class);
+
+  private Intf intf;
+
+  public void runConsumer() throws InterruptedException, ExecutionException {
+    intf = Invoker.createProxy(
+        PerfConfiguration.producer,
+        "impl",
+        Intf.class);
+
+    if (PerfConfiguration.sync) {
+      runSyncConsumers();
+      return;
+    }
+
+    runAsyncConsumers();
+  }
+
+  private void runAsyncConsumers() throws InterruptedException, ExecutionException {
+    CompletableFuture<String> future = intf.asyncQuery(PerfConfiguration.id,
+        PerfConfiguration.step,
+        PerfConfiguration.all,
+        PerfConfiguration.fromDB);
+    LOGGER.info("runAsyncConsumer: {}", future.get());
+
+    for (int idx = 0; idx < PerfConfiguration.asyncCount; idx++) {
+      runAsyncConsumer();
+    }
+  }
+
+  private void runAsyncConsumer() {
+    CompletableFuture<String> future = intf.asyncQuery(PerfConfiguration.id,
+        PerfConfiguration.step,
+        PerfConfiguration.all,
+        PerfConfiguration.fromDB);
+    future.whenComplete((r, e) -> {
+      if (e == null) {
+        runAsyncConsumer();
+        return;
+      }
+
+      throw new IllegalStateException("invoke failed.", e);
+    });
+  }
+
+  private void runSyncConsumers() {
+    LOGGER.info("runSyncConsumer: {}",
+        intf.syncQuery(PerfConfiguration.id,
+            PerfConfiguration.step,
+            PerfConfiguration.all,
+            PerfConfiguration.fromDB));
+
+    Executor executor = Executors.newFixedThreadPool(PerfConfiguration.syncCount);
+    for (int idx = 0; idx < PerfConfiguration.syncCount; idx++) {
+      executor.execute(this::runSyncConsumer);
+    }
+  }
+
+  private void runSyncConsumer() {
+    try {
+      for (; ; ) {
+        intf.syncQuery(PerfConfiguration.id,
+            PerfConfiguration.step,
+            PerfConfiguration.all,
+            PerfConfiguration.fromDB);
+      }
+    } catch (Throwable e) {
+      throw new IllegalStateException("invoke failed.", e);
+    }
+  }
+}
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfMain.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfMain.java
new file mode 100644
index 0000000..871ccb4
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/PerfMain.java
@@ -0,0 +1,40 @@
+/*
+ * 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.demo.perf;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.vertx.VertxUtils;
+
+public class PerfMain {
+
+  public static void main(String[] args) throws Exception {
+    BeanUtils.init();
+
+    // redis
+    RedisClientUtils.init(VertxUtils.getOrCreateVertxByName("transport", null));
+
+    List<String> argList = Arrays.asList(args);
+    if (argList.contains("-c")) {
+      PerfConsumer consumer = BeanUtils.getContext().getBean(PerfConsumer.class);
+      consumer.runConsumer();
+    }
+  }
+}
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/RedisClientUtils.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/RedisClientUtils.java
new file mode 100644
index 0000000..0ce693a
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/RedisClientUtils.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.demo.perf;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.servicecomb.foundation.vertx.VertxUtils;
+import org.apache.servicecomb.foundation.vertx.client.ClientPoolFactory;
+import org.apache.servicecomb.foundation.vertx.client.ClientPoolManager;
+import org.apache.servicecomb.foundation.vertx.client.ClientVerticle;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+
+import io.vertx.core.DeploymentOptions;
+import io.vertx.core.Vertx;
+import io.vertx.redis.RedisClient;
+import io.vertx.redis.RedisOptions;
+
+public class RedisClientUtils {
+  private static ClientPoolManager<RedisClient> clientMgr;
+
+  public static void init(Vertx vertx) throws InterruptedException {
+    RedisOptions redisOptions = new RedisOptions()
+        .setHost(PerfConfiguration.redisHost)
+        .setPort(PerfConfiguration.redisPort)
+        .setAuth(PerfConfiguration.redisPassword);
+    ClientPoolFactory<RedisClient> factory = (ctx) -> {
+      return RedisClient.create(vertx, redisOptions);
+    };
+    clientMgr = new ClientPoolManager<>(vertx, factory);
+
+    DeploymentOptions deployOptions = VertxUtils.createClientDeployOptions(clientMgr,
+        PerfConfiguration.redisClientCount);
+    VertxUtils.blockDeploy(vertx, ClientVerticle.class, deployOptions);
+  }
+
+  public static String syncQuery(String id) {
+    CompletableFuture<String> future = doQuery(id, true);
+    try {
+      return future.get();
+    } catch (InterruptedException | ExecutionException e) {
+      throw new InvocationException(Status.INTERNAL_SERVER_ERROR.getStatusCode(),
+          Status.INTERNAL_SERVER_ERROR.getReasonPhrase(), (Object) "Failed to query from redis.", e);
+    }
+  }
+
+  public static CompletableFuture<String> asyncQuery(String id) {
+    return doQuery(id, false);
+  }
+
+  private static CompletableFuture<String> doQuery(String id, boolean sync) {
+    CompletableFuture<String> future = new CompletableFuture<>();
+    RedisClient redisClient = clientMgr.findClientPool(sync);
+    RedisSession session = new RedisSession(redisClient, id, future);
+    session.query();
+    return future;
+  }
+}
diff --git a/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/RedisSession.java b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/RedisSession.java
new file mode 100644
index 0000000..f9d657f
--- /dev/null
+++ b/java-chassis-perfermance/src/main/java/org/apache/servicecomb/demo/perf/RedisSession.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.demo.perf;
+
+import java.util.concurrent.CompletableFuture;
+
+import io.vertx.core.AsyncResult;
+import io.vertx.redis.RedisClient;
+
+public class RedisSession {
+  RedisClient redis;
+
+  String id;
+
+  CompletableFuture<String> future;
+
+  String createResult;
+
+  public RedisSession(RedisClient redis, String id, CompletableFuture<String> future) {
+    this.redis = redis;
+    this.id = id;
+    this.future = future;
+  }
+
+  public void query() {
+    redis.get(id, this::onGetResponse);
+  }
+
+  private void onGetResponse(AsyncResult<String> ar) {
+    if (ar.succeeded()) {
+      if (ar.result() == null) {
+        createCache();
+        return;
+      }
+
+      future.complete(ar.result());
+      return;
+    }
+
+    future.completeExceptionally(ar.cause());
+  }
+
+  private void createCache() {
+    createResult = PerfConfiguration.buildResponse("redis", id);
+    redis.set(id, createResult, this::onCreateCacheResponse);
+  }
+
+  private void onCreateCacheResponse(AsyncResult<Void> ar) {
+    if (ar.succeeded()) {
+      future.complete(createResult);
+      return;
+    }
+
+    future.completeExceptionally(ar.cause());
+  }
+}
diff --git a/java-chassis-perfermance/src/main/resources/logback.xml b/java-chassis-perfermance/src/main/resources/logback.xml
new file mode 100644
index 0000000..5264742
--- /dev/null
+++ b/java-chassis-perfermance/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][%marker] - %msg (%F:%L\)%n</pattern>
+    </encoder>
+  </appender>
+  <root level="INFO">
+    <appender-ref ref="STDOUT"/>
+  </root>
+</configuration>
\ No newline at end of file
diff --git a/java-chassis-perfermance/src/main/resources/microservice.yaml b/java-chassis-perfermance/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..4a26c08
--- /dev/null
+++ b/java-chassis-perfermance/src/main/resources/microservice.yaml
@@ -0,0 +1,79 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+APPLICATION_ID: perfTest
+service_description:
+  name: perf1
+  version: 0.0.1
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  rest:
+    address: 0.0.0.0:8080?sslEnabled=false
+    server:
+      verticle-count: 8
+    client:
+      verticle-count: 8
+      connection:
+        maxPoolSize: 30
+  highway:
+    address: 0.0.0.0:7070?sslEnabled=false
+    server:
+      verticle-count: 8
+    client:
+      verticle-count: 8
+  executor:
+    default:
+      group: 4
+      maxThreads-per-group: 4
+  references:
+    transport: highway
+    transport: rest
+  metrics:
+    endpoint:
+      enabled: false
+    window_time: 1000
+    invocation.latencyDistribution: 0,1,3,10,100
+    Consumer.invocation.slow:
+      enabled: true
+      msTime: 40
+    Provider.invocation.slow:
+      enabled: true
+      msTime: 1
+    publisher.defaultLog:
+      enabled: true
+      endpoints.client.detail.enabled: true
+      invocation.latencyDistribution:
+        minScopeLength: 9
+
+sync-count: 10
+async-count: 10
+sync: false
+producer: perf1
+id: 1
+step: 1
+all: 1
+fromDB: false
+response-size: 1
+
+redis:
+  client:
+    count: 8
+  host: localhost
+  port: 6379
+#  password: