You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ma...@apache.org on 2019/08/07 03:19:02 UTC

[servicecomb-samples] 02/32: add porter demo

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

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

commit 4bfdb295453193dc5bc82bb11365614a1a10b8df
Author: liubao <ba...@huawei.com>
AuthorDate: Wed Mar 6 22:47:42 2019 +0800

    add porter demo
---
 .gitignore                                         |  85 +++++++++++
 README.md                                          |   2 +
 porter_lightweight/README.md                       |  82 ++++++++++
 porter_lightweight/common/pom.xml                  |  31 ++++
 .../java/samples/porter/file/api/FileEndpoint.java |  51 +++++++
 .../java/samples/porter/file/api/FileService.java  |  26 ++++
 .../java/samples/porter/user/api/SessionInfo.java  |  50 +++++++
 .../java/samples/porter/user/api/UserEndpoint.java |  49 ++++++
 .../java/samples/porter/user/api/UserService.java  |  27 ++++
 .../common/src/main/resources/microservice.yaml    |  30 ++++
 porter_lightweight/file-service/pom.xml            |  49 ++++++
 .../servicecomb/samples/porter/file/FileMain.java  |  28 ++++
 .../porter/file/service/FileServiceImpl.java       |  53 +++++++
 .../porter/file/service/FileStoreService.java      |  31 ++++
 .../porter/file/service/LocalFileStoreService.java |  64 ++++++++
 .../samples/porter/file/service/SessionInfo.java   |  81 ++++++++++
 .../main/resources/META-INF/spring/file.bean.xml   |  29 ++++
 .../src/main/resources/microservice.yaml           |  30 ++++
 porter_lightweight/gateway-service/pom.xml         |  58 ++++++++
 .../samples/porter/gateway/ApiDispatcher.java      |  68 +++++++++
 .../samples/porter/gateway/AuthHandler.java        | 105 +++++++++++++
 .../samples/porter/gateway/EdgeSSLCustom.java      |  38 +++++
 .../samples/porter/gateway/GatewayMain.java        |  28 ++++
 .../porter/gateway/StaticWebpageDispatcher.java    |  52 +++++++
 ...cecomb.transport.rest.vertx.VertxHttpDispatcher |  19 +++
 .../src/main/resources/config/cse.handler.xml      |  21 +++
 .../src/main/resources/microservice.yaml           |  45 ++++++
 .../src/main/resources/ui/css/style.css            |  49 ++++++
 .../src/main/resources/ui/js/jquery-1.11.1.min.js  |   4 +
 .../src/main/resources/ui/js/login.js              |  52 +++++++
 .../src/main/resources/ui/js/upload.js             |  63 ++++++++
 .../src/main/resources/ui/login.html               |  45 ++++++
 .../src/main/resources/ui/upload.html              |  61 ++++++++
 porter_lightweight/pom.xml                         | 165 +++++++++++++++++++++
 porter_lightweight/user-service/.gitignore         |   1 +
 porter_lightweight/user-service/pom.xml            |  85 +++++++++++
 .../servicecomb/samples/porter/user/UserMain.java  |  28 ++++
 .../samples/porter/user/dao/SessionInfoModel.java  |  90 +++++++++++
 .../samples/porter/user/dao/SessionMapper.java     |  28 ++++
 .../samples/porter/user/dao/UserInfo.java          |  61 ++++++++
 .../samples/porter/user/dao/UserMapper.java        |  24 +++
 .../porter/user/service/UserServiceImpl.java       | 114 ++++++++++++++
 .../main/resources/META-INF/spring/user.bean.xml   |  57 +++++++
 .../src/main/resources/config/SessionMapper.xml    |  57 +++++++
 .../src/main/resources/config/UserMapper.xml       |  46 ++++++
 .../src/main/resources/config/create_db_user.sql   |  46 ++++++
 .../src/main/resources/config/mybatis-config.xml   |  27 ++++
 .../src/main/resources/microservice.yaml           |  27 ++++
 48 files changed, 2362 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..67e5a7d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,85 @@
+# Output Directory
+target/
+
+# C pre-compile
+*.gch
+*.pch
+
+# C compile
+*.a
+*.o
+*.ko
+*.la
+*.lo
+*.obj
+*.elf
+*.so
+*.so.*
+*.dylib
+*.exe
+*.lib
+*.dll
+*.out
+*.app
+*.hex
+
+# Debug files
+*.dSYM/
+
+# Java
+*.class
+
+# Java Package Files
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+# Zip Files
+*.rar
+*.zip
+*.7z
+*.tar
+*.gz
+
+# Ant
+build/
+
+# Compiled Python
+__pycache__/
+*.py[cod]
+*py.class
+
+# Eclipse
+.settings/
+.classpath
+.project
+
+# IntelliJ, based on http://devnet.jetbrains.net/docs/DOC-1186
+.idea/
+*.iml
+*.ipr
+*.iws
+
+# logs and trace
+*.log
+*.trace
+*.dat
+
+# vi swap
+*.swp
+
+# Backup Files
+*.bak
+*.old
+
+# SVN metadata
+.svn/
+
+# Mac
+.DS_Store
+
+# gradle
+.gradle
diff --git a/README.md b/README.md
index 3cf272a..ac5abc5 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,4 @@
 # servicecomb samples
 
+## porter_lightweight
+A sample shows an application with basic login, download file, delete file functions. 
diff --git a/porter_lightweight/README.md b/porter_lightweight/README.md
new file mode 100644
index 0000000..ef8c671
--- /dev/null
+++ b/porter_lightweight/README.md
@@ -0,0 +1,82 @@
+This project shows how to using java-chassis and service-center to create a simple microservice application. It shows basic authentication and authorization, uploading files and delte files operations.
+
+## build and run
+
+* compile
+
+```
+mvn clean install
+```
+
+* run
+  * create a database using mysql with user name and password(e.g. root/root)
+  * execute create_db_user.sql
+
+* run user-service:
+
+```
+java $JAVA_OPT -Ddb.url="jdbc:mysql://localhost/porter_user_db?useSSL=false" -Ddb.username=root -Ddb.password=root -jar porter-user-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* run file-service:
+
+```
+java $JAVA_OPT -jar porter-file-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* run gateway-serivce:
+
+gateway-service contains static webpages in resources/ui. First copy to web root folder,e.g webapp, which is relative to working directory. 
+
+```
+java $JAVA_OPT -Dgateway.webroot=webapp -jar porter-gateway-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+## Try it
+
+1. Using browser: http://localhost:9090/ui/login.html with user admin or guest to login, password is test.
+2. Choose a file to upload. Uploaded file is stored in file-service workding directory. And name is random number generated. 
+3. Delete file. Input the random number generated in step 2. 
+
+
+这个项目帮助开发者学习如何使用ServiceComb开发完整的微服务。 这个项目实现的功能非常简单,用户登录后,上传一个文件和删除一个文件,验证了没有权限的用户无法删除文件。
+
+# 编译和运行
+
+* 编译
+
+```
+mvn clean install
+```
+
+* 运行
+  * 安装mysql数据库,设置用户名密码(假设为root/root)
+  * 执行脚本create_db_user.sql
+
+
+* 启动user-service:
+
+```
+java $JAVA_OPT -Ddb.url="jdbc:mysql://localhost/porter_user_db?useSSL=false" -Ddb.username=root -Ddb.password=root -jar porter-user-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* 启动file-service:
+
+```
+java $JAVA_OPT -jar porter-file-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* 启动gateway-serivce:
+
+gateway-service包含了静态页面文件,在resources/ui目录。首先需要将页面文件拷贝到WEB主目录(相对路径,当前运行目录),比如: webapp,然后将ui目录整体拷贝到webapp/ui目录。启动:
+```
+java $JAVA_OPT -Dgateway.webroot=webapp -jar porter-gateway-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+# 使用
+
+1. 输入: http://localhost:9090/ui/login.html 使用admin或者guest登陆,密码为test。
+2. 选择一个文件上传,上传成功,上传成功后的文件会保存在file-service的当前目录, 文件名称是一个随机的数字,这个数字就是文件ID。
+3. 删除文件:输入上一步的文件ID,点击删除。 如果是admin用户,上传成功;如果是guest用户,上传失败。
+
+
diff --git a/porter_lightweight/common/pom.xml b/porter_lightweight/common/pom.xml
new file mode 100644
index 0000000..772ec4e
--- /dev/null
+++ b/porter_lightweight/common/pom.xml
@@ -0,0 +1,31 @@
+<?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>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-common</artifactId>
+  <packaging>jar</packaging>
+
+</project>
diff --git a/porter_lightweight/common/src/main/java/samples/porter/file/api/FileEndpoint.java b/porter_lightweight/common/src/main/java/samples/porter/file/api/FileEndpoint.java
new file mode 100644
index 0000000..e7c1f0c
--- /dev/null
+++ b/porter_lightweight/common/src/main/java/samples/porter/file/api/FileEndpoint.java
@@ -0,0 +1,51 @@
+/*
+ * 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 samples.porter.file.api;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+
+@RestSchema(schemaId = "file")
+@RequestMapping(path = "/")
+public class FileEndpoint {
+  @Autowired
+  private FileService fileService;
+  
+  /**
+   * upload and return file id
+   */
+  @PostMapping(path = "/upload", produces = MediaType.TEXT_PLAIN_VALUE)
+  public String uploadFile(@RequestPart(name = "fileName") MultipartFile file) {
+      return fileService.uploadFile(file);
+  }
+
+  /**
+   * delete file by id
+   */
+  @DeleteMapping(path = "/delete", produces = MediaType.APPLICATION_JSON_VALUE)
+  public boolean deleteFile(@RequestParam(name = "id") String id) {
+      return fileService.deleteFile(id);
+  }
+}
diff --git a/porter_lightweight/common/src/main/java/samples/porter/file/api/FileService.java b/porter_lightweight/common/src/main/java/samples/porter/file/api/FileService.java
new file mode 100644
index 0000000..606e727
--- /dev/null
+++ b/porter_lightweight/common/src/main/java/samples/porter/file/api/FileService.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 samples.porter.file.api;
+
+import org.springframework.web.multipart.MultipartFile;
+
+public interface FileService {
+  public String uploadFile(MultipartFile file);
+
+  public boolean deleteFile(String id);
+}
diff --git a/porter_lightweight/common/src/main/java/samples/porter/user/api/SessionInfo.java b/porter_lightweight/common/src/main/java/samples/porter/user/api/SessionInfo.java
new file mode 100644
index 0000000..2aca62b
--- /dev/null
+++ b/porter_lightweight/common/src/main/java/samples/porter/user/api/SessionInfo.java
@@ -0,0 +1,50 @@
+/*
+ * 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 samples.porter.user.api;
+
+public class SessionInfo {
+  private String sessiondId;
+
+  private String userName;
+
+  private String roleName;
+
+  public String getSessiondId() {
+    return sessiondId;
+  }
+
+  public void setSessiondId(String sessiondId) {
+    this.sessiondId = sessiondId;
+  }
+
+  public String getUserName() {
+    return userName;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public String getRoleName() {
+    return roleName;
+  }
+
+  public void setRoleName(String roleName) {
+    this.roleName = roleName;
+  }
+}
diff --git a/porter_lightweight/common/src/main/java/samples/porter/user/api/UserEndpoint.java b/porter_lightweight/common/src/main/java/samples/porter/user/api/UserEndpoint.java
new file mode 100644
index 0000000..8a248d3
--- /dev/null
+++ b/porter_lightweight/common/src/main/java/samples/porter/user/api/UserEndpoint.java
@@ -0,0 +1,49 @@
+/*
+ * 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 samples.porter.user.api;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "user")
+@RequestMapping(path = "/")
+public class UserEndpoint {
+  @Autowired
+  private UserService userService;
+
+  @PostMapping(path = "/v1/user/login", produces = MediaType.APPLICATION_JSON_VALUE)
+  public SessionInfo login(@RequestParam(name = "userName") String userName,
+      @RequestParam(name = "password") String password) {
+    return userService.login(userName, password);
+  }
+
+  @GetMapping(path = "/v1/user/session", produces = MediaType.APPLICATION_JSON_VALUE)
+  public SessionInfo getSession(@RequestParam(name = "sessionId") String sessionId) {
+    return userService.getSession(sessionId);
+  }
+
+  @GetMapping(path = "/v1/user/ping", produces = MediaType.APPLICATION_JSON_VALUE)
+  public String ping(@RequestParam(name = "message") String message) {
+    return userService.ping(message);
+  }
+}
diff --git a/porter_lightweight/common/src/main/java/samples/porter/user/api/UserService.java b/porter_lightweight/common/src/main/java/samples/porter/user/api/UserService.java
new file mode 100644
index 0000000..a37ffa3
--- /dev/null
+++ b/porter_lightweight/common/src/main/java/samples/porter/user/api/UserService.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 samples.porter.user.api;
+
+public interface UserService {
+  public SessionInfo login(String userName,
+      String password);
+
+  public SessionInfo getSession(String sessionId);
+
+  public String ping(String message);
+}
diff --git a/porter_lightweight/common/src/main/resources/microservice.yaml b/porter_lightweight/common/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..9e3de6e
--- /dev/null
+++ b/porter_lightweight/common/src/main/resources/microservice.yaml
@@ -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.
+## ---------------------------------------------------------------------------
+
+servicecomb-config-order: 10
+
+APPLICATION_ID: porter-application
+service_description:
+  version: 0.0.1
+
+servicecomb:
+  service:
+    registry:
+      address: http://localhost:30100
+      instance:
+        watch: false
\ No newline at end of file
diff --git a/porter_lightweight/file-service/pom.xml b/porter_lightweight/file-service/pom.xml
new file mode 100644
index 0000000..d42ed5c
--- /dev/null
+++ b/porter_lightweight/file-service/pom.xml
@@ -0,0 +1,49 @@
+<!--
+  ~ 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>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-file-service</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>porter-common</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+  <properties>
+    <main.class>org.apache.servicecomb.samples.porter.file.FileMain</main.class>
+  </properties>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/FileMain.java b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/FileMain.java
new file mode 100644
index 0000000..9b13142
--- /dev/null
+++ b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/FileMain.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.samples.porter.file;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+
+public class FileMain {
+    public static void main(String[] args) throws Exception {
+        Log4jUtils.init();
+        BeanUtils.init();
+    }
+}
diff --git a/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileServiceImpl.java b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileServiceImpl.java
new file mode 100644
index 0000000..78aea60
--- /dev/null
+++ b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileServiceImpl.java
@@ -0,0 +1,53 @@
+/*
+ * 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.samples.porter.file.service;
+
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service
+public class FileServiceImpl implements samples.porter.file.api.FileService {
+    @Autowired
+    private FileStoreService fileService;
+
+    public String uploadFile(MultipartFile file) {
+        return fileService.uploadFile(file);
+    }
+
+    public boolean deleteFile(String id) {
+        String session = ContextUtils.getInvocationContext().getContext("session-info");
+        if (session == null) {
+            throw new InvocationException(403, "", "not allowed");
+        } else {
+            SessionInfo sessionInfo = null;
+            try {
+                sessionInfo = JsonUtils.readValue(session.getBytes("UTF-8"), SessionInfo.class);
+            } catch (Exception e) {
+                throw new InvocationException(403, "", "session not allowed");
+            }
+            if (sessionInfo == null || !sessionInfo.getRoleName().equals("admin")) {
+                throw new InvocationException(403, "", "not allowed");
+            }
+        }
+        return fileService.deleteFile(id);
+    }
+}
diff --git a/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileStoreService.java b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileStoreService.java
new file mode 100644
index 0000000..f9ff5c9
--- /dev/null
+++ b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileStoreService.java
@@ -0,0 +1,31 @@
+/*
+ * 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.samples.porter.file.service;
+
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * file storage service, can implement using file system, OBS, etc.
+ */
+public interface FileStoreService {
+
+    public String uploadFile(MultipartFile file);
+
+    public boolean deleteFile(String id);
+
+}
diff --git a/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/LocalFileStoreService.java b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/LocalFileStoreService.java
new file mode 100644
index 0000000..adb8b19
--- /dev/null
+++ b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/LocalFileStoreService.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.samples.porter.file.service;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.UUID;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ *  Simple file storage implementation.
+ *  Caution: file check and other security constraints not implemented. 
+ */
+@Component
+public class LocalFileStoreService implements FileStoreService {
+    // maxmum BUFFER_SIZE * BUFFER_NUM
+    private static final int BUFFER_SIZE = 10240;
+
+    private static final File BASE_FILE = new File(".");
+
+    @Override
+    public String uploadFile(MultipartFile file) {
+        byte[] buffer = new byte[BUFFER_SIZE];
+        String fileId = UUID.randomUUID().toString();
+
+        File outFile = new File(BASE_FILE, fileId);
+        int len;
+        try (InputStream is = file.getInputStream(); OutputStream os = new FileOutputStream(outFile)) {
+            while ((len = is.read(buffer)) != -1) {
+                os.write(buffer, 0, len);
+            }
+        } catch (IOException e) {
+            return null;
+        }
+        return fileId;
+    }
+
+    @Override
+    public boolean deleteFile(String id) {
+        File outFile = new File(BASE_FILE, id);
+        return outFile.delete();
+    }
+
+}
diff --git a/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/SessionInfo.java b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/SessionInfo.java
new file mode 100644
index 0000000..eeff226
--- /dev/null
+++ b/porter_lightweight/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/SessionInfo.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.samples.porter.file.service;
+
+public class SessionInfo {
+    private int id;
+
+    private String sessiondId;
+
+    private String userName;
+
+    private String roleName;
+
+    private java.sql.Timestamp creationTime;
+
+    private java.sql.Timestamp activeTime;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getSessiondId() {
+        return sessiondId;
+    }
+
+    public void setSessiondId(String sessiondId) {
+        this.sessiondId = sessiondId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public java.sql.Timestamp getCreationTime() {
+        return creationTime;
+    }
+
+    public void setCreationTime(java.sql.Timestamp creationTime) {
+        this.creationTime = creationTime;
+    }
+
+    public java.sql.Timestamp getActiveTime() {
+        return activeTime;
+    }
+
+    public void setActiveTime(java.sql.Timestamp activeTime) {
+        this.activeTime = activeTime;
+    }
+
+}
diff --git a/porter_lightweight/file-service/src/main/resources/META-INF/spring/file.bean.xml b/porter_lightweight/file-service/src/main/resources/META-INF/spring/file.bean.xml
new file mode 100644
index 0000000..4a3846c
--- /dev/null
+++ b/porter_lightweight/file-service/src/main/resources/META-INF/spring/file.bean.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.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+    xmlns:util="http://www.springframework.org/schema/util"
+    xmlns:context="http://www.springframework.org/schema/context"
+    xsi:schemaLocation="
+        http://www.springframework.org/schema/beans classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd
+        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <!-- Only scan file components. Other beans in common module like org.apache.servicecomb.samples.porter.user.api.UserEndpoint ignored. -->
+    <context:component-scan base-package="samples.porter.file" />
+</beans>
\ No newline at end of file
diff --git a/porter_lightweight/file-service/src/main/resources/microservice.yaml b/porter_lightweight/file-service/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..bb71959
--- /dev/null
+++ b/porter_lightweight/file-service/src/main/resources/microservice.yaml
@@ -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.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+service_description:
+  name: file-service
+
+servicecomb:
+  rest:
+    address: 0.0.0.0:9091
+
+  uploads:
+    directory: tmp_for_upload_file
\ No newline at end of file
diff --git a/porter_lightweight/gateway-service/pom.xml b/porter_lightweight/gateway-service/pom.xml
new file mode 100644
index 0000000..427c75e
--- /dev/null
+++ b/porter_lightweight/gateway-service/pom.xml
@@ -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.
+  -->
+
+<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>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-gateway-service</artifactId>
+  <packaging>jar</packaging>
+
+  <properties>
+    <main.class>org.apache.servicecomb.samples.porter.gateway.GatewayMain</main.class>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>porter-common</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>edge-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>metrics-core</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java
new file mode 100644
index 0000000..c80f42a
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.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.samples.porter.gateway;
+
+import java.util.Map;
+
+import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher;
+import org.apache.servicecomb.edge.core.EdgeInvocation;
+
+import io.vertx.ext.web.Cookie;
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.CookieHandler;
+
+public class ApiDispatcher extends AbstractEdgeDispatcher {
+  @Override
+  public int getOrder() {
+    return 10002;
+  }
+
+  @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 path = "/" + pathParams.get("param1");
+
+    EdgeInvocation invoker = new EdgeInvocation() {
+      // 认证鉴权:构造Invocation的时候,设置会话信息。如果是认证请求,则添加Cookie。
+      protected void createInvocation() {
+        super.createInvocation();
+        // 既从cookie里面读取会话ID,也从header里面读取,方便各种独立的测试工具联调
+        String sessionId = context.request().getHeader("session-id");
+        if (sessionId != null) {
+          this.invocation.addContext("session-id", sessionId);
+        } else {
+          Cookie sessionCookie = context.getCookie("session-id");
+          if (sessionCookie != null) {
+            this.invocation.addContext("session-id", sessionCookie.getValue());
+          }
+        }
+      }
+    };
+    invoker.init(microserviceName, context, path, httpServerFilters);
+    invoker.edgeInvoke();
+  }
+}
diff --git a/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java
new file mode 100644
index 0000000..73cc06d
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java
@@ -0,0 +1,105 @@
+/*
+ * 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.samples.porter.gateway;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.core.Handler;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.provider.springmvc.reference.async.CseAsyncRestTemplate;
+import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.concurrent.ListenableFuture;
+import org.springframework.util.concurrent.ListenableFutureCallback;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+import samples.porter.user.api.SessionInfo;
+
+
+public class AuthHandler implements Handler {
+  private CseAsyncRestTemplate restTemplate = new CseAsyncRestTemplate();
+
+  //服务端会话过期是10分钟,客户端缓存1分钟会话。
+  private Cache<String, String> sessionCache = CacheBuilder.newBuilder()
+      .expireAfterAccess(30, TimeUnit.SECONDS)
+      .build();
+
+  @Override
+  public void handle(Invocation invocation, AsyncResponse asyncResponse) throws Exception {
+    if (invocation.getMicroserviceName().equals("user-service")
+        && (invocation.getOperationName().equals("login")
+            || (invocation.getOperationName().equals("getSession")))) {
+      // login: 直接返回认证结果。  开发者需要在JS里面设置cookie。 
+      invocation.next(asyncResponse);
+    } else {
+      // check session
+      String sessionId = invocation.getContext("session-id");
+      if (sessionId == null) {
+        throw new InvocationException(403, "", "session is not valid.");
+      }
+
+      String sessionInfo = sessionCache.getIfPresent(sessionId);
+      if (sessionInfo != null) {
+        try {
+          // 将会话信息传递给后面的微服务。后面的微服务可以从context获取到会话信息,从而可以进行鉴权等。 
+          invocation.addContext("session-id", sessionId);
+          invocation.addContext("session-info", sessionInfo);
+          invocation.next(asyncResponse);
+        } catch (Exception e) {
+          asyncResponse.complete(Response.failResp(new InvocationException(500, "", e.getMessage())));
+        }
+        return;
+      }
+
+      // 在网关执行的Hanlder逻辑,是reactive模式的,不能使用阻塞调用。
+      ListenableFuture<ResponseEntity<SessionInfo>> sessionInfoFuture =
+          restTemplate.getForEntity("cse://user-service/v1/user/session?sessionId=" + sessionId, SessionInfo.class);
+      sessionInfoFuture.addCallback(
+          new ListenableFutureCallback<ResponseEntity<SessionInfo>>() {
+            @Override
+            public void onFailure(Throwable ex) {
+              asyncResponse.complete(Response.failResp(new InvocationException(403, "", "session is not valid.")));
+            }
+
+            @Override
+            public void onSuccess(ResponseEntity<SessionInfo> result) {
+              SessionInfo sessionInfo = result.getBody();
+              if (sessionInfo == null) {
+                asyncResponse.complete(Response.failResp(new InvocationException(403, "", "session is not valid.")));
+                return;
+              }
+              try {
+                // 将会话信息传递给后面的微服务。后面的微服务可以从context获取到会话信息,从而可以进行鉴权等。 
+                invocation.addContext("session-id", sessionId);
+                String sessionInfoStr = JsonUtils.writeValueAsString(sessionInfo);
+                invocation.addContext("session-info", sessionInfoStr);
+                invocation.next(asyncResponse);
+                sessionCache.put(sessionId, sessionInfoStr);
+              } catch (Exception e) {
+                asyncResponse.complete(Response.failResp(new InvocationException(500, "", e.getMessage())));
+              }
+            }
+          });
+    }
+  }
+}
diff --git a/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java
new file mode 100644
index 0000000..159c10d
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java
@@ -0,0 +1,38 @@
+/*
+ * 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.samples.porter.gateway;
+
+import java.io.File;
+
+import org.apache.servicecomb.foundation.ssl.SSLCustom;
+
+public class EdgeSSLCustom extends SSLCustom {
+
+    @Override
+    public char[] decode(char[] plain) {
+        return plain;
+    }
+
+    @Override
+    public String getFullPath(String name) {
+        String fullName = System.getProperty("user.dir") + File.separator + name;
+        System.out.println(fullName);
+        return (new File(fullName)).getAbsolutePath();
+    }
+
+}
diff --git a/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java
new file mode 100644
index 0000000..48c1824
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.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.samples.porter.gateway;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+
+public class GatewayMain {
+    public static void main(String[] args) throws Exception {
+        Log4jUtils.init();
+        BeanUtils.init();
+    }
+}
diff --git a/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java
new file mode 100644
index 0000000..791c512
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.config.DynamicPropertyFactory;
+
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.handler.StaticHandler;
+
+public class StaticWebpageDispatcher implements VertxHttpDispatcher {
+  private static final Logger LOGGER = LoggerFactory.getLogger(StaticWebpageDispatcher.class);
+
+  private static final String WEB_ROOT = DynamicPropertyFactory.getInstance()
+      .getStringProperty("gateway.webroot", "/var/static")
+      .get();
+
+  @Override
+  public int getOrder() {
+    return Integer.MAX_VALUE;
+  }
+
+  @Override
+  public void init(Router router) {
+    String regex = "/ui/(.*)";
+    StaticHandler webpageHandler = StaticHandler.create();
+    webpageHandler.setWebRoot(WEB_ROOT);
+    LOGGER.info("server static web page for WEB_ROOT={}", WEB_ROOT);
+    router.routeWithRegex(regex).failureHandler((context) -> {
+      LOGGER.error("", context.failure());
+    }).handler(webpageHandler);
+  }
+
+}
diff --git a/porter_lightweight/gateway-service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/porter_lightweight/gateway-service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
new file mode 100644
index 0000000..71009db
--- /dev/null
+++ b/porter_lightweight/gateway-service/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.samples.porter.gateway.ApiDispatcher
+org.apache.servicecomb.samples.porter.gateway.StaticWebpageDispatcher
\ No newline at end of file
diff --git a/porter_lightweight/gateway-service/src/main/resources/config/cse.handler.xml b/porter_lightweight/gateway-service/src/main/resources/config/cse.handler.xml
new file mode 100644
index 0000000..00295f8
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/config/cse.handler.xml
@@ -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.
+  -->
+
+<config>
+	<handler id="auth"
+			 class="org.apache.servicecomb.samples.porter.gateway.AuthHandler" />
+</config>
diff --git a/porter_lightweight/gateway-service/src/main/resources/microservice.yaml b/porter_lightweight/gateway-service/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..5623c60
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/microservice.yaml
@@ -0,0 +1,45 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 100
+
+service_description:
+  name: gateway-service
+
+servicecomb:
+  rest:
+    address: 0.0.0.0:9090?sslEnabled=false
+
+  handler:
+    chain:
+      Consumer:
+        default: auth,qps-flowcontrol-consumer,loadbalance
+
+  uploads:
+    directory: tmp_for_upload_gateway
+
+  accesslog:
+    enabled: true
+  metrics:
+    window_time: 30000
+    publisher.defaultLog.enabled: true
+
+servicecomb.http.dispatcher.edge.default.enabled: false
+servicecomb.http.dispatcher.rest.enabled: false
+gateway.webroot: /code/servicecomb-samples/porter_lightweight/gateway-service/src/main/resources
diff --git a/porter_lightweight/gateway-service/src/main/resources/ui/css/style.css b/porter_lightweight/gateway-service/src/main/resources/ui/css/style.css
new file mode 100644
index 0000000..5731863
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/ui/css/style.css
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+.error {
+    font-family:verdana;
+    color:red;
+}
+
+.header {
+    background-color:black;
+    color:white;
+    text-align:center;
+    padding:5px;
+}
+
+.nav {
+    line-height:30px;
+    background-color:#eeeeee;
+    height:300px;
+    width:100px;
+    float:left;
+    padding:5px; 
+}
+
+.section {
+    text-align:center;
+    padding:5px;
+}
+
+.footer {
+    color:red;
+    clear:both;
+    text-align:center;
+    padding:25px; 
+}
\ No newline at end of file
diff --git a/porter_lightweight/gateway-service/src/main/resources/ui/js/jquery-1.11.1.min.js b/porter_lightweight/gateway-service/src/main/resources/ui/js/jquery-1.11.1.min.js
new file mode 100644
index 0000000..ab28a24
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/ui/js/jquery-1.11.1.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b [...]
+if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&& [...]
+},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.prop [...]
diff --git a/porter_lightweight/gateway-service/src/main/resources/ui/js/login.js b/porter_lightweight/gateway-service/src/main/resources/ui/js/login.js
new file mode 100644
index 0000000..c7e7c8e
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/ui/js/login.js
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function loginAction() {
+     var username = document.getElementById("username").value;
+     var password = document.getElementById("paasword").value;
+     var formData = {};
+     formData.userName = username;
+     formData.password = password;
+
+     $.ajax({
+        type: 'POST',
+        url: "/api/user-service/v1/user/login",
+        data: formData,
+        success: function (data) {
+            console.log(data);
+            setCookie("session-id", data.sessiondId, 1);
+            window.location = "/ui/upload.html";
+        },
+        error: function(data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Login failed";
+            error.hidden=false;
+        },
+        async: true
+    });
+}
+
+function setCookie(name,value,days) {
+    var expires = "";
+    if (days) {
+        var date = new Date();
+        date.setTime(date.getTime() + (days*24*60*60*1000));
+        expires = "; expires=" + date.toUTCString();
+    }
+    document.cookie = name + "=" + (value || "")  + expires + "; path=/";
+}
\ No newline at end of file
diff --git a/porter_lightweight/gateway-service/src/main/resources/ui/js/upload.js b/porter_lightweight/gateway-service/src/main/resources/ui/js/upload.js
new file mode 100644
index 0000000..7d66555
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/ui/js/upload.js
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+function uploadAction() {
+     var formData = new FormData(document.getElementById("upload_form"));
+
+     $.ajax({
+        type: 'POST',
+        url: "/api/file-service/upload",
+        data: formData,
+        processData:false,
+        contentType:false,
+        success: function (data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Upload Successfully";
+            error.hidden=false;
+        },
+        error: function(data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Upload failed";
+            error.hidden=false;
+        },
+        async: true
+    });
+}
+
+function deleteAction() {
+     var fileID = document.getElementById("fileID").value;
+     $.ajax({
+        type: 'DELETE',
+        url: "/api/file-service/delete?" + $.param({ id: fileID }),
+        data: {},
+        success: function (data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Delete successfully";
+            error.hidden=false;
+        },
+        error: function(data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Delete failed";
+            error.hidden=false;
+        },
+        async: true
+    });
+}
\ No newline at end of file
diff --git a/porter_lightweight/gateway-service/src/main/resources/ui/login.html b/porter_lightweight/gateway-service/src/main/resources/ui/login.html
new file mode 100644
index 0000000..c8b45fb
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/ui/login.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+
+<!--
+  ~ 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.
+  -->
+
+<html>
+
+    <head>
+        <title>PORTER</title>
+        <link href="css/style.css" rel="stylesheet" type="text/css" media="all" />
+        <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
+        <script type="text/javascript" src="js/login.js"></script>
+    </head>
+
+    <body>
+    <div class="header">
+        <h2>Login</h2>
+    </div>
+    <div class="section">
+        <form method="POST" enctype="multipart/form-data">
+            <input id="username" type="text" placeholder="Username" required="true"/>
+            <input id="paasword" type="password" placeholder="Password" required="true"/>
+            <input type="button" value="Login" onclick="loginAction()">
+        </form>
+    </div>
+    <div class="footer">
+        <p id="error" hidden="true" class="error"/>
+    </div>
+    </body>
+
+</html>
\ No newline at end of file
diff --git a/porter_lightweight/gateway-service/src/main/resources/ui/upload.html b/porter_lightweight/gateway-service/src/main/resources/ui/upload.html
new file mode 100644
index 0000000..bd5eeff
--- /dev/null
+++ b/porter_lightweight/gateway-service/src/main/resources/ui/upload.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+  ~ 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.
+  -->
+
+<html>
+
+    <head>
+        <title>PORTER</title>
+        <link href="css/style.css" rel="stylesheet" type="text/css" media="all" />
+        <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
+        <script type="text/javascript" src="js/upload.js"></script>
+    </head>
+
+    <body>
+    <div class="header">
+        <h2>Upload</h2>
+    </div>
+    <div class="section">
+        <form id="upload_form" method="POST">
+            <p>
+                File Name: <input type="file" name="fileName"/>
+            </p>
+            <p>
+                <input type="button" value="Upload" onclick="uploadAction()">
+            </p>
+        </form>
+    </div>
+
+    <div class="header">
+        <h2>Delete file</h2>
+    </div>
+    <div class="section">
+        <form id="delete_form" method="DELETE">
+            <p>
+                File ID: <input id="fileID" type="text"/>
+            </p>
+            <p>
+                <input type="button" value="Delete" onclick="deleteAction()">
+            </p>
+        </form>
+    </div>
+    <div class="footer">
+        <p id="error" hidden="true" class="error"/>
+    </div>
+    </body>
+
+</html>
\ No newline at end of file
diff --git a/porter_lightweight/pom.xml b/porter_lightweight/pom.xml
new file mode 100644
index 0000000..5a7e539
--- /dev/null
+++ b/porter_lightweight/pom.xml
@@ -0,0 +1,165 @@
+<?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.porter</groupId>
+  <artifactId>porter-application</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </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>
+      <!-- need to compile lastest java-chassis code -->
+      <dependency>
+        <groupId>org.apache.servicecomb</groupId>
+        <artifactId>java-chassis-dependencies</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>solution-basic</artifactId>
+    </dependency>
+  </dependencies>
+
+  <modules>
+    <module>common</module>
+    <module>file-service</module>
+    <module>user-service</module>
+    <module>gateway-service</module>
+  </modules>
+
+  <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>
+          </configuration>
+        </plugin>
+        <plugin>
+          <artifactId>maven-deploy-plugin</artifactId>
+          <version>2.8.2</version>
+          <configuration>
+            <skip>true</skip>
+          </configuration>
+        </plugin>
+        <plugin>
+          <artifactId>maven-install-plugin</artifactId>
+          <version>2.5.2</version>
+          <configuration>
+            <skip>false</skip>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>2.6</version>
+          <configuration>
+            <outputDirectory>${project.build.directory}</outputDirectory>
+            <archive>
+              <manifestEntries>
+                <Class-Path>.</Class-Path>
+              </manifestEntries>
+            </archive>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-war-plugin</artifactId>
+          <version>2.6</version>
+          <configuration>
+            <outputDirectory>${project.build.directory}</outputDirectory>
+            <archive>
+              <manifest>
+                <addClasspath>true</addClasspath>
+                <classpathPrefix>./lib/</classpathPrefix>
+              </manifest>
+              <manifestEntries>
+                <Class-Path>.</Class-Path>
+              </manifestEntries>
+            </archive>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-dependency-plugin</artifactId>
+          <version>2.10</version>
+          <executions>
+            <execution>
+              <id>copy-dependencies</id>
+              <phase>package</phase>
+              <goals>
+                <goal>copy-dependencies</goal>
+              </goals>
+              <configuration>
+                <outputDirectory>${project.build.directory}/lib</outputDirectory>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-maven-plugin</artifactId>
+          <version>2.1.2.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/porter_lightweight/user-service/.gitignore b/porter_lightweight/user-service/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/porter_lightweight/user-service/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/porter_lightweight/user-service/pom.xml b/porter_lightweight/user-service/pom.xml
new file mode 100644
index 0000000..04c50ae
--- /dev/null
+++ b/porter_lightweight/user-service/pom.xml
@@ -0,0 +1,85 @@
+<?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>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-user-service</artifactId>
+  <packaging>jar</packaging>
+
+  <properties>
+    <main.class>org.apache.servicecomb.samples.porter.user.UserMain</main.class>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>porter-common</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.mybatis</groupId>
+      <artifactId>mybatis</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-dbcp2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.mybatis</groupId>
+      <artifactId>mybatis-spring</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-jdbc</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-aop</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context-support</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-tx</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/UserMain.java b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/UserMain.java
new file mode 100644
index 0000000..390b040
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/UserMain.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.samples.porter.user;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+
+public class UserMain {
+  public static void main(String[] args) throws Exception {
+    Log4jUtils.init();
+    BeanUtils.init();
+  }
+}
diff --git a/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionInfoModel.java b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionInfoModel.java
new file mode 100644
index 0000000..f363af5
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionInfoModel.java
@@ -0,0 +1,90 @@
+/*
+ * 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.samples.porter.user.dao;
+
+import samples.porter.user.api.SessionInfo;
+
+public class SessionInfoModel {
+  private int id;
+
+  private String sessiondId;
+
+  private String userName;
+
+  private String roleName;
+
+  private java.sql.Timestamp creationTime;
+
+  private java.sql.Timestamp activeTime;
+
+  public int getId() {
+    return id;
+  }
+
+  public void setId(int id) {
+    this.id = id;
+  }
+
+  public String getSessiondId() {
+    return sessiondId;
+  }
+
+  public void setSessiondId(String sessiondId) {
+    this.sessiondId = sessiondId;
+  }
+
+  public String getUserName() {
+    return userName;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public String getRoleName() {
+    return roleName;
+  }
+
+  public void setRoleName(String roleName) {
+    this.roleName = roleName;
+  }
+
+  public java.sql.Timestamp getCreationTime() {
+    return creationTime;
+  }
+
+  public void setCreationTime(java.sql.Timestamp creationTime) {
+    this.creationTime = creationTime;
+  }
+
+  public java.sql.Timestamp getActiveTime() {
+    return activeTime;
+  }
+
+  public void setActiveTime(java.sql.Timestamp activeTime) {
+    this.activeTime = activeTime;
+  }
+
+  public static SessionInfo toSessionInfo(SessionInfoModel entity) {
+    SessionInfo info = new SessionInfo();
+    info.setSessiondId(entity.getSessiondId());
+    info.setUserName(entity.getUserName());
+    info.setRoleName(entity.getRoleName());
+    return info;
+  }
+}
diff --git a/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionMapper.java b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionMapper.java
new file mode 100644
index 0000000..fb3306b
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionMapper.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.samples.porter.user.dao;
+
+import samples.porter.user.api.SessionInfo;
+
+public interface SessionMapper {
+    void createSession(SessionInfo sessionInfo);
+
+    SessionInfoModel getSessioinInfo(String sessionId);
+    
+    void updateSessionInfo(String sessionId);
+}
diff --git a/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserInfo.java b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserInfo.java
new file mode 100644
index 0000000..b0e2003
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserInfo.java
@@ -0,0 +1,61 @@
+/*
+ * 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.samples.porter.user.dao;
+
+public class UserInfo {
+    private int id;
+
+    private String userName;
+
+    private String password;
+
+    private String roleName;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+}
diff --git a/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserMapper.java b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserMapper.java
new file mode 100644
index 0000000..5c2d331
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserMapper.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.samples.porter.user.dao;
+
+public interface UserMapper {
+    void createUser(UserInfo userInfo);
+
+    UserInfo getUserInfo(String userName);
+}
diff --git a/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/service/UserServiceImpl.java b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/service/UserServiceImpl.java
new file mode 100644
index 0000000..2633d57
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/service/UserServiceImpl.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.samples.porter.user.service;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel;
+import org.apache.servicecomb.samples.porter.user.dao.SessionMapper;
+import org.apache.servicecomb.samples.porter.user.dao.UserInfo;
+import org.apache.servicecomb.samples.porter.user.dao.UserMapper;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.netflix.config.DynamicPropertyFactory;
+
+import samples.porter.user.api.SessionInfo;
+import samples.porter.user.api.UserService;
+
+@Service
+public class UserServiceImpl implements UserService {
+  private static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
+
+  @Autowired
+  private UserMapper userMapper;
+
+  @Autowired
+  private SessionMapper sessionMapper;
+
+
+  public SessionInfo login(String userName,
+      String password) {
+    UserInfo userInfo = userMapper.getUserInfo(userName);
+    if (userInfo != null) {
+      if (validatePassword(password, userInfo.getPassword())) {
+        SessionInfo sessionInfo = new SessionInfo();
+        sessionInfo.setSessiondId(UUID.randomUUID().toString());
+        sessionInfo.setUserName(userInfo.getUserName());
+        sessionInfo.setRoleName(userInfo.getRoleName());
+        sessionMapper.createSession(sessionInfo);
+        return sessionInfo;
+      }
+    }
+    return null;
+  }
+
+  public SessionInfo getSession(String sessionId) {
+    if (sessionId == null) {
+      throw new InvocationException(405, "", "invalid session.");
+    }
+    SessionInfoModel sessionInfo = sessionMapper.getSessioinInfo(sessionId);
+    if (sessionInfo != null) {
+      if (System.currentTimeMillis() - sessionInfo.getActiveTime().getTime() > 10 * 60 * 1000) {
+        LOGGER.info("user session expired.");
+        return null;
+      } else {
+        sessionMapper.updateSessionInfo(sessionInfo.getSessiondId());
+        return SessionInfoModel.toSessionInfo(sessionInfo);
+      }
+    }
+    return null;
+  }
+
+  private boolean validatePassword(String plain, String encrypt) {
+    // 简单加密校验,开发者可以结合业务场景自行修改
+    try {
+      MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+      messageDigest.update(plain.getBytes("UTF-8"));
+      byte byteBuffer[] = messageDigest.digest();
+      String encryptedText = Base64.encodeBase64String(byteBuffer);
+      return encryptedText.equals(encrypt);
+    } catch (NoSuchAlgorithmException e) {
+      LOGGER.error("", e);
+    } catch (UnsupportedEncodingException e) {
+      LOGGER.error("", e);
+    }
+    return false;
+  }
+
+
+  public String ping(String message) {
+    long delay = DynamicPropertyFactory.getInstance().getLongProperty("user.ping.delay", 0).get();
+    if (delay > 0) {
+      try {
+        TimeUnit.SECONDS.sleep(delay);
+      } catch (InterruptedException e) {
+        LOGGER.error("", e);
+      }
+    }
+    return message;
+  }
+}
diff --git a/porter_lightweight/user-service/src/main/resources/META-INF/spring/user.bean.xml b/porter_lightweight/user-service/src/main/resources/META-INF/spring/user.bean.xml
new file mode 100644
index 0000000..e1cdd94
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/resources/META-INF/spring/user.bean.xml
@@ -0,0 +1,57 @@
+<?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.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+    xmlns:util="http://www.springframework.org/schema/util"
+    xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:tx="http://www.springframework.org/schema/tx"
+    xsi:schemaLocation="
+		http://www.springframework.org/schema/beans classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd
+        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <context:component-scan base-package="samples.porter.user" >
+    </context:component-scan>
+
+    <bean id="dataSource"
+        class="org.apache.commons.dbcp2.BasicDataSource"
+        destroy-method="close">
+        <property name="driverClassName" value="${db.driverClassName:com.mysql.jdbc.Driver}" />
+        <property name="url"
+            value="${db.url:jdbc:mysql://localhost/porter_user_db}" />
+        <property name="username" value="${db.username:root}" />
+        <property name="password" value="${db.password:}" />
+    </bean>
+
+    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
+        <property name="dataSource" ref="dataSource" />
+        <property name="configLocation" value="classpath:/config/mybatis-config.xml"></property>
+    </bean>
+
+    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
+        <property name="mapperInterface"
+            value="org.apache.servicecomb.samples.porter.user.dao.UserMapper" />
+        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
+    </bean>
+    <bean id="sessionMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
+        <property name="mapperInterface"
+            value="org.apache.servicecomb.samples.porter.user.dao.SessionMapper" />
+        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
+    </bean>
+</beans>
\ No newline at end of file
diff --git a/porter_lightweight/user-service/src/main/resources/config/SessionMapper.xml b/porter_lightweight/user-service/src/main/resources/config/SessionMapper.xml
new file mode 100644
index 0000000..989e786
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/resources/config/SessionMapper.xml
@@ -0,0 +1,57 @@
+<?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.
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.SessionMapper">
+    <resultMap id="sessionInfo" type="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
+        <result column="ID" jdbcType="INTEGER" property="id" />
+        <result column="SESSION_ID" jdbcType="VARCHAR" property="sessiondId" />
+        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
+        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
+        <result column="CREATION_TIME" jdbcType="TIMESTAMP" property="creationTime" />
+        <result column="ACTIVE_TIME" jdbcType="TIMESTAMP" property="activeTime" />
+    </resultMap>
+
+    <sql id="all_column">
+        ID, SESSION_ID, USER_NAME, ROLE_NAME, CREATION_TIME, ACTIVE_TIME
+    </sql>
+
+    <sql id="all_column_auto">
+        SESSION_ID, USER_NAME, ROLE_NAME
+    </sql>
+
+    <insert id="createSession" parameterType="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
+        insert into T_SESSION (
+        <include refid="all_column_auto" />
+        )
+        values (#{sessiondId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR},
+        #{roleName,jdbcType=VARCHAR})
+    </insert>
+
+    <select id="getSessioinInfo" parameterType="java.lang.String"
+        resultMap="sessionInfo">
+        select
+        <include refid="all_column" />
+        from T_SESSION where SESSION_ID = #{0,jdbcType=VARCHAR}
+    </select>
+    
+    <update id="updateSessionInfo" parameterType="java.lang.String">
+        update T_SESSION
+        set CREATION_TIME = CREATION_TIME where SESSION_ID = #{0,jdbcType=VARCHAR};
+    </update>
+</mapper>
\ No newline at end of file
diff --git a/porter_lightweight/user-service/src/main/resources/config/UserMapper.xml b/porter_lightweight/user-service/src/main/resources/config/UserMapper.xml
new file mode 100644
index 0000000..c02e60d
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/resources/config/UserMapper.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.
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.UserMapper">
+    <resultMap id="userInfo" type="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
+        <result column="ID" jdbcType="INTEGER" property="id" />
+        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
+        <result column="PASSWORD" jdbcType="VARCHAR" property="password" />
+        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
+    </resultMap>
+
+    <sql id="all_column">
+        ID, USER_NAME, PASSWORD, ROLE_NAME
+    </sql>
+
+    <insert id="createUser" parameterType="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
+        insert into T_USER (
+        <include refid="all_column" />
+        )
+        values (#{id,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR},
+        #{password,jdbcType=VARCHAR},#{roleName,jdbcType=VARCHAR})
+    </insert>
+
+    <select id="getUserInfo" parameterType="java.lang.String"
+        resultMap="userInfo">
+        select
+        <include refid="all_column" />
+        from T_USER where USER_NAME = #{0,jdbcType=VARCHAR}
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/porter_lightweight/user-service/src/main/resources/config/create_db_user.sql b/porter_lightweight/user-service/src/main/resources/config/create_db_user.sql
new file mode 100644
index 0000000..3505f3d
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/resources/config/create_db_user.sql
@@ -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.
+ */
+
+CREATE DATABASE IF NOT EXISTS porter_user_db;
+
+USE porter_user_db;
+
+DROP TABLE IF EXISTS T_USER;
+
+CREATE TABLE `T_USER` (
+  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT '用户名称',
+  `PASSWORD`  VARCHAR(64) NOT NULL COMMENT '用户密码',
+  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT '角色名称',
+  PRIMARY KEY (`ID`)
+);
+
+#### password is encrypted for test
+insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("admin", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "admin");
+insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("guest", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "guest");
+
+DROP TABLE IF EXISTS T_SESSION;
+
+CREATE TABLE `T_SESSION` (
+  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT '唯一标识',
+  `SESSION_ID`  VARCHAR(64) NOT NULL COMMENT '临时会话ID',
+  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT '用户名称',
+  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT '角色名称',
+  `CREATION_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `ACTIVE_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最近活跃时间',
+  PRIMARY KEY (`ID`)
+);
diff --git a/porter_lightweight/user-service/src/main/resources/config/mybatis-config.xml b/porter_lightweight/user-service/src/main/resources/config/mybatis-config.xml
new file mode 100644
index 0000000..894caac
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/resources/config/mybatis-config.xml
@@ -0,0 +1,27 @@
+<?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.
+  -->
+
+<!DOCTYPE configuration
+  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+  "http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+    <mappers>
+        <mapper resource="config/UserMapper.xml"/>
+        <mapper resource="config/SessionMapper.xml"/>
+    </mappers>
+</configuration>
\ No newline at end of file
diff --git a/porter_lightweight/user-service/src/main/resources/microservice.yaml b/porter_lightweight/user-service/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..81ef89e
--- /dev/null
+++ b/porter_lightweight/user-service/src/main/resources/microservice.yaml
@@ -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.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+service_description:
+  name: user-service
+
+servicecomb:
+  rest:
+    address: 0.0.0.0:9093
\ No newline at end of file