You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by wu...@apache.org on 2018/07/11 06:50:12 UTC

[incubator-skywalking] branch 6.0 updated: Feature/oap/cluster plugin (#1440)

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

wusheng pushed a commit to branch 6.0
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking.git


The following commit(s) were added to refs/heads/6.0 by this push:
     new dcdfeb1  Feature/oap/cluster plugin (#1440)
dcdfeb1 is described below

commit dcdfeb1e145b487c664fe9e11017c974df087aa7
Author: 彭勇升 pengys <80...@qq.com>
AuthorDate: Wed Jul 11 14:50:08 2018 +0800

    Feature/oap/cluster plugin (#1440)
    
    * Cluster module implementation finished.
---
 .../apm/collector/core/util/CollectionUtils.java   |   5 +-
 .../apm/collector/storage/base/sql/SqlBuilder.java |   7 +-
 .../concepts-and-designs/OAP-Cluster-Management.md |  43 +++++
 oap-server/pom.xml                                 | 193 +++++++++++++++++++++
 .../cluster-standalone-plugin/pom.xml              |  40 +++++
 .../ClusterModuleStandaloneProvider.java           |  61 +++++++
 .../plugin/standalone/StandaloneModuleQuery.java   |  41 ++---
 .../standalone/StandaloneModuleRegister.java       |  38 +---
 .../plugin/standalone/StandaloneRegister.java      |  36 +---
 .../standalone/StandaloneServiceManager.java       |  38 ++--
 ...alking.oap.server.library.module.ModuleProvider |  19 ++
 .../cluster-zookeeper-plugin/pom.xml               |  77 ++++++++
 .../zookeeper/ClusterModuleZookeeperConfig.java    |  55 ++++++
 .../zookeeper/ClusterModuleZookeeperProvider.java  |  86 +++++++++
 .../cluster/plugin/zookeeper/NodeNameBuilder.java  |  37 +---
 .../plugin/zookeeper/SWInstanceSerializer.java     |  42 ++---
 .../plugin/zookeeper/ServiceCacheManager.java      |  40 ++---
 .../plugin/zookeeper/ZookeeperModuleQuery.java     |  44 +++++
 .../plugin/zookeeper/ZookeeperModuleRegister.java  |  66 +++++++
 ...alking.oap.server.library.module.ModuleProvider |  19 ++
 .../ClusterModuleZookeeperProviderTestCase.java    |  71 ++++++++
 .../src/test/resources/log4j2.xml                  |  31 ++++
 oap-server/server-cluster-plugin/pom.xml           |  49 ++++++
 oap-server/server-core/core-cluster/pom.xml        |  33 ++++
 .../oap/server/core/cluster/ClusterModule.java     |  37 +---
 .../oap/server/core/cluster/InstanceDetails.java   |  39 ++---
 .../oap/server/core/cluster/ModuleQuery.java       |  36 +---
 .../oap/server/core/cluster/ModuleRegister.java    |  38 +---
 .../core/cluster/ServiceRegisterException.java     |  37 +---
 ...ywalking.oap.server.library.module.ModuleDefine |  19 ++
 oap-server/server-core/pom.xml                     |  48 +++++
 oap-server/server-library/library-module/pom.xml   |  32 ++++
 .../library/module/ApplicationConfiguration.java   |  92 ++++++++++
 .../library/module/DuplicateProviderException.java |  25 +++
 .../oap/server/library/module/ModuleConfig.java    |  37 +---
 .../library/module/ModuleConfigException.java      |  37 +---
 .../oap/server/library/module/ModuleDefine.java    | 133 ++++++++++++++
 .../oap/server/library/module/ModuleManager.java   |  86 +++++++++
 .../library/module/ModuleNotFoundException.java    |  30 ++++
 .../module/ModuleNotFoundRuntimeException.java     |  37 +---
 .../oap/server/library/module/ModuleProvider.java  | 131 ++++++++++++++
 .../library/module/ModuleStartException.java       |  37 +---
 .../library/module/ProviderNotFoundException.java  |  29 ++++
 .../oap/server/library/module/Service.java         |  29 ++++
 .../module/ServiceNotProvidedException.java        |  25 +++
 .../module/ServiceNotProvidedRuntimeException.java |  25 +++
 .../module/ApplicationConfigurationTestCase.java   |  56 ++++++
 .../oap/server/library/module/BaseModuleA.java     |  37 ++--
 .../oap/server/library/module/BaseModuleB.java     |  35 ++--
 .../library/module/ModuleABusiness1Impl.java       |  28 +++
 .../library/module/ModuleABusiness2Impl.java       |  26 +++
 .../oap/server/library/module/ModuleAProvider.java |  63 +++++++
 .../library/module/ModuleBBusiness1Impl.java       |  25 +++
 .../library/module/ModuleBBusiness2Impl.java       |  25 +++
 .../oap/server/library/module/ModuleBProvider.java |  39 ++---
 .../library/module/ModuleManagerTestCase.java      | 102 +++++++++++
 .../oap/server/library/module/TestModule.java      |  35 ++++
 .../server/library/module/TestModuleProvider.java  |  37 ++--
 ...ywalking.oap.server.library.module.ModuleDefine |  21 +++
 ...alking.oap.server.library.module.ModuleProvider |  21 +++
 .../library-module/src/test/resources/log4j2.xml   |  31 ++++
 oap-server/server-library/library-util/pom.xml     |  32 ++++
 .../oap/server/library}/util/CollectionUtils.java  |   6 +-
 .../oap/server/library/util/ResourceUtils.java     |  45 ++---
 .../oap/server/library/util/StringUtils.java       |  37 +---
 oap-server/server-library/pom.xml                  |  37 ++++
 oap-server/server-starter/pom.xml                  |  54 ++++++
 .../oap/server/starter/OAPBootStartUp.java         |  50 ++++++
 .../starter/config/ApplicationConfigLoader.java    | 128 ++++++++++++++
 .../config/ConfigFileNotFoundException.java        |  37 +---
 .../oap/server/starter/config/ConfigLoader.java    |  38 +---
 .../src/main/resources/application.yml             |  28 +++
 .../server-starter/src/main/resources/log4j2.xml   |  37 ++++
 pom.xml                                            |  42 ++++-
 74 files changed, 2635 insertions(+), 727 deletions(-)

diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
index 45cd3e5..31d8c61 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
@@ -16,12 +16,9 @@
  *
  */
 
-
 package org.apache.skywalking.apm.collector.core.util;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * @author peng-yongsheng
diff --git a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/base/sql/SqlBuilder.java b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/base/sql/SqlBuilder.java
index 75e235c..8f3f997 100644
--- a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/base/sql/SqlBuilder.java
+++ b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/base/sql/SqlBuilder.java
@@ -19,8 +19,7 @@
 package org.apache.skywalking.apm.collector.storage.base.sql;
 
 import java.text.MessageFormat;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  * @author peng-yongsheng, clevertension
@@ -38,7 +37,7 @@ public class SqlBuilder {
     public static String buildBatchInsertSql(String tableName, Set<String> columnNames) {
         StringBuilder sb = new StringBuilder("insert into ");
         sb.append(tableName).append("(");
-        columnNames.forEach((columnName) -> sb.append(columnName).append(","));
+        columnNames.forEach(columnName -> sb.append(columnName).append(","));
         sb.delete(sb.length() - 1, sb.length());
         sb.append(") values(");
         for (int i = 0; i < columnNames.size(); i++) {
@@ -52,7 +51,7 @@ public class SqlBuilder {
     public static String buildBatchUpdateSql(String tableName, Set<String> columnNames, String whereClauseName) {
         StringBuilder sb = new StringBuilder("update ");
         sb.append(tableName).append(" set ");
-        columnNames.forEach((columnName) -> sb.append(columnName).append("=?,"));
+        columnNames.forEach(columnName -> sb.append(columnName).append("=?,"));
         sb.delete(sb.length() - 1, sb.length());
         sb.append(" where ").append(whereClauseName).append("=?");
         return sb.toString();
diff --git a/docs/en/concepts-and-designs/OAP-Cluster-Management.md b/docs/en/concepts-and-designs/OAP-Cluster-Management.md
new file mode 100644
index 0000000..8a27d54
--- /dev/null
+++ b/docs/en/concepts-and-designs/OAP-Cluster-Management.md
@@ -0,0 +1,43 @@
+# Observability Analysis Platform Cluster Management
+OAP(Observability Analysis Platform) backend is a distributed system, services need to find each 
+other. i.e. a web service needs to find query service, level 1 aggregate service need to find 
+level 2 aggregate service. Cluster management is just a client-side implementation. It must work 
+together with a distributed coordination service, (i.e. Zookeeper, Consul, Kubernetes.) unless 
+running in standalone mode.
+
+## Architecture overview
+<img src="https://skywalkingtest.github.io/page-resources/6.0.0-alpha/cluster_management.png"/>
+
+### Cluster Management Plugins
+By default, OAP backend provides two implementations for cluster management, which are standalone 
+and zookeeper. When the scale of services, which are under monitoring, is small, you can choose 
+the standalone mode. Otherwise, you must choose the cluster mode by zookeeper plugin, or you can 
+implement a new service discovery plugin for your own scene.
+
+### Cluster Management Interface
+There are two interfaces defined beforehand in the OAP server core, which are Module register and 
+module query, all the cluster management plugins must implement those two interfaces.
+
+* Module Register: When any modules need to provide services for others, the module must do register 
+through this interface.
+* Module Query: When any module needs to find other services, it can use this interface to retrieve 
+the service instance list in the certain order.
+
+### Process Flow Between Client and Cluster Management
+The client has two ways to connect the backend, one, use the direct link by a set of backend instance 
+endpoint list, or you can use naming service, which considers your given list is just the seed nodes 
+of the whole cluster. The following graph is showing you how naming service works. You need to check 
+the probe documents to know which way(s) is(are) supported.
+```
+         Client lib                         Collector1             Collector2              Collector3
+ (Set collector.servers=Collector2)              (Collector 1,2,3 constitute the cluster)
+             |
+             +-----------> naming service ---------------------------->|
+                                                                       |
+             |<------- receive gRPC IP:Port(s) of Collector 1,2,3---<--|
+             |
+             |Select a random gRPC service
+             |For example collector 3
+             |
+             |------------------------->Uplink gRPC service----------------------------------->|
+```
\ No newline at end of file
diff --git a/oap-server/pom.xml b/oap-server/pom.xml
new file mode 100644
index 0000000..de56d23
--- /dev/null
+++ b/oap-server/pom.xml
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>apm</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>oap-server</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>server-cluster-plugin</module>
+        <module>server-library</module>
+        <module>server-core</module>
+        <module>server-starter</module>
+    </modules>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <slf4j.version>1.7.25</slf4j.version>
+        <log4j.version>2.9.0</log4j.version>
+        <guava.version>19.0</guava.version>
+        <snakeyaml.version>1.18</snakeyaml.version>
+        <gson.version>2.8.1</gson.version>
+        <graphql-java-tools.version>4.3.0</graphql-java-tools.version>
+        <zookeeper.version>3.4.10</zookeeper.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.skywalking</groupId>
+                <artifactId>apm-util</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>log4j-over-slf4j</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.logging.log4j</groupId>
+                <artifactId>log4j-core</artifactId>
+                <version>${log4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.graphql-java</groupId>
+                <artifactId>graphql-java-tools</artifactId>
+                <version>${graphql-java-tools.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.code.gson</groupId>
+                <artifactId>gson</artifactId>
+                <version>${gson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>joda-time</groupId>
+                <artifactId>joda-time</artifactId>
+                <version>${joda-time.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.elasticsearch.client</groupId>
+                <artifactId>transport</artifactId>
+                <version>${elasticsearch.client.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <artifactId>snakeyaml</artifactId>
+                        <groupId>org.yaml</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>netty-common</artifactId>
+                        <groupId>io.netty</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>netty-transport</artifactId>
+                        <groupId>io.netty</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>netty-codec</artifactId>
+                        <groupId>io.netty</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>netty-codec-http</artifactId>
+                        <groupId>io.netty</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>netty-buffer</artifactId>
+                        <groupId>io.netty</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>netty-handler</artifactId>
+                        <groupId>io.netty</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>netty-resolver</artifactId>
+                        <groupId>io.netty</groupId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.zookeeper</groupId>
+                <artifactId>zookeeper</artifactId>
+                <version>${zookeeper.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <artifactId>slf4j-api</artifactId>
+                        <groupId>org.slf4j</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>slf4j-log4j12</artifactId>
+                        <groupId>org.slf4j</groupId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.yaml</groupId>
+                <artifactId>snakeyaml</artifactId>
+                <version>${snakeyaml.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.logging.log4j</groupId>
+                <artifactId>log4j-slf4j-impl</artifactId>
+                <version>${log4j.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.apache.logging.log4j</groupId>
+                        <artifactId>log4j-core</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-cluster-plugin/cluster-standalone-plugin/pom.xml b/oap-server/server-cluster-plugin/cluster-standalone-plugin/pom.xml
new file mode 100644
index 0000000..743028f
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-standalone-plugin/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>server-cluster-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>cluster-standalone-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>core-cluster</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/ClusterModuleStandaloneProvider.java b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/ClusterModuleStandaloneProvider.java
new file mode 100644
index 0000000..fddd3f5
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/ClusterModuleStandaloneProvider.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.skywalking.oap.server.cluster.plugin.standalone;
+
+import org.apache.skywalking.oap.server.core.cluster.*;
+import org.apache.skywalking.oap.server.library.module.*;
+import org.slf4j.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class ClusterModuleStandaloneProvider extends ModuleProvider {
+
+    private static final Logger logger = LoggerFactory.getLogger(ClusterModuleStandaloneProvider.class);
+
+    private final StandaloneServiceManager serviceManager;
+
+    public ClusterModuleStandaloneProvider() {
+        super();
+        this.serviceManager = new StandaloneServiceManager();
+    }
+
+    @Override public String name() {
+        return "standalone";
+    }
+
+    @Override public Class module() {
+        return ClusterModule.class;
+    }
+
+    @Override public ModuleConfig createConfigBeanIfAbsent() {
+        return null;
+    }
+
+    @Override public void prepare() throws ServiceNotProvidedException {
+        this.registerServiceImplementation(ModuleRegister.class, new StandaloneModuleRegister(serviceManager));
+        this.registerServiceImplementation(ModuleQuery.class, new StandaloneModuleQuery(serviceManager));
+    }
+
+    @Override public void start() throws ModuleStartException {
+    }
+
+    @Override public void notifyAfterCompleted() {
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneModuleQuery.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneModuleQuery.java
index 45cd3e5..cc0b326 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneModuleQuery.java
@@ -16,43 +16,26 @@
  *
  */
 
+package org.apache.skywalking.oap.server.cluster.plugin.standalone;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+import org.apache.skywalking.oap.server.core.cluster.*;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
+public class StandaloneModuleQuery implements ModuleQuery {
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
+    private final StandaloneServiceManager serviceManager;
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    StandaloneModuleQuery(StandaloneServiceManager serviceManager) {
+        this.serviceManager = serviceManager;
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    @Override
+    public List<InstanceDetails> query(String moduleName, String providerName) {
+        List<InstanceDetails> instanceDetails = new ArrayList<>(1);
+        instanceDetails.add(serviceManager.get(moduleName, providerName));
+        return instanceDetails;
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneModuleRegister.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneModuleRegister.java
index 45cd3e5..bb9241d 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneModuleRegister.java
@@ -16,43 +16,23 @@
  *
  */
 
+package org.apache.skywalking.oap.server.cluster.plugin.standalone;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.apache.skywalking.oap.server.core.cluster.*;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
+public class StandaloneModuleRegister implements ModuleRegister {
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
+    private final StandaloneServiceManager serviceManager;
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    StandaloneModuleRegister(StandaloneServiceManager serviceManager) {
+        this.serviceManager = serviceManager;
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    @Override public void register(String moduleName, String providerName,
+        InstanceDetails instanceDetails) {
+        serviceManager.put(moduleName, providerName, instanceDetails);
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneRegister.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneRegister.java
index 45cd3e5..7f923fa 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneRegister.java
@@ -16,43 +16,17 @@
  *
  */
 
+package org.apache.skywalking.oap.server.cluster.plugin.standalone;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.apache.skywalking.oap.server.core.cluster.*;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
+public class StandaloneRegister implements ModuleRegister {
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+    @Override public void register(String moduleName, String providerName,
+        InstanceDetails instanceDetails) throws ServiceRegisterException {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneServiceManager.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneServiceManager.java
index 45cd3e5..fe5fe1d 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/standalone/StandaloneServiceManager.java
@@ -16,43 +16,27 @@
  *
  */
 
+package org.apache.skywalking.oap.server.cluster.plugin.standalone;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+import org.apache.skywalking.oap.server.core.cluster.InstanceDetails;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
+public class StandaloneServiceManager {
 
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
+    private final Map<String, InstanceDetails> instanceDetailsMap;
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
+    public StandaloneServiceManager() {
+        this.instanceDetailsMap = new HashMap<>();
     }
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    public void put(String moduleName, String providerName, InstanceDetails instanceDetails) {
+        instanceDetailsMap.put(moduleName + "/" + providerName, instanceDetails);
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public InstanceDetails get(String moduleName, String providerName) {
+        return instanceDetailsMap.get(moduleName + "/" + providerName);
     }
 }
diff --git a/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..3fe80af
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-standalone-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -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.skywalking.oap.server.cluster.plugin.standalone.ClusterModuleStandaloneProvider
\ No newline at end of file
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/pom.xml b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/pom.xml
new file mode 100644
index 0000000..0fab89c
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.skywalking</groupId>
+        <artifactId>server-cluster-plugin</artifactId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>cluster-zookeeper-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <curator.version>4.0.1</curator.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>core-cluster</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-x-discovery</artifactId>
+            <version>${curator.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <version>2.12.0</version>
+            <!--<version>${curator.version}</version>-->
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+            </exclusions>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperConfig.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperConfig.java
new file mode 100644
index 0000000..fb64f17
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperConfig.java
@@ -0,0 +1,55 @@
+/*
+ * 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.skywalking.oap.server.cluster.plugin.zookeeper;
+
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+import org.apache.skywalking.oap.server.library.util.StringUtils;
+
+/**
+ * @author peng-yongsheng
+ */
+class ClusterModuleZookeeperConfig extends ModuleConfig {
+    private String hostPort;
+    private int baseSleepTimeMs;
+    private int maxRetries;
+
+    public String getHostPort() {
+        return StringUtils.isNotEmpty(hostPort) ? hostPort : "localhost:2181";
+    }
+
+    public void setHostPort(String hostPort) {
+        this.hostPort = hostPort;
+    }
+
+    public int getBaseSleepTimeMs() {
+        return baseSleepTimeMs > 0 ? baseSleepTimeMs : 1000;
+    }
+
+    public void setBaseSleepTimeMs(int baseSleepTimeMs) {
+        this.baseSleepTimeMs = baseSleepTimeMs;
+    }
+
+    public int getMaxRetries() {
+        return maxRetries > 0 ? maxRetries : 3;
+    }
+
+    public void setMaxRetries(int maxRetries) {
+        this.maxRetries = maxRetries;
+    }
+}
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperProvider.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperProvider.java
new file mode 100644
index 0000000..031c9ab
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperProvider.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.cluster.plugin.zookeeper;
+
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.*;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.curator.x.discovery.*;
+import org.apache.skywalking.oap.server.core.cluster.*;
+import org.apache.skywalking.oap.server.library.module.*;
+import org.slf4j.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class ClusterModuleZookeeperProvider extends ModuleProvider {
+
+    private static final Logger logger = LoggerFactory.getLogger(ClusterModuleZookeeperProvider.class);
+
+    private static final String BASE_PATH = "/skywalking";
+
+    private final ServiceCacheManager cacheManager;
+    private final ClusterModuleZookeeperConfig config;
+    private CuratorFramework client;
+    private ServiceDiscovery<InstanceDetails> serviceDiscovery;
+
+    public ClusterModuleZookeeperProvider() {
+        super();
+        this.config = new ClusterModuleZookeeperConfig();
+        this.cacheManager = new ServiceCacheManager();
+    }
+
+    @Override public String name() {
+        return "zookeeper";
+    }
+
+    @Override public Class module() {
+        return ClusterModule.class;
+    }
+
+    @Override public ModuleConfig createConfigBeanIfAbsent() {
+        return config;
+    }
+
+    @Override public void prepare() throws ServiceNotProvidedException {
+        RetryPolicy retryPolicy = new ExponentialBackoffRetry(config.getBaseSleepTimeMs(), config.getMaxRetries());
+        client = CuratorFrameworkFactory.newClient(config.getHostPort(), retryPolicy);
+
+        serviceDiscovery = ServiceDiscoveryBuilder.builder(InstanceDetails.class).client(client)
+            .basePath(BASE_PATH)
+            .watchInstances(true)
+            .serializer(new SWInstanceSerializer()).build();
+
+        this.registerServiceImplementation(ModuleRegister.class, new ZookeeperModuleRegister(serviceDiscovery, cacheManager));
+        this.registerServiceImplementation(ModuleQuery.class, new ZookeeperModuleQuery(cacheManager));
+    }
+
+    @Override public void start() throws ModuleStartException {
+        try {
+            client.start();
+            client.blockUntilConnected();
+            serviceDiscovery.start();
+        } catch (Exception e) {
+            throw new ModuleStartException(e.getMessage(), e);
+        }
+    }
+
+    @Override public void notifyAfterCompleted() {
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/NodeNameBuilder.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/NodeNameBuilder.java
index 45cd3e5..af9db7c 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/NodeNameBuilder.java
@@ -16,43 +16,14 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.cluster.plugin.zookeeper;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+public class NodeNameBuilder {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public static String build(String moduleName, String providerName) {
+        return moduleName + "/" + providerName;
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/SWInstanceSerializer.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/SWInstanceSerializer.java
index 45cd3e5..76b59b5 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/SWInstanceSerializer.java
@@ -16,43 +16,27 @@
  *
  */
 
+package org.apache.skywalking.oap.server.cluster.plugin.zookeeper;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import org.apache.curator.x.discovery.ServiceInstance;
+import org.apache.curator.x.discovery.details.InstanceSerializer;
+import org.apache.skywalking.oap.server.core.cluster.InstanceDetails;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
+public class SWInstanceSerializer implements InstanceSerializer<InstanceDetails> {
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
+    private final Gson gson = new Gson();
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    @Override public byte[] serialize(ServiceInstance<InstanceDetails> instance) throws Exception {
+        return gson.toJson(instance).getBytes();
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    @Override public ServiceInstance<InstanceDetails> deserialize(byte[] bytes) throws Exception {
+        return gson.fromJson(new String(bytes), new TypeToken<ServiceInstance<InstanceDetails>>() {
+        }.getType());
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ServiceCacheManager.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ServiceCacheManager.java
index 45cd3e5..e08a01b 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ServiceCacheManager.java
@@ -16,43 +16,29 @@
  *
  */
 
+package org.apache.skywalking.oap.server.cluster.plugin.zookeeper;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.curator.x.discovery.ServiceCache;
+import org.apache.skywalking.oap.server.core.cluster.InstanceDetails;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
+public class ServiceCacheManager {
 
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
+    private final Map<String, ServiceCache<InstanceDetails>> serviceCacheMap;
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
+    public ServiceCacheManager() {
+        this.serviceCacheMap = new ConcurrentHashMap<>();
     }
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    public void put(String name, ServiceCache<InstanceDetails> cache) {
+        serviceCacheMap.put(name, cache);
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public ServiceCache<InstanceDetails> get(String name) {
+        return serviceCacheMap.get(name);
     }
 }
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperModuleQuery.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperModuleQuery.java
new file mode 100644
index 0000000..7dd93e8
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperModuleQuery.java
@@ -0,0 +1,44 @@
+/*
+ * 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.skywalking.oap.server.cluster.plugin.zookeeper;
+
+import java.util.*;
+import org.apache.curator.x.discovery.ServiceInstance;
+import org.apache.skywalking.oap.server.core.cluster.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class ZookeeperModuleQuery implements ModuleQuery {
+
+    private final ServiceCacheManager cacheManager;
+
+    ZookeeperModuleQuery(ServiceCacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
+
+    @Override
+    public List<InstanceDetails> query(String moduleName, String providerName) throws ServiceRegisterException {
+        List<ServiceInstance<InstanceDetails>> serviceInstances = cacheManager.get(NodeNameBuilder.build(moduleName, providerName)).getInstances();
+
+        List<InstanceDetails> instanceDetails = new ArrayList<>(serviceInstances.size());
+        serviceInstances.forEach(serviceInstance -> instanceDetails.add(serviceInstance.getPayload()));
+        return instanceDetails;
+    }
+}
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperModuleRegister.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperModuleRegister.java
new file mode 100644
index 0000000..ede5fbd
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperModuleRegister.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.cluster.plugin.zookeeper;
+
+import java.util.UUID;
+import org.apache.curator.x.discovery.*;
+import org.apache.skywalking.oap.server.core.cluster.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class ZookeeperModuleRegister implements ModuleRegister {
+
+    private final ServiceDiscovery<InstanceDetails> serviceDiscovery;
+    private final ServiceCacheManager cacheManager;
+
+    ZookeeperModuleRegister(ServiceDiscovery<InstanceDetails> serviceDiscovery,
+        ServiceCacheManager cacheManager) {
+        this.serviceDiscovery = serviceDiscovery;
+        this.cacheManager = cacheManager;
+    }
+
+    @Override public synchronized void register(String moduleName, String providerName,
+        InstanceDetails instanceDetails) throws ServiceRegisterException {
+        try {
+            String name = NodeNameBuilder.build(moduleName, providerName);
+
+            ServiceInstance<InstanceDetails> thisInstance = ServiceInstance.<InstanceDetails>builder()
+                .name(NodeNameBuilder.build(moduleName, providerName))
+                .id(UUID.randomUUID().toString())
+                .address(instanceDetails.getHost())
+                .port(instanceDetails.getPort())
+//                .uriSpec(new UriSpec(StringUtils.isEmpty(instanceDetails.getContextPath()) ? StringUtils.EMPTY_STRING : instanceDetails.getContextPath()))
+                .payload(instanceDetails)
+                .build();
+
+            serviceDiscovery.registerService(thisInstance);
+
+            ServiceCache<InstanceDetails> serviceCache = serviceDiscovery.serviceCacheBuilder()
+                .name(name)
+                .build();
+            serviceCache.start();
+
+            cacheManager.put(name, serviceCache);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ServiceRegisterException(e.getMessage());
+        }
+    }
+}
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..cf619b6
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -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.skywalking.oap.server.cluster.plugin.zookeeper.ClusterModuleZookeeperProvider
\ No newline at end of file
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperProviderTestCase.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperProviderTestCase.java
new file mode 100644
index 0000000..218eccc
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ClusterModuleZookeeperProviderTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.cluster.plugin.zookeeper;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.curator.test.TestingServer;
+import org.apache.skywalking.oap.server.core.cluster.*;
+import org.apache.skywalking.oap.server.library.module.*;
+import org.junit.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class ClusterModuleZookeeperProviderTestCase {
+
+    private TestingServer server;
+
+    @Before
+    public void before() throws Exception {
+        server = new TestingServer(12181, true);
+        server.start();
+    }
+
+    @Test
+    public void testStart() throws ServiceNotProvidedException, ModuleStartException, ServiceRegisterException {
+        ClusterModuleZookeeperProvider provider = new ClusterModuleZookeeperProvider();
+        ClusterModuleZookeeperConfig moduleConfig = (ClusterModuleZookeeperConfig)provider.createConfigBeanIfAbsent();
+        moduleConfig.setHostPort(server.getConnectString());
+        moduleConfig.setBaseSleepTimeMs(3000);
+        moduleConfig.setMaxRetries(4);
+
+        provider.prepare();
+        provider.start();
+
+        ModuleRegister moduleRegister = provider.getService(ModuleRegister.class);
+        ModuleQuery moduleQuery = provider.getService(ModuleQuery.class);
+
+        InstanceDetails instanceDetails = new InstanceDetails();
+        instanceDetails.setHost("ProviderAHost");
+        instanceDetails.setPort(1000);
+
+        moduleRegister.register("ModuleA", "ProviderA", instanceDetails);
+
+        List<InstanceDetails> detailsList = moduleQuery.query("ModuleA", "ProviderA");
+        Assert.assertEquals(1, detailsList.size());
+        Assert.assertEquals("ProviderAHost", detailsList.get(0).getHost());
+        Assert.assertEquals(1000, detailsList.get(0).getPort());
+    }
+
+    @After
+    public void after() throws IOException {
+        server.stop();
+    }
+}
diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/resources/log4j2.xml b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..c9eec4f
--- /dev/null
+++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/resources/log4j2.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.
+  ~
+  -->
+
+<Configuration status="info">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout charset="UTF-8" pattern="%d - %c -%-4r [%t] %-5p %x - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="info">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/oap-server/server-cluster-plugin/pom.xml b/oap-server/server-cluster-plugin/pom.xml
new file mode 100644
index 0000000..408fca6
--- /dev/null
+++ b/oap-server/server-cluster-plugin/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>oap-server</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>server-cluster-plugin</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>cluster-zookeeper-plugin</module>
+        <module>cluster-standalone-plugin</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>library-module</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>library-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-core/core-cluster/pom.xml b/oap-server/server-core/core-cluster/pom.xml
new file mode 100644
index 0000000..c41d739
--- /dev/null
+++ b/oap-server/server-core/core-cluster/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.skywalking</groupId>
+        <artifactId>server-core</artifactId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>core-cluster</artifactId>
+    <packaging>jar</packaging>
+
+</project>
\ No newline at end of file
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ClusterModule.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ClusterModule.java
index 45cd3e5..992ed10 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ClusterModule.java
@@ -16,43 +16,22 @@
  *
  */
 
+package org.apache.skywalking.oap.server.core.cluster;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.apache.skywalking.oap.server.library.module.ModuleDefine;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
+public class ClusterModule extends ModuleDefine {
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
+    public static final String NAME = "cluster";
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    @Override public String name() {
+        return NAME;
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    @Override public Class[] services() {
+        return new Class[] {ModuleRegister.class, ModuleQuery.class};
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/InstanceDetails.java
similarity index 53%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/InstanceDetails.java
index 45cd3e5..a4f8dc2 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/InstanceDetails.java
@@ -16,43 +16,38 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.core.cluster;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
+public class InstanceDetails {
 
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
+    private String host;
+    private int port;
+    private String contextPath;
 
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
+    public String getHost() {
+        return host;
     }
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
+    public void setHost(String host) {
+        this.host = host;
     }
 
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
+    public int getPort() {
+        return port;
     }
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
+    public void setPort(int port) {
+        this.port = port;
     }
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    public String getContextPath() {
+        return contextPath;
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public void setContextPath(String contextPath) {
+        this.contextPath = contextPath;
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ModuleQuery.java
similarity index 52%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ModuleQuery.java
index 45cd3e5..b3a4746 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ModuleQuery.java
@@ -16,43 +16,15 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
+package org.apache.skywalking.oap.server.core.cluster;
 
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.apache.skywalking.oap.server.library.module.Service;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+public interface ModuleQuery extends Service {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
-    }
+    List<InstanceDetails> query(String moduleName, String providerName) throws ServiceRegisterException;
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ModuleRegister.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ModuleRegister.java
index 45cd3e5..e3cdb0e 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ModuleRegister.java
@@ -16,43 +16,15 @@
  *
  */
 
+package org.apache.skywalking.oap.server.core.cluster;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.apache.skywalking.oap.server.library.module.Service;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+public interface ModuleRegister extends Service {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
-    }
+    void register(String moduleName, String providerName,
+        InstanceDetails instanceDetails) throws ServiceRegisterException;
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ServiceRegisterException.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ServiceRegisterException.java
index 45cd3e5..901c606 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-core/core-cluster/src/main/java/org/apache/skywalking/oap/server/core/cluster/ServiceRegisterException.java
@@ -16,43 +16,14 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.core.cluster;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+public class ServiceRegisterException extends Exception {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public ServiceRegisterException(String message) {
+        super(message);
     }
 }
diff --git a/oap-server/server-core/core-cluster/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine b/oap-server/server-core/core-cluster/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
new file mode 100644
index 0000000..0810065
--- /dev/null
+++ b/oap-server/server-core/core-cluster/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
@@ -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.skywalking.oap.server.core.cluster.ClusterModule
\ No newline at end of file
diff --git a/oap-server/server-core/pom.xml b/oap-server/server-core/pom.xml
new file mode 100644
index 0000000..37ad39c
--- /dev/null
+++ b/oap-server/server-core/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>oap-server</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>server-core</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>core-cluster</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>library-module</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>library-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-library/library-module/pom.xml b/oap-server/server-library/library-module/pom.xml
new file mode 100644
index 0000000..beeaa10
--- /dev/null
+++ b/oap-server/server-library/library-module/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>server-library</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>library-module</artifactId>
+    <packaging>jar</packaging>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ApplicationConfiguration.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ApplicationConfiguration.java
new file mode 100644
index 0000000..ca685e9
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ApplicationConfiguration.java
@@ -0,0 +1,92 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+import java.util.*;
+
+/**
+ * Modularization configurations. The {@link ModuleManager} is going to start, lookup, start modules based on this.
+ *
+ * @author wu-sheng, peng-yongsheng
+ */
+public class ApplicationConfiguration {
+
+    private final Map<String, ModuleConfiguration> modules = new HashMap<>();
+
+    public String[] moduleList() {
+        return modules.keySet().toArray(new String[0]);
+    }
+
+    public ModuleConfiguration addModule(String moduleName) {
+        ModuleConfiguration newModule = new ModuleConfiguration();
+        modules.put(moduleName, newModule);
+        return newModule;
+    }
+
+    public boolean has(String moduleName) {
+        return modules.containsKey(moduleName);
+    }
+
+    public ModuleConfiguration getModuleConfiguration(String name) {
+        return modules.get(name);
+    }
+
+    /**
+     * The configurations about a certain module.
+     */
+    public class ModuleConfiguration {
+        private final Map<String, ProviderConfiguration> providers = new HashMap<>();
+
+        private ModuleConfiguration() {
+        }
+
+        public Properties getProviderConfiguration(String name) {
+            return providers.get(name).getProperties();
+        }
+
+        public boolean has(String name) {
+            return providers.containsKey(name);
+        }
+
+        public String[] providerList() {
+            return providers.keySet().toArray(new String[0]);
+        }
+
+        public ModuleConfiguration addProviderConfiguration(String name, Properties properties) {
+            ProviderConfiguration newProvider = new ProviderConfiguration(properties);
+            providers.put(name, newProvider);
+            return this;
+        }
+    }
+
+    /**
+     * The configuration about a certain provider of a module.
+     */
+    public class ProviderConfiguration {
+        private Properties properties;
+
+        ProviderConfiguration(Properties properties) {
+            this.properties = properties;
+        }
+
+        private Properties getProperties() {
+            return properties;
+        }
+    }
+}
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/DuplicateProviderException.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/DuplicateProviderException.java
new file mode 100644
index 0000000..bf9c0c4
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/DuplicateProviderException.java
@@ -0,0 +1,25 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+public class DuplicateProviderException extends Exception {
+    public DuplicateProviderException(String message) {
+        super(message);
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleConfig.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleConfig.java
index 45cd3e5..08b5fcf 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleConfig.java
@@ -16,43 +16,10 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
-
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
-    }
+public abstract class ModuleConfig {
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleConfigException.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleConfigException.java
index 45cd3e5..79ee829 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleConfigException.java
@@ -16,43 +16,18 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
+public class ModuleConfigException extends Exception {
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    public ModuleConfigException(String message) {
+        super(message);
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public ModuleConfigException(String message, Throwable cause) {
+        super(message, cause);
     }
 }
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleDefine.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleDefine.java
new file mode 100644
index 0000000..7772102
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleDefine.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.module;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import org.slf4j.*;
+
+/**
+ * A module definition.
+ *
+ * @author wu-sheng, peng-yongsheng
+ */
+public abstract class ModuleDefine {
+
+    private static final Logger logger = LoggerFactory.getLogger(ModuleDefine.class);
+
+    private ModuleProvider moduleProvider;
+
+    /**
+     * @return the module name
+     */
+    public abstract String name();
+
+    /**
+     * @return the {@link Service} provided by this module.
+     */
+    public abstract Class[] services();
+
+    /**
+     * Run the prepare stage for the module, including finding all potential providers, and asking them to prepare.
+     *
+     * @param moduleManager of this module
+     * @param configuration of this module
+     * @throws ProviderNotFoundException when even don't find a single one providers.
+     */
+    void prepare(ModuleManager moduleManager,
+        ApplicationConfiguration.ModuleConfiguration configuration) throws ProviderNotFoundException, ServiceNotProvidedException, ModuleConfigException {
+        ServiceLoader<ModuleProvider> moduleProviderLoader = ServiceLoader.load(ModuleProvider.class);
+        if (configuration.providerList().length != 1) {
+            throw new ModuleConfigException("Just a single provider configuration allowed to open in one module.");
+        }
+
+        boolean providerExist = false;
+        for (ModuleProvider provider : moduleProviderLoader) {
+            if (!configuration.has(provider.name())) {
+                continue;
+            }
+
+            providerExist = true;
+            if (provider.module().equals(getClass())) {
+                try {
+                    moduleProvider = provider.getClass().newInstance();
+                } catch (InstantiationException | IllegalAccessException e) {
+                    throw new ProviderNotFoundException(e);
+                }
+                moduleProvider.setManager(moduleManager);
+                moduleProvider.setModule(this);
+            }
+        }
+
+        if (!providerExist) {
+            throw new ProviderNotFoundException(this.name() + " module no provider exists.");
+        }
+
+        logger.info("Prepare the {} provider in {} module.", moduleProvider.name(), this.name());
+        try {
+            copyProperties(moduleProvider.createConfigBeanIfAbsent(), configuration.getProviderConfiguration(moduleProvider.name()), this.name(), moduleProvider.name());
+        } catch (IllegalAccessException e) {
+            throw new ModuleConfigException(this.name() + " module config transport to config bean failure.", e);
+        }
+        moduleProvider.prepare();
+    }
+
+    private void copyProperties(ModuleConfig dest, Properties src, String moduleName,
+        String providerName) throws IllegalAccessException {
+        Enumeration<?> propertyNames = src.propertyNames();
+        while (propertyNames.hasMoreElements()) {
+            String propertyName = (String)propertyNames.nextElement();
+            Class<? extends ModuleConfig> destClass = dest.getClass();
+
+            try {
+                Field field = getDeclaredField(destClass, propertyName);
+                field.setAccessible(true);
+                field.set(dest, src.get(propertyName));
+            } catch (NoSuchFieldException e) {
+                logger.warn(propertyName + " setting is not supported in " + providerName + " provider of " + moduleName + " module");
+            }
+        }
+    }
+
+    private Field getDeclaredField(Class<?> destClass, String fieldName) throws NoSuchFieldException {
+        if (destClass != null) {
+            Field[] fields = destClass.getDeclaredFields();
+            for (Field field : fields) {
+                if (field.getName().equals(fieldName)) {
+                    return field;
+                }
+            }
+            return getDeclaredField(destClass.getSuperclass(), fieldName);
+        }
+
+        throw new NoSuchFieldException();
+    }
+
+    final ModuleProvider provider() {
+        return moduleProvider;
+    }
+
+    public final <T extends Service> T getService(Class<T> serviceType) throws ServiceNotProvidedRuntimeException {
+        try {
+            return provider().getService(serviceType);
+        } catch (ServiceNotProvidedException e) {
+            throw new ServiceNotProvidedRuntimeException(e.getMessage());
+        }
+    }
+}
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleManager.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleManager.java
new file mode 100644
index 0000000..00d1f44
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleManager.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.module;
+
+import java.util.*;
+
+/**
+ * The <code>ModuleManager</code> takes charge of all {@link ModuleDefine}s in collector.
+ *
+ * @author wu-sheng, peng-yongsheng
+ */
+public class ModuleManager {
+    private boolean isInPrepareStage = true;
+    private final Map<String, ModuleDefine> loadedModules = new HashMap<>();
+
+    /**
+     * Init the given modules
+     */
+    public void init(
+        ApplicationConfiguration applicationConfiguration) throws ModuleNotFoundException, ProviderNotFoundException, ServiceNotProvidedException, ModuleConfigException, DuplicateProviderException, ModuleStartException {
+        String[] moduleNames = applicationConfiguration.moduleList();
+        ServiceLoader<ModuleDefine> moduleServiceLoader = ServiceLoader.load(ModuleDefine.class);
+        List<String> moduleList = new LinkedList<>(Arrays.asList(moduleNames));
+        for (ModuleDefine module : moduleServiceLoader) {
+            for (String moduleName : moduleNames) {
+                if (moduleName.equals(module.name())) {
+                    ModuleDefine newInstance;
+                    try {
+                        newInstance = module.getClass().newInstance();
+                    } catch (InstantiationException | IllegalAccessException e) {
+                        throw new ModuleNotFoundException(e);
+                    }
+
+                    newInstance.prepare(this, applicationConfiguration.getModuleConfiguration(moduleName));
+                    loadedModules.put(moduleName, newInstance);
+                    moduleList.remove(moduleName);
+                }
+            }
+        }
+        // Finish prepare stage
+        isInPrepareStage = false;
+
+        if (moduleList.size() > 0) {
+            throw new ModuleNotFoundException(moduleList.toString() + " missing.");
+        }
+
+        for (ModuleDefine module : loadedModules.values()) {
+            module.provider().start();
+            module.provider().notifyAfterCompleted();
+        }
+    }
+
+    public boolean has(String moduleName) {
+        return loadedModules.get(moduleName) != null;
+    }
+
+    public ModuleDefine find(String moduleName) throws ModuleNotFoundRuntimeException {
+        assertPreparedStage();
+        ModuleDefine module = loadedModules.get(moduleName);
+        if (module != null)
+            return module;
+        throw new ModuleNotFoundRuntimeException(moduleName + " missing.");
+    }
+
+    private void assertPreparedStage() {
+        if (isInPrepareStage) {
+            throw new AssertionError("Still in preparing stage.");
+        }
+    }
+}
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleNotFoundException.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleNotFoundException.java
new file mode 100644
index 0000000..3ca8e68
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleNotFoundException.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.module;
+
+public class ModuleNotFoundException extends Exception {
+
+    public ModuleNotFoundException(Throwable cause) {
+        super(cause);
+    }
+
+    public ModuleNotFoundException(String message) {
+        super(message);
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleNotFoundRuntimeException.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleNotFoundRuntimeException.java
index 45cd3e5..2ca0c0c 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleNotFoundRuntimeException.java
@@ -16,43 +16,14 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+public class ModuleNotFoundRuntimeException extends RuntimeException {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public ModuleNotFoundRuntimeException(String message) {
+        super(message);
     }
 }
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleProvider.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleProvider.java
new file mode 100644
index 0000000..f7d4b51
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleProvider.java
@@ -0,0 +1,131 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+import java.util.*;
+
+/**
+ * The <code>ModuleProvider</code> is an implementation of a {@link ModuleDefine}.
+ *
+ * And each module can have one or more implementation, which depends on `application.yml`
+ *
+ * @author wu-sheng, peng-yongsheng
+ */
+public abstract class ModuleProvider {
+    private ModuleManager manager;
+    private ModuleDefine module;
+    private Map<Class<? extends Service>, Service> services = new HashMap<>();
+
+    public ModuleProvider() {
+    }
+
+    void setManager(ModuleManager manager) {
+        this.manager = manager;
+    }
+
+    void setModule(ModuleDefine module) {
+        this.module = module;
+    }
+
+    protected final ModuleManager getManager() {
+        return manager;
+    }
+
+    /**
+     * @return the name of this provider.
+     */
+    public abstract String name();
+
+    /**
+     * @return the module name
+     */
+    public abstract Class module();
+
+    /**
+     * @return ModuleConfig
+     */
+    public abstract ModuleConfig createConfigBeanIfAbsent();
+
+    /**
+     * In prepare stage, the module should initialize things which are irrelative other modules.
+     */
+    public abstract void prepare() throws ServiceNotProvidedException;
+
+    /**
+     * In start stage, the module has been ready for interop.
+     */
+    public abstract void start() throws ServiceNotProvidedException, ModuleStartException;
+
+    /**
+     * This callback executes after all modules start up successfully.
+     */
+    public abstract void notifyAfterCompleted() throws ServiceNotProvidedException;
+
+    /**
+     * Register a implementation for the service of this module provider.
+     */
+    protected final void registerServiceImplementation(Class<? extends Service> serviceType,
+        Service service) throws ServiceNotProvidedException {
+        if (serviceType.isInstance(service)) {
+            this.services.put(serviceType, service);
+        } else {
+            throw new ServiceNotProvidedException(serviceType + " is not implemented by " + service);
+        }
+    }
+
+    /**
+     * Make sure all required services have been implemented.
+     *
+     * @param requiredServices must be implemented by the module.
+     * @throws ServiceNotProvidedException when exist unimplemented service.
+     */
+    void requiredCheck(Class<? extends Service>[] requiredServices) throws ServiceNotProvidedException {
+        if (requiredServices == null)
+            return;
+
+        for (Class<? extends Service> service : requiredServices) {
+            if (!services.containsKey(service)) {
+                throw new ServiceNotProvidedException("Service:" + service.getName() + " not provided");
+            }
+        }
+
+        if (requiredServices.length != services.size()) {
+            throw new ServiceNotProvidedException("The " + this.name() + " provider in " + module.name() + " module provide more service implementations than ModuleDefine requirements.");
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends Service> T getService(
+        Class<T> serviceType) throws ServiceNotProvidedException {
+        Service serviceImpl = services.get(serviceType);
+        if (serviceImpl != null) {
+            return (T)serviceImpl;
+        }
+
+        throw new ServiceNotProvidedException("Service " + serviceType.getName() + " should not be provided, based on module define.");
+    }
+
+    ModuleDefine getModule() {
+        return module;
+    }
+
+    String getModuleName() {
+        return module.name();
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleStartException.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleStartException.java
index 45cd3e5..010cb65 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ModuleStartException.java
@@ -16,43 +16,14 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+public class ModuleStartException extends Exception {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public ModuleStartException(String message, Throwable cause) {
+        super(message, cause);
     }
 }
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ProviderNotFoundException.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ProviderNotFoundException.java
new file mode 100644
index 0000000..63d45a0
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ProviderNotFoundException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+public class ProviderNotFoundException extends Exception {
+    public ProviderNotFoundException(String message) {
+        super(message);
+    }
+
+    public ProviderNotFoundException(Throwable e) {
+        super(e);
+    }
+}
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/Service.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/Service.java
new file mode 100644
index 0000000..18547ce
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/Service.java
@@ -0,0 +1,29 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+/**
+ * The <code>Service</code> implementation is a service provided by its own modules.
+ *
+ * And every {@link ModuleProvider} must provide all the given services of the {@link ModuleDefine}.
+ *
+ * @author wu-sheng
+ */
+public interface Service {
+}
\ No newline at end of file
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ServiceNotProvidedException.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ServiceNotProvidedException.java
new file mode 100644
index 0000000..4ebfe45
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ServiceNotProvidedException.java
@@ -0,0 +1,25 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+public class ServiceNotProvidedException extends Exception {
+    public ServiceNotProvidedException(String message) {
+        super(message);
+    }
+}
diff --git a/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ServiceNotProvidedRuntimeException.java b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ServiceNotProvidedRuntimeException.java
new file mode 100644
index 0000000..0135376
--- /dev/null
+++ b/oap-server/server-library/library-module/src/main/java/org/apache/skywalking/oap/server/library/module/ServiceNotProvidedRuntimeException.java
@@ -0,0 +1,25 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+public class ServiceNotProvidedRuntimeException extends RuntimeException {
+    public ServiceNotProvidedRuntimeException(String message) {
+        super(message);
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ApplicationConfigurationTestCase.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ApplicationConfigurationTestCase.java
new file mode 100644
index 0000000..ad9a532
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ApplicationConfigurationTestCase.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.module;
+
+import java.util.Properties;
+import org.junit.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class ApplicationConfigurationTestCase {
+
+    @Test
+    public void test() {
+        ApplicationConfiguration configuration = new ApplicationConfiguration();
+        Properties providerAConfig = new Properties();
+        providerAConfig.setProperty("A-key1", "A-value1");
+        providerAConfig.setProperty("A-key2", "A-value2");
+        Properties providerBConfig = new Properties();
+        providerBConfig.setProperty("B-key1", "B-value1");
+        providerBConfig.setProperty("B-key2", "B-value2");
+
+        final String module = "Module";
+        final String providerA = "ProviderA";
+        final String providerB = "ProviderB";
+        configuration.addModule(module)
+            .addProviderConfiguration(providerA, providerAConfig)
+            .addProviderConfiguration(providerB, providerBConfig);
+
+        Assert.assertArrayEquals(new String[] {module}, configuration.moduleList());
+        Assert.assertTrue(configuration.has(module));
+        Assert.assertFalse(configuration.has("ModuleB"));
+
+        Assert.assertTrue(configuration.getModuleConfiguration(module).has(providerA));
+        Assert.assertFalse(configuration.getModuleConfiguration(module).has("ProviderC"));
+
+        Assert.assertEquals("B-value1", configuration.getModuleConfiguration(module).getProviderConfiguration(providerB).getProperty("B-key1"));
+        Assert.assertEquals(providerAConfig, configuration.getModuleConfiguration(module).getProviderConfiguration(providerA));
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/BaseModuleA.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/BaseModuleA.java
index 45cd3e5..ebf50a2 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/BaseModuleA.java
@@ -16,43 +16,28 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
- * @author peng-yongsheng
+ * @author wu-sheng, peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
+public class BaseModuleA extends ModuleDefine {
 
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
+    static final String NAME = "BaseModuleA";
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
+    @Override public String name() {
+        return NAME;
     }
 
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
+    @Override public Class[] services() {
+        return new Class[] {ServiceABusiness1.class, ServiceABusiness2.class};
     }
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
+    public interface ServiceABusiness1 extends Service {
+        void print();
     }
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+    public interface ServiceABusiness2 extends Service {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/BaseModuleB.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/BaseModuleB.java
index 45cd3e5..1f56a87 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/BaseModuleB.java
@@ -16,43 +16,28 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
- * @author peng-yongsheng
+ * @author wu-sheng
  */
-public class CollectionUtils {
+public class BaseModuleB extends ModuleDefine {
 
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
+    static final String NAME = "BaseModuleB";
 
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
+    @Override public String name() {
+        return NAME;
     }
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
+    @Override public Class[] services() {
+        return new Class[] {BaseModuleB.ServiceBBusiness1.class, BaseModuleB.ServiceBBusiness2.class};
     }
 
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
+    public interface ServiceBBusiness1 extends Service {
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
     }
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
+    public interface ServiceBBusiness2 extends Service {
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
     }
 }
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleABusiness1Impl.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleABusiness1Impl.java
new file mode 100644
index 0000000..7938877
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleABusiness1Impl.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.skywalking.oap.server.library.module;
+
+/**
+ * @author wu-sheng
+ */
+public class ModuleABusiness1Impl implements BaseModuleA.ServiceABusiness1 {
+
+    @Override public void print() {
+    }
+}
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleABusiness2Impl.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleABusiness2Impl.java
new file mode 100644
index 0000000..cd95957
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleABusiness2Impl.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.module;
+
+/**
+ * @author wu-sheng
+ */
+public class ModuleABusiness2Impl implements BaseModuleA.ServiceABusiness2 {
+
+}
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleAProvider.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleAProvider.java
new file mode 100644
index 0000000..52c3b78
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleAProvider.java
@@ -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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.module;
+
+/**
+ * @author wu-sheng, peng-yongsheng
+ */
+public class ModuleAProvider extends ModuleProvider {
+
+    static final String NAME = "ModuleAProvider";
+
+    private ModuleConfig config;
+
+    @Override public String name() {
+        return NAME;
+    }
+
+    @Override public ModuleConfig createConfigBeanIfAbsent() {
+        if (config == null) {
+            config = new Config();
+        }
+        return config;
+    }
+
+    @Override public Class<? extends ModuleDefine> module() {
+        return BaseModuleA.class;
+    }
+
+    @Override public void prepare() throws ServiceNotProvidedException {
+        this.registerServiceImplementation(BaseModuleA.ServiceABusiness1.class, new ModuleABusiness1Impl());
+        this.registerServiceImplementation(BaseModuleA.ServiceABusiness2.class, new ModuleABusiness2Impl());
+    }
+
+    @Override public void start() {
+    }
+
+    @Override public void notifyAfterCompleted() {
+    }
+
+    public class Config extends ModuleConfig {
+        private String host;
+
+        public String getHost() {
+            return host;
+        }
+    }
+}
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBBusiness1Impl.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBBusiness1Impl.java
new file mode 100644
index 0000000..c2fef6d
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBBusiness1Impl.java
@@ -0,0 +1,25 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+/**
+ * @author wu-sheng
+ */
+public class ModuleBBusiness1Impl implements BaseModuleB.ServiceBBusiness1 {
+}
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBBusiness2Impl.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBBusiness2Impl.java
new file mode 100644
index 0000000..92551e5
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBBusiness2Impl.java
@@ -0,0 +1,25 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+/**
+ * @author wu-sheng
+ */
+public class ModuleBBusiness2Impl implements BaseModuleB.ServiceBBusiness2 {
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBProvider.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBProvider.java
index 45cd3e5..5bc2e61 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleBProvider.java
@@ -16,43 +16,38 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
- * @author peng-yongsheng
+ * @author wu-sheng, peng-yongsheng
  */
-public class CollectionUtils {
+public class ModuleBProvider extends ModuleProvider {
+
+    static final String NAME = "ModuleBProvider";
 
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
+    @Override public String name() {
+        return NAME;
     }
 
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
+    @Override public ModuleConfig createConfigBeanIfAbsent() {
+        return null;
     }
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
+    @Override public Class<? extends ModuleDefine> module() {
+        return BaseModuleB.class;
     }
 
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
+    @Override public void prepare() throws ServiceNotProvidedException {
+        this.registerServiceImplementation(BaseModuleB.ServiceBBusiness1.class, new ModuleBBusiness1Impl());
+        this.registerServiceImplementation(BaseModuleB.ServiceBBusiness2.class, new ModuleBBusiness2Impl());
     }
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
+    @Override public void start() {
     }
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    @Override public void notifyAfterCompleted() {
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    class Config {
     }
 }
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleManagerTestCase.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleManagerTestCase.java
new file mode 100644
index 0000000..210d807
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/ModuleManagerTestCase.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.module;
+
+import java.util.Properties;
+import org.junit.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class ModuleManagerTestCase {
+
+    private ApplicationConfiguration configuration;
+
+    @Before
+    public void init() {
+        Properties providerAConfig = new Properties();
+        providerAConfig.setProperty("host", "oap");
+        providerAConfig.setProperty("A-key1", "A-value1");
+        providerAConfig.setProperty("A-key2", "A-value2");
+
+        configuration = new ApplicationConfiguration();
+        configuration.addModule(TestModule.NAME).addProviderConfiguration(TestModuleProvider.NAME, new Properties());
+        configuration.addModule(BaseModuleA.NAME).addProviderConfiguration(ModuleAProvider.NAME, providerAConfig);
+        configuration.addModule(BaseModuleB.NAME).addProviderConfiguration(ModuleBProvider.NAME, new Properties());
+    }
+
+    @Test
+    public void testHas() throws ModuleNotFoundException, ModuleConfigException, ServiceNotProvidedException, ProviderNotFoundException, ModuleStartException, DuplicateProviderException {
+        ModuleManager manager = new ModuleManager();
+        manager.init(configuration);
+
+        Assert.assertTrue(manager.has(TestModule.NAME));
+        Assert.assertTrue(manager.has(BaseModuleA.NAME));
+        Assert.assertTrue(manager.has(BaseModuleB.NAME));
+
+        Assert.assertFalse(manager.has("Undefined"));
+    }
+
+    @Test
+    public void testFind() throws ModuleNotFoundException, ModuleConfigException, ServiceNotProvidedException, ProviderNotFoundException, ModuleStartException, DuplicateProviderException {
+        ModuleManager manager = new ModuleManager();
+        manager.init(configuration);
+
+        try {
+            manager.find("Undefined");
+        } catch (ModuleNotFoundRuntimeException e) {
+            Assert.assertEquals("Undefined missing.", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testInit() throws ServiceNotProvidedException, DuplicateProviderException, ModuleConfigException, ModuleNotFoundException, ProviderNotFoundException, ModuleStartException {
+        ModuleManager manager = new ModuleManager();
+        manager.init(configuration);
+        BaseModuleA.ServiceABusiness1 serviceABusiness1 = manager.find(BaseModuleA.NAME).provider().getService(BaseModuleA.ServiceABusiness1.class);
+        Assert.assertNotNull(serviceABusiness1);
+
+        ModuleAProvider.Config config = (ModuleAProvider.Config)manager.find(BaseModuleA.NAME).provider().createConfigBeanIfAbsent();
+        Assert.assertEquals("oap", config.getHost());
+    }
+
+    @Test
+    public void testAssertPreparedStage() {
+        ModuleManager manager = new ModuleManager();
+
+        try {
+            manager.find("Undefined");
+        } catch (AssertionError e) {
+            Assert.assertEquals("Still in preparing stage.", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testEmptyConfig() throws ModuleConfigException, ServiceNotProvidedException, ProviderNotFoundException, ModuleStartException, DuplicateProviderException {
+        configuration.addModule("Undefined").addProviderConfiguration("Undefined", new Properties());
+
+        ModuleManager manager = new ModuleManager();
+
+        try {
+            manager.init(configuration);
+        } catch (ModuleNotFoundException e) {
+            Assert.assertEquals("[Undefined] missing.", e.getMessage());
+        }
+    }
+}
diff --git a/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/TestModule.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/TestModule.java
new file mode 100644
index 0000000..76added
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/TestModule.java
@@ -0,0 +1,35 @@
+/*
+ * 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.skywalking.oap.server.library.module;
+
+/**
+ * @author wu-sheng, peng-yongsheng
+ */
+public class TestModule extends ModuleDefine {
+
+    static final String NAME = "TestModule";
+
+    @Override public String name() {
+        return NAME;
+    }
+
+    @Override public Class[] services() {
+        return new Class[0];
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/TestModuleProvider.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/TestModuleProvider.java
index 45cd3e5..ecbc380 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-module/src/test/java/org/apache/skywalking/oap/server/library/module/TestModuleProvider.java
@@ -16,43 +16,36 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.module;
 
 /**
- * @author peng-yongsheng
+ * @author wu-sheng
  */
-public class CollectionUtils {
+public class TestModuleProvider extends ModuleProvider {
+
+    static final String NAME = "TestModuleProvider";
 
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
+    @Override public String name() {
+        return NAME;
     }
 
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
+    @Override public Class<? extends ModuleDefine> module() {
+        return TestModule.class;
     }
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
+    @Override public ModuleConfig createConfigBeanIfAbsent() {
+        return null;
     }
 
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
+    @Override public void prepare() {
     }
 
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
+    @Override public void start() {
     }
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    @Override public void notifyAfterCompleted() {
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    class Config {
     }
 }
diff --git a/oap-server/server-library/library-module/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine b/oap-server/server-library/library-module/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
new file mode 100644
index 0000000..67a6e24
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+org.apache.skywalking.oap.server.library.module.TestModule
+org.apache.skywalking.oap.server.library.module.BaseModuleA
+org.apache.skywalking.oap.server.library.module.BaseModuleB
\ No newline at end of file
diff --git a/oap-server/server-library/library-module/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-library/library-module/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..8efb813
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+org.apache.skywalking.oap.server.library.module.TestModuleProvider
+org.apache.skywalking.oap.server.library.module.ModuleAProvider
+org.apache.skywalking.oap.server.library.module.ModuleBProvider
\ No newline at end of file
diff --git a/oap-server/server-library/library-module/src/test/resources/log4j2.xml b/oap-server/server-library/library-module/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..c9eec4f
--- /dev/null
+++ b/oap-server/server-library/library-module/src/test/resources/log4j2.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.
+  ~
+  -->
+
+<Configuration status="info">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout charset="UTF-8" pattern="%d - %c -%-4r [%t] %-5p %x - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="info">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/oap-server/server-library/library-util/pom.xml b/oap-server/server-library/library-util/pom.xml
new file mode 100644
index 0000000..6f3ca2c
--- /dev/null
+++ b/oap-server/server-library/library-util/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>server-library</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>library-util</artifactId>
+    <packaging>jar</packaging>
+</project>
\ No newline at end of file
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/CollectionUtils.java
similarity index 92%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/CollectionUtils.java
index 45cd3e5..58e68a6 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/CollectionUtils.java
@@ -17,11 +17,9 @@
  */
 
 
-package org.apache.skywalking.apm.collector.core.util;
+package org.apache.skywalking.oap.server.library.util;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * @author peng-yongsheng
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/ResourceUtils.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/ResourceUtils.java
index 45cd3e5..4994939 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/ResourceUtils.java
@@ -16,43 +16,22 @@
  *
  */
 
+package org.apache.skywalking.oap.server.library.util;
 
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.io.*;
+import java.net.URL;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
-
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+public class ResourceUtils {
+
+    public static Reader read(String fileName) throws FileNotFoundException {
+        URL url = ResourceUtils.class.getClassLoader().getResource(fileName);
+        if (url == null) {
+            throw new FileNotFoundException("file not found: " + fileName);
+        }
+        InputStream inputStream = ResourceUtils.class.getClassLoader().getResourceAsStream(fileName);
+        return new InputStreamReader(inputStream);
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/StringUtils.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/StringUtils.java
index 45cd3e5..34d84ca 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/StringUtils.java
@@ -16,43 +16,20 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.library.util;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
+public class StringUtils {
 
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
+    public static final String EMPTY_STRING = "";
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    public static boolean isEmpty(Object str) {
+        return str == null || EMPTY_STRING.equals(str);
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public static boolean isNotEmpty(Object str) {
+        return !isEmpty(str);
     }
 }
diff --git a/oap-server/server-library/pom.xml b/oap-server/server-library/pom.xml
new file mode 100644
index 0000000..863ca99
--- /dev/null
+++ b/oap-server/server-library/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>oap-server</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>server-library</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>library-module</module>
+        <module>library-util</module>
+    </modules>
+
+</project>
\ No newline at end of file
diff --git a/oap-server/server-starter/pom.xml b/oap-server/server-starter/pom.xml
new file mode 100644
index 0000000..a0599ce
--- /dev/null
+++ b/oap-server/server-starter/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>oap-server</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.0.0-alpha-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>server-starter</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>cluster-standalone-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>cluster-zookeeper-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>library-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/OAPBootStartUp.java b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/OAPBootStartUp.java
new file mode 100644
index 0000000..0bcf6ba
--- /dev/null
+++ b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/OAPBootStartUp.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 org.apache.skywalking.oap.server.starter;
+
+import java.util.concurrent.TimeUnit;
+import org.apache.skywalking.oap.server.library.module.*;
+import org.apache.skywalking.oap.server.starter.config.*;
+import org.slf4j.*;
+
+/**
+ * @author peng-yongsheng
+ */
+public class OAPBootStartUp {
+
+    private static final Logger logger = LoggerFactory.getLogger(OAPBootStartUp.class);
+
+    public static void main(String[] args) {
+        ApplicationConfigLoader configLoader = new ApplicationConfigLoader();
+        ModuleManager manager = new ModuleManager();
+        try {
+            ApplicationConfiguration applicationConfiguration = configLoader.load();
+            manager.init(applicationConfiguration);
+        } catch (ConfigFileNotFoundException | ModuleNotFoundException | ProviderNotFoundException | ServiceNotProvidedException | ModuleConfigException | ModuleStartException | DuplicateProviderException e) {
+            logger.error(e.getMessage(), e);
+            System.exit(1);
+        }
+
+        try {
+            TimeUnit.MINUTES.sleep(5);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ApplicationConfigLoader.java b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ApplicationConfigLoader.java
new file mode 100644
index 0000000..4c40ae8
--- /dev/null
+++ b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ApplicationConfigLoader.java
@@ -0,0 +1,128 @@
+/*
+ * 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.skywalking.oap.server.starter.config;
+
+import java.io.*;
+import java.util.*;
+import org.apache.skywalking.oap.server.library.module.ApplicationConfiguration;
+import org.apache.skywalking.oap.server.library.util.*;
+import org.slf4j.*;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * Initialize collector settings with following sources.
+ * Use application.yml as primary setting,
+ * and fix missing setting by default settings in application-default.yml.
+ *
+ * At last, override setting by system.properties and system.envs if the key matches moduleName.provideName.settingKey.
+ *
+ * @author peng-yongsheng, wusheng
+ */
+public class ApplicationConfigLoader implements ConfigLoader<ApplicationConfiguration> {
+
+    private static final Logger logger = LoggerFactory.getLogger(ApplicationConfigLoader.class);
+
+    private final Yaml yaml = new Yaml();
+
+    @Override public ApplicationConfiguration load() throws ConfigFileNotFoundException {
+        ApplicationConfiguration configuration = new ApplicationConfiguration();
+        this.loadConfig(configuration);
+        this.overrideConfigBySystemEnv(configuration);
+        return configuration;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void loadConfig(ApplicationConfiguration configuration) throws ConfigFileNotFoundException {
+        try {
+            Reader applicationReader = ResourceUtils.read("application.yml");
+            Map<String, Map<String, Map<String, ?>>> moduleConfig = yaml.loadAs(applicationReader, Map.class);
+            if (CollectionUtils.isNotEmpty(moduleConfig)) {
+                moduleConfig.forEach((moduleName, providerConfig) -> {
+                    if (providerConfig.size() > 0) {
+                        logger.info("Get a module define from application.yml, module name: {}", moduleName);
+                        ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.addModule(moduleName);
+                        providerConfig.forEach((name, propertiesConfig) -> {
+                            logger.info("Get a provider define belong to {} module, provider name: {}", moduleName, name);
+                            Properties properties = new Properties();
+                            if (propertiesConfig != null) {
+                                propertiesConfig.forEach((key, value) -> {
+                                    properties.put(key, value);
+                                    logger.info("The property with key: {}, value: {}, in {} provider", key, value, name);
+                                });
+                            }
+                            moduleConfiguration.addProviderConfiguration(name, properties);
+                        });
+                    } else {
+                        logger.warn("Get a module define from application.yml, but no provider define, use default, module name: {}", moduleName);
+                    }
+                });
+            }
+        } catch (FileNotFoundException e) {
+            throw new ConfigFileNotFoundException(e.getMessage(), e);
+        }
+    }
+
+    private void overrideConfigBySystemEnv(ApplicationConfiguration configuration) {
+        for (Map.Entry<Object, Object> prop : System.getProperties().entrySet()) {
+            overrideModuleSettings(configuration, prop.getKey().toString(), prop.getValue().toString());
+        }
+    }
+
+    private void overrideModuleSettings(ApplicationConfiguration configuration, String key, String value) {
+        int moduleAndConfigSeparator = key.indexOf('.');
+        if (moduleAndConfigSeparator <= 0) {
+            return;
+        }
+        String moduleName = key.substring(0, moduleAndConfigSeparator);
+        String providerSettingSubKey = key.substring(moduleAndConfigSeparator + 1);
+        ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.getModuleConfiguration(moduleName);
+        if (moduleConfiguration == null) {
+            return;
+        }
+        int providerAndConfigSeparator = providerSettingSubKey.indexOf('.');
+        if (providerAndConfigSeparator <= 0) {
+            return;
+        }
+        String providerName = providerSettingSubKey.substring(0, providerAndConfigSeparator);
+        String settingKey = providerSettingSubKey.substring(providerAndConfigSeparator + 1);
+        if (!moduleConfiguration.has(providerName)) {
+            return;
+        }
+        Properties providerSettings = moduleConfiguration.getProviderConfiguration(providerName);
+        if (!providerSettings.containsKey(settingKey)) {
+            return;
+        }
+        Object originValue = providerSettings.get(settingKey);
+        Class<?> type = originValue.getClass();
+        if (type.equals(int.class) || type.equals(Integer.class))
+            providerSettings.put(settingKey, Integer.valueOf(value));
+        else if (type.equals(String.class))
+            providerSettings.put(settingKey, value);
+        else if (type.equals(long.class) || type.equals(Long.class))
+            providerSettings.put(settingKey, Long.valueOf(value));
+        else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
+            providerSettings.put(settingKey, Boolean.valueOf(value));
+        } else {
+            return;
+        }
+
+        logger.info("The setting has been override by key: {}, value: {}, in {} provider of {} module through {}",
+            settingKey, value, providerName, moduleName, "System.properties");
+    }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ConfigFileNotFoundException.java
similarity index 51%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ConfigFileNotFoundException.java
index 45cd3e5..1c79e03 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ConfigFileNotFoundException.java
@@ -16,43 +16,18 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.starter.config;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
+public class ConfigFileNotFoundException extends Exception {
 
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
+    public ConfigFileNotFoundException(String message) {
+        super(message);
     }
 
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
+    public ConfigFileNotFoundException(String message, Throwable cause) {
+        super(message, cause);
     }
 }
diff --git a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ConfigLoader.java
similarity index 50%
copy from apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
copy to oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ConfigLoader.java
index 45cd3e5..790afa8 100644
--- a/apm-collector/apm-collector-core/src/main/java/org/apache/skywalking/apm/collector/core/util/CollectionUtils.java
+++ b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ConfigLoader.java
@@ -16,43 +16,11 @@
  *
  */
 
-
-package org.apache.skywalking.apm.collector.core.util;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+package org.apache.skywalking.oap.server.starter.config;
 
 /**
  * @author peng-yongsheng
  */
-public class CollectionUtils {
-
-    public static boolean isEmpty(Map map) {
-        return map == null || map.size() == 0;
-    }
-
-    public static boolean isEmpty(List list) {
-        return list == null || list.size() == 0;
-    }
-
-    public static boolean isEmpty(Set set) {
-        return set == null || set.size() == 0;
-    }
-
-    public static boolean isNotEmpty(List list) {
-        return !isEmpty(list);
-    }
-
-    public static boolean isNotEmpty(Set set) {
-        return !isEmpty(set);
-    }
-
-    public static boolean isNotEmpty(Map map) {
-        return !isEmpty(map);
-    }
-
-    public static <T> boolean isNotEmpty(T[] array) {
-        return array != null && array.length > 0;
-    }
+public interface ConfigLoader<T> {
+    T load() throws ConfigFileNotFoundException;
 }
diff --git a/oap-server/server-starter/src/main/resources/application.yml b/oap-server/server-starter/src/main/resources/application.yml
new file mode 100644
index 0000000..bfe498a
--- /dev/null
+++ b/oap-server/server-starter/src/main/resources/application.yml
@@ -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.
+
+cluster:
+  zookeeper:
+    hostPort: localhost:2181
+    # Retry Policy
+    baseSleepTimeMs: 1000 # initial amount of time to wait between retries
+    maxRetries: 3 # max number of times to retry
+#naming:
+#  jetty:
+#    #OS real network IP(binding required), for agent to find collector cluster
+#    host: localhost
+#    port: 10800
+#    contextPath: /
\ No newline at end of file
diff --git a/oap-server/server-starter/src/main/resources/log4j2.xml b/oap-server/server-starter/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..6697ebf
--- /dev/null
+++ b/oap-server/server-starter/src/main/resources/log4j2.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<Configuration status="info">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout charset="UTF-8" pattern="%d - %c -%-4r [%t] %-5p %x - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <logger name="org.eclipse.jetty" level="INFO"/>
+        <logger name="org.apache.zookeeper" level="INFO"/>
+        <logger name="org.elasticsearch.common.network.IfConfig" level="INFO"/>
+        <logger name="org.apache.skywalking.apm.collector.agent.grpc.provider.handler.JVMMetricsServiceHandler" level="INFO"/>
+        <logger name="org.apache.skywalking.apm.collector.analysis.worker.timer.PersistenceTimer" level="INFO"/>
+        <logger name="io.grpc.netty" level="INFO"/>
+        <Root level="info">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/pom.xml b/pom.xml
index dffe2ad..7a56ef7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,8 @@
   ~
   -->
 
-<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">
+<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.skywalking</groupId>
@@ -58,6 +59,7 @@
     </developers>
 
     <modules>
+        <module>oap-server</module>
         <module>apm-commons</module>
         <module>apm-sniffer</module>
         <module>apm-application-toolkit</module>
@@ -119,29 +121,54 @@
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
-            <version>4.12</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-all</artifactId>
-            <version>1.10.19</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.powermock</groupId>
             <artifactId>powermock-module-junit4</artifactId>
-            <version>${powermock.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.powermock</groupId>
             <artifactId>powermock-api-mockito</artifactId>
-            <version>${powermock.version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>junit</groupId>
+                <artifactId>junit</artifactId>
+                <version>4.12</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.mockito</groupId>
+                <artifactId>mockito-all</artifactId>
+                <version>1.10.19</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.powermock</groupId>
+                <artifactId>powermock-module-junit4</artifactId>
+                <version>${powermock.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.powermock</groupId>
+                <artifactId>powermock-api-mockito</artifactId>
+                <version>${powermock.version}</version>
+                <scope>test</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
     <build>
         <plugins>
             <plugin>
@@ -299,6 +326,11 @@
                         <artifactId>apm-checkstyle</artifactId>
                         <version>5.0.0-beta</version>
                     </dependency>
+                    <dependency>
+                        <groupId>com.puppycrawl.tools</groupId>
+                        <artifactId>checkstyle</artifactId>
+                        <version>8.11</version>
+                    </dependency>
                 </dependencies>
                 <executions>
                     <execution>