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

[servicecomb-service-center] branch master updated: SCB-2094 Move plugin/discovery, registry package (#722)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new de446fc  SCB-2094 Move plugin/discovery,registry package (#722)
de446fc is described below

commit de446fc1e0ec54e898aaf25a04e8c8c5a7b7e3eb
Author: little-cui <su...@qq.com>
AuthorDate: Wed Oct 28 15:45:37 2020 +0800

    SCB-2094 Move plugin/discovery,registry package (#722)
    
    * SCB-2094 Move plugin/discovery,registry package
    
    * SCB-2094 Refactor service/plugin pkg
    
    * SCB-2094 Remove REGISTRY/DISCOVERY plugin
    
    * SCB-2094 Refactor server/plugin pkg
    
    * SCB-2094 Remove REGISTRY/DISCOVERY plugin
    
    * SCB-2094 Add SCManager API
    
    * SCB-2094 Rename pkg
    
    * SCB-2094 Refactor KV store pkg
    
    * SCB-2094 Refactor etcd pkg
    
    * SCB-2094 Remove plugin/discovery & registry pkg
    
    * SCB-2094 Fix UT failures
    
    * SCB-2094 Fix UT failures
    
    * SCB-2094 Fix golint error
---
 .github/workflows/golangci-lint.yml                |   2 +-
 client/apis.go                                     |   2 +-
 datasource/datasource.go                           |   1 +
 pkg/cache/cache.go => datasource/engine.go         |  35 +-
 datasource/etcd/account.go                         |  48 +-
 datasource/etcd/account_test.go                    |  20 +-
 .../etcd/bootstrap/bootstrap.go                    |  39 +-
 .../etcd/client}/buildin/buildin.go                |  19 +-
 datasource/etcd/client/client.go                   | 156 +++++
 datasource/etcd/client/client_test.go              |  79 +++
 .../discovery => datasource/etcd/client}/common.go |  44 +-
 datasource/etcd/client/config.go                   |  76 +++
 .../etcd/client/embedded}/embededetcd.go           | 124 ++--
 .../etcd/client/lease_task.go                      |  14 +-
 .../etcd/client/lease_task_test.go                 |  15 +-
 datasource/etcd/client/manager.go                  |  81 +++
 .../registry => datasource/etcd/client}/metrics.go |   2 +-
 .../option.go => datasource/etcd/client/options.go |  51 +-
 .../etcd/client/remote}/common.go                  |   2 +-
 .../etcd => datasource/etcd/client/remote}/etcd.go | 170 ++---
 .../etcd/client/remote}/etcd_test.go               | 455 ++++++------
 .../etcd/client/remote}/logger.go                  |   2 +-
 .../etcd/client/remote}/logger_test.go             |   2 +-
 .../etcd/client/remote}/tracing.go                 |  13 +-
 .../registry => datasource/etcd/client}/types.go   |  42 +-
 datasource/etcd/config.go                          |  71 ++
 datasource/etcd/dep.go                             |  11 +-
 datasource/etcd/dep_test.go                        |  78 +--
 datasource/etcd/engine.go                          | 256 +++++++
 .../etcd/engine_test.go                            |  79 +--
 datasource/etcd/etcd.go                            |  93 ++-
 datasource/etcd/etcd_suite_test.go                 |  24 +-
 datasource/etcd/job/job.go                         |  62 ++
 datasource/etcd/key_generator_test.go              |   9 +-
 .../core/backend => datasource/etcd/kv}/addon.go   |  12 +-
 .../etcd/kv/instance_event_handler.go              |  24 +-
 .../etcd/kv/instance_event_handler_test.go         |  74 +-
 datasource/etcd/kv/kv.go                           | 198 ++++++
 datasource/etcd/kv/kv_test.go                      | 101 +++
 datasource/etcd/kv/types.go                        |  96 +++
 datasource/etcd/ms.go                              | 316 ++++-----
 datasource/etcd/ms_test.go                         | 759 +++++++--------------
 {server => datasource/etcd}/mux/mux.go             |   0
 .../etcd/sd}/aggregate/adaptor.go                  |  36 +-
 .../etcd/sd}/aggregate/cache.go                    |  32 +-
 .../etcd/sd}/aggregate/common.go                   |   0
 .../etcd/sd}/aggregate/conflict_checker.go         |  20 +-
 .../etcd/sd}/aggregate/indexer.go                  |  40 +-
 .../etcd/sd}/aggregate/repo.go                     |  14 +-
 .../discovery => datasource/etcd/sd}/cache.go      |   3 +-
 .../discovery => datasource/etcd/sd}/cache_kv.go   |   3 +-
 .../discovery => datasource/etcd/sd}/cache_null.go |   3 +-
 .../discovery => datasource/etcd/sd}/cache_test.go |   3 +-
 .../discovery => datasource/etcd/sd}/cacher.go     |  34 +-
 .../etcd/sd}/cacher_test.go                        |  32 +-
 .../discovery => datasource/etcd/sd}/common.go     |   3 +-
 .../discovery => datasource/etcd/sd}/config.go     |   3 +-
 .../etcd/sd}/config_test.go                        |  32 +-
 .../discovery => datasource/etcd/sd}/defer.go      |   3 +-
 .../discovery => datasource/etcd/sd}/discovery.go  |   7 +-
 .../etcd/sd}/etcd/adaptor.go                       |  27 +-
 .../etcd/sd}/etcd/adaptor_test.go                  |  13 +-
 .../etcd/sd}/etcd/cacher_kv.go                     |  80 +--
 .../etcd/sd}/etcd/cacher_kv_test.go                |  55 +-
 .../etcd/sd}/etcd/common.go                        |   6 +-
 .../etcd/sd}/etcd/indexer_cache.go                 |  19 +-
 .../etcd/sd}/etcd/indexer_etcd.go                  |  24 +-
 .../etcd/sd}/etcd/indexer_test.go                  |  59 +-
 .../etcd/sd}/etcd/listwatch.go                     |   7 +-
 .../etcd/sd}/etcd/listwatch_inner.go               |  19 +-
 .../etcd/sd}/etcd/listwatch_test.go                |  17 +-
 .../etcd/sd}/etcd/metrics.go                       |   1 +
 .../etcd/sd}/etcd/metrics_test.go                  |   1 +
 .../common.go => datasource/etcd/sd/etcd/repo.go   |  27 +-
 .../etcd/sd}/etcd/watcher.go                       |   5 +-
 .../etcd/sd}/etcd/watcher_inner.go                 |  13 +-
 .../etcd/sd}/etcd/watcher_test.go                  |  18 +-
 .../etcd/sd}/event_proxy.go                        |   3 +-
 .../etcd/sd}/event_proxy_test.go                   |  14 +-
 .../discovery => datasource/etcd/sd}/indexer.go    |   9 +-
 .../etcd/sd}/indexer_cache.go                      |  17 +-
 .../etcd/sd}/indexer_test.go                       |  48 +-
 .../etcd/sd}/k8s/adaptor/adaptor.go                |  22 +-
 .../etcd/sd}/k8s/adaptor/cacher.go                 |  14 +-
 .../etcd/sd}/k8s/adaptor/cacher_index.go           |   6 +-
 .../etcd/sd}/k8s/adaptor/cacher_instance.go        |  16 +-
 .../etcd/sd}/k8s/adaptor/cacher_service.go         |   6 +-
 .../etcd/sd}/k8s/adaptor/common.go                 |   3 +-
 .../etcd/sd}/k8s/adaptor/convertor.go              |  12 +-
 .../etcd/sd}/k8s/adaptor/kube_client.go            |   0
 .../etcd/sd}/k8s/adaptor/listwatcher.go            |   0
 .../discovery => datasource/etcd/sd}/k8s/nok8s.go  |   0
 .../discovery => datasource/etcd/sd}/k8s/repo.go   |  11 +-
 datasource/{ => etcd/sd}/manager.go                |  43 +-
 .../schema_util_test.go => sd/manager_test.go}     |  27 +-
 .../discovery => datasource/etcd/sd}/metrics.go    |   3 +-
 .../auth/auth.go => datasource/etcd/sd/options.go  |  11 +-
 .../discovery => datasource/etcd/sd}/service.go    |   3 +-
 .../etcd/sd}/servicecenter/adaptor.go              |  30 +-
 .../etcd/sd}/servicecenter/aggregate.go            |  47 +-
 .../etcd/sd}/servicecenter/aggregate_test.go       |   6 +-
 .../etcd/sd}/servicecenter/cacher.go               |  10 +-
 .../etcd/sd}/servicecenter/common.go               |   0
 .../etcd/sd}/servicecenter/indexer.go              |  40 +-
 .../etcd/sd/servicecenter/repo.go                  |  23 +-
 .../etcd/sd}/servicecenter/syncer.go               |  54 +-
 .../etcd/sd}/servicecenter/syncer_test.go          | 104 +--
 .../discovery => datasource/etcd/sd}/types.go      |  40 +-
 .../etcd/sd/types_test.go                          |  46 +-
 datasource/etcd/system.go                          |  26 +-
 datasource/etcd/system_test.go                     |  23 +-
 datasource/etcd/util.go                            | 109 ++-
 datasource/etcd/util/dependency.go                 |  47 +-
 datasource/etcd/util/dependency_query.go           |  44 +-
 datasource/etcd/util/dependency_test.go            |  66 +-
 datasource/etcd/util/dependency_util.go            |  82 +--
 datasource/etcd/util/domain_util.go                |  34 +-
 datasource/etcd/util/domain_util_test.go           |   3 +-
 datasource/etcd/util/heartbeat_util.go             |   9 +-
 datasource/etcd/util/heartbeat_util_test.go        |   5 +-
 datasource/etcd/util/instance_util.go              |  78 +--
 datasource/etcd/util/instance_util_test.go         |   9 +-
 datasource/etcd/util/microservice_util.go          |  87 ++-
 datasource/etcd/util/rule_util.go                  |  26 +-
 datasource/etcd/util/rule_util_test.go             |  11 +-
 datasource/etcd/util/schema_util.go                |   9 +-
 datasource/etcd/util/schema_util_test.go           |   3 +-
 datasource/etcd/util/tag_util.go                   |  18 +-
 datasource/etcd/util/tag_util_test.go              |   3 +-
 datasource/etcd/util/util.go                       |  12 +-
 datasource/etcd/util/util_suite_test.go            |  30 +-
 datasource/etcd/util/versionrule.go                |  26 +-
 datasource/etcd/util/versionrule_test.go           |  36 +-
 datasource/etcd/version.go                         | 102 +++
 datasource/manager.go                              |  13 +-
 datasource/manager_test.go                         |   6 +-
 {server/core/backend => datasource}/metrics.go     |   2 +-
 datasource/ms.go                                   |   3 +-
 datasource/options.go                              |   8 +-
 pkg/cache/cache.go                                 |   5 +-
 pkg/etcdsync/mutex.go                              |  37 +-
 pkg/etcdsync/mutex_test.go                         |  10 +-
 pkg/registry/struct.go                             |   9 +
 pkg/task/service.go                                |   4 +
 server/api.go                                      |  27 +-
 server/bootstrap/bootstrap.go                      |  32 +-
 server/broker/service.go                           |  60 +-
 server/broker/service_test.go                      |  22 +-
 server/broker/store.go                             |  74 +-
 server/broker/util.go                              |  78 ++-
 server/core/backend/common.go                      |  95 ---
 server/core/backend/discovery.go                   | 231 -------
 server/core/backend/discovery_test.go              | 164 -----
 server/core/backend/registry.go                    | 256 -------
 server/core/microservice.go                        |   4 +-
 server/core/proto/common.go                        |  10 +-
 server/core/proto/parser.go                        |  16 +-
 server/core/proto/parser_test.go                   |   8 +-
 server/core/proto/{services.pb.go => service.go}   |   4 +-
 server/core/proto/{services.go => service_ex.go}   |   1 +
 server/handler/auth/auth.go                        |   4 +-
 server/handler/tracing/tracing.go                  |   6 +-
 server/notify/publisher.go                         |   4 +
 server/notify/stream.go                            |  35 +-
 server/notify/stream_test.go                       |   3 +-
 server/notify/websocket.go                         |  34 +-
 server/notify/websocket_test.go                    |  33 +-
 server/plugin/auditlog/auditlog.go                 |  11 +-
 server/plugin/auth/auth.go                         |  13 +-
 server/plugin/auth/buildin/buidlin_test.go         |  12 +-
 server/plugin/auth/buildin/buildin.go              |   3 +-
 server/plugin/common.go                            |   4 +-
 server/plugin/discovery/etcd/repo.go               |  44 --
 server/plugin/discovery/servicecenter/repo.go      |  43 --
 server/plugin/discovery/types_test.go              |  49 --
 server/plugin/export.go                            |  69 --
 server/plugin/plugin.go                            |  54 +-
 server/plugin/plugin_test.go                       |  22 +-
 server/plugin/quota/buildin/buildin.go             |   6 +-
 server/plugin/quota/buildin/common.go              |  30 +-
 server/plugin/quota/buildin/counter.go             |  16 +-
 server/plugin/quota/buildin/counter_test.go        |  26 +-
 server/plugin/quota/counter/counter.go             |  10 +-
 server/plugin/quota/counter/event.go               |  28 +-
 server/plugin/quota/counter/event_test.go          | 102 +--
 server/plugin/quota/quota.go                       |  11 +
 server/plugin/quota/unlimit/unlimit.go             |   2 +-
 server/plugin/registry/common.go                   |  67 --
 server/plugin/registry/config.go                   | 113 ---
 server/plugin/registry/registry.go                 |  42 --
 .../security/{ => cipher}/buildin/buildin.go       |   7 +-
 .../{service => plugin/security}/cipher/cipher.go  |  11 +-
 .../{tls => security/tlsconf}/buildin/buildin.go   |   7 +-
 .../tls.go => security/tlsconf/buildin/tlsconf.go} |   2 +-
 .../tlsconf/buildin/tlsconf_test.go}               |   6 +-
 .../{tls/tls.go => security/tlsconf/tlsconf.go}    |  20 +-
 server/plugin/tracing/pzipkin/buildin.go           |   2 +-
 server/plugin/tracing/pzipkin/buildin_test.go      |   4 +-
 server/plugin/tracing/tracing.go                   |  31 +-
 server/plugin/types.go                             |  27 +-
 server/plugin/uuid/buildin/buildin.go              |   7 +-
 server/plugin/uuid/context/context.go              |   2 +-
 server/plugin/uuid/uuid.go                         |  12 +-
 server/rest/admin/service.go                       |  41 +-
 server/rest/admin/service_test.go                  |  10 +-
 server/rest/controller/rest_util.go                |   4 +-
 server/rest/controller/v3/main_controller.go       |   2 +-
 server/rest/controller/v4/instance_controller.go   |   2 +-
 server/rest/controller/v4/main_controller.go       |   2 +-
 server/rest/govern/govern_suite_test.go            |   7 +-
 server/rest/govern/service.go                      |  60 +-
 server/rest/govern/service_test.go                 |  32 +-
 server/rest/server.go                              |   4 +-
 server/server.go                                   | 157 +----
 server/service/cache/common.go                     |  28 +
 server/service/cache/filter_consistency.go         |   4 +-
 server/service/cache/filter_instances.go           |  34 +-
 server/service/cache/filter_permission.go          |   2 +-
 server/service/cache/filter_tags.go                |   2 +-
 server/service/cache/filter_version.go             |   2 +-
 server/service/dependency.go                       |  17 +-
 server/service/dependency_test.go                  | 112 +--
 server/service/dependency_validator.go             |   2 +-
 server/service/event/dependency_event_handler.go   |  33 +-
 .../service/event/dependency_rule_event_handler.go |  11 +-
 .../event/dependency_rule_event_handler_test.go    |  12 +-
 server/service/event/domain_event_handler.go       |  11 +-
 server/service/event/event.go                      |  19 +-
 server/service/event/instance_event_handler.go     |  17 +-
 server/service/event/rule_event_handler.go         |  17 +-
 .../service/event/schema_summary_event_handler.go  |  11 +-
 server/service/event/service_event_handler.go      |  13 +-
 server/service/event/tag_event_handler.go          |  17 +-
 server/service/instance.go                         |  57 +-
 server/service/instance_test.go                    | 234 +++----
 server/service/kv/store.go                         |  90 ---
 server/service/kv/store_test.go                    |  73 --
 server/service/lock/datasource.go                  |  20 -
 server/service/lock/etcd/etcd.go                   | 210 ------
 server/service/lock/etcd/etcd_test.go              |  57 --
 server/service/lock/manager.go                     |  58 --
 server/service/lock/options.go                     |  22 -
 server/service/microservice.go                     | 139 ++--
 server/service/microservice_test.go                |  98 +--
 server/service/microservice_validator.go           |   2 +-
 server/service/rbac/dao/account_dao.go             |  18 +-
 server/service/rbac/dao/account_dao_test.go        |  11 +-
 server/service/rbac/rbac.go                        |   2 +-
 server/service/rule.go                             |  62 +-
 server/service/rule_test.go                        |  82 +--
 server/service/schema.go                           | 115 ++--
 server/service/schema_test.go                      | 162 ++---
 server/service/service_suite_test.go               |   6 +-
 server/service/tag.go                              |  26 +-
 server/service/tag_test.go                         |  72 +-
 server/service/util/dependency.go                  | 128 ----
 server/service/util/dependency_query.go            | 363 ----------
 server/service/util/dependency_test.go             | 292 --------
 server/service/util/dependency_util.go             | 513 --------------
 server/service/util/domain_util.go                 | 125 ----
 server/service/util/domain_util_test.go            |  83 ---
 server/service/util/heartbeat_util.go              |  51 --
 server/service/util/instance_util.go               | 274 --------
 server/service/util/instance_util_test.go          | 169 -----
 server/service/util/microservice_util.go           | 308 ---------
 server/service/util/rule_util.go                   | 298 --------
 server/service/util/rule_util_test.go              | 304 ---------
 server/service/util/schema_util.go                 |  35 -
 server/service/util/schema_util_test.go            |  29 -
 server/service/util/tag_util.go                    |  65 --
 server/service/util/tag_util_test.go               |  36 -
 server/service/util/util.go                        |  37 -
 server/service/util/util_suite_test.go             | 138 ----
 server/service/util/versionrule.go                 | 262 -------
 server/service/util/versionrule_test.go            | 384 -----------
 server/service/watch.go                            |   4 +-
 server/service/watch_test.go                       |   2 +-
 server/task/clear_service.go                       | 123 ----
 server/version.go                                  |  58 --
 279 files changed, 4915 insertions(+), 9662 deletions(-)

diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index 162d9f8..9b3cb12 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -10,4 +10,4 @@ jobs:
         uses: golangci/golangci-lint-action@v1
         with:
           version: v1.27
-          args: --timeout=5m --skip-dirs=server/core/proto,test,pkg/cache,server/plugin/discovery,server/service/event,server/service/util,server/bootstrap,server/notify,server/rest/controller/v3,server/broker/brokerpb,examples,syncer,frontend,scctl,integration,pkg/registry --out-format=colored-line-number --enable golint,gocyclo --skip-files=.*_test.go$
\ No newline at end of file
+          args: --timeout=5m --skip-dirs='test,pkg/registry,.*/controller/(v3|v4)$,.*/bootstrap$,server/broker/brokerpb,examples,syncer,frontend,scctl,integration' --out-format=colored-line-number --enable golint,gocyclo --skip-files=.*_test.go$
\ No newline at end of file
diff --git a/client/apis.go b/client/apis.go
index ffb811a..809c7f7 100644
--- a/client/apis.go
+++ b/client/apis.go
@@ -35,7 +35,7 @@ const (
 	apiClustersURL = "/v4/default/admin/clusters"
 	apiHealthURL   = "/v4/default/registry/health"
 
-	QueryGlobal = "global"
+	QueryGlobal util.CtxKey = "global"
 )
 
 func (c *Client) toError(body []byte) *scerr.Error {
diff --git a/datasource/datasource.go b/datasource/datasource.go
index 4b76556..4b9dac8 100644
--- a/datasource/datasource.go
+++ b/datasource/datasource.go
@@ -23,4 +23,5 @@ type DataSource interface {
 	AccountManager
 	DependencyManager
 	MetadataManager
+	SCManager
 }
diff --git a/pkg/cache/cache.go b/datasource/engine.go
similarity index 65%
copy from pkg/cache/cache.go
copy to datasource/engine.go
index c32cf98..07fd03f 100644
--- a/pkg/cache/cache.go
+++ b/datasource/engine.go
@@ -15,33 +15,20 @@
  * limitations under the License.
  */
 
-package cache
+package datasource
 
 import (
 	"context"
-	"sync"
+	"github.com/apache/servicecomb-service-center/pkg/types"
+	"time"
 )
 
-type Cache struct {
-	data context.Context
-	lock sync.RWMutex
-}
-
-func (c *Cache) Set(k string, v interface{}) {
-	c.lock.Lock()
-	c.data = context.WithValue(c.data, k, v)
-	c.lock.Unlock()
-}
-
-func (c *Cache) Get(k string) (v interface{}) {
-	c.lock.RLock()
-	v = c.data.Value(k)
-	c.lock.RUnlock()
-	return
-}
-
-func NewCache() *Cache {
-	return &Cache{
-		data: context.Background(),
-	}
+// SCManager contains the APIs of registration of SC itself
+type SCManager interface {
+	SelfRegister(ctx context.Context) error
+	SelfUnregister(ctx context.Context) error
+	// OPS
+	ClearNoInstanceServices(ctx context.Context, ttl time.Duration) error
+	UpgradeVersion(ctx context.Context) error
+	GetClusters(ctx context.Context) (types.Clusters, error)
 }
diff --git a/datasource/etcd/account.go b/datasource/etcd/account.go
index 486b6b4..5791bee 100644
--- a/datasource/etcd/account.go
+++ b/datasource/etcd/account.go
@@ -18,16 +18,16 @@ package etcd
 import (
 	"context"
 	"encoding/json"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/kv"
 	utils "github.com/apache/servicecomb-service-center/datasource/etcd/util"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/rbacframe"
-	"github.com/apache/servicecomb-service-center/server/core/backend"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 )
 
 func (ds *DataSource) AccountExist(ctx context.Context, key string) (bool, error) {
-	resp, err := backend.Registry().Do(ctx, registry.GET,
-		registry.WithStrKey(GenerateETCDAccountKey(key)))
+	resp, err := client.Instance().Do(ctx, client.GET,
+		client.WithStrKey(GenerateETCDAccountKey(key)))
 	if err != nil {
 		return false, err
 	}
@@ -38,13 +38,13 @@ func (ds *DataSource) AccountExist(ctx context.Context, key string) (bool, error
 }
 
 func (ds *DataSource) GetAccount(ctx context.Context, key string) (*rbacframe.Account, error) {
-	resp, err := backend.Registry().Do(ctx, registry.GET,
-		registry.WithStrKey(GenerateETCDAccountKey(key)))
+	resp, err := client.Instance().Do(ctx, client.GET,
+		client.WithStrKey(GenerateETCDAccountKey(key)))
 	if err != nil {
 		return nil, err
 	}
 	if resp.Count != 1 {
-		return nil, ErrNotUnique
+		return nil, client.ErrNotUnique
 	}
 	account := &rbacframe.Account{}
 	err = json.Unmarshal(resp.Kvs[0].Value, account)
@@ -55,8 +55,8 @@ func (ds *DataSource) GetAccount(ctx context.Context, key string) (*rbacframe.Ac
 	return account, nil
 }
 func (ds *DataSource) ListAccount(ctx context.Context, key string) ([]*rbacframe.Account, int64, error) {
-	resp, err := backend.Registry().Do(ctx, registry.GET,
-		registry.WithStrKey(GenerateETCDAccountKey(key)), registry.WithPrefix())
+	resp, err := client.Instance().Do(ctx, client.GET,
+		client.WithStrKey(GenerateETCDAccountKey(key)), client.WithPrefix())
 	if err != nil {
 		return nil, 0, err
 	}
@@ -74,8 +74,8 @@ func (ds *DataSource) ListAccount(ctx context.Context, key string) ([]*rbacframe
 	return accounts, resp.Count, nil
 }
 func (ds *DataSource) DeleteAccount(ctx context.Context, key string) (bool, error) {
-	resp, err := backend.Registry().Do(ctx, registry.DEL,
-		registry.WithStrKey(GenerateETCDAccountKey(key)))
+	resp, err := client.Instance().Do(ctx, client.DEL,
+		client.WithStrKey(GenerateETCDAccountKey(key)))
 	if err != nil {
 		return false, err
 	}
@@ -87,15 +87,15 @@ func (ds *DataSource) UpdateAccount(ctx context.Context, key string, account *rb
 		log.Errorf(err, "account info is invalid")
 		return err
 	}
-	_, err = backend.Registry().Do(ctx, registry.PUT,
-		registry.WithStrKey(GenerateETCDAccountKey(key)),
-		registry.WithValue(value))
+	_, err = client.Instance().Do(ctx, client.PUT,
+		client.WithStrKey(GenerateETCDAccountKey(key)),
+		client.WithValue(value))
 	return err
 }
 
 func (ds *DataSource) AddDomain(ctx context.Context, domain string) (bool, error) {
-	ok, err := backend.Registry().PutNoOverride(ctx,
-		registry.WithStrKey(GenerateETCDDomainKey(domain)))
+	ok, err := client.Instance().PutNoOverride(ctx,
+		client.WithStrKey(GenerateETCDDomainKey(domain)))
 	if err != nil {
 		return false, err
 	}
@@ -104,9 +104,9 @@ func (ds *DataSource) AddDomain(ctx context.Context, domain string) (bool, error
 
 func (ds *DataSource) DomainExist(ctx context.Context, domain string) (bool, error) {
 	opts := append(utils.FromContext(ctx),
-		registry.WithStrKey(GenerateETCDDomainKey(domain)),
-		registry.WithCountOnly())
-	rsp, err := backend.Store().Domain().Search(ctx, opts...)
+		client.WithStrKey(GenerateETCDDomainKey(domain)),
+		client.WithCountOnly())
+	rsp, err := kv.Store().Domain().Search(ctx, opts...)
 	if err != nil {
 		return false, err
 	}
@@ -114,8 +114,8 @@ func (ds *DataSource) DomainExist(ctx context.Context, domain string) (bool, err
 }
 
 func (ds *DataSource) AddProject(ctx context.Context, domain, project string) (bool, error) {
-	ok, err := backend.Registry().PutNoOverride(ctx,
-		registry.WithStrKey(GenerateETCDProjectKey(domain, project)))
+	ok, err := client.Instance().PutNoOverride(ctx,
+		client.WithStrKey(GenerateETCDProjectKey(domain, project)))
 	if err != nil {
 		return ok, err
 	}
@@ -124,9 +124,9 @@ func (ds *DataSource) AddProject(ctx context.Context, domain, project string) (b
 
 func (ds *DataSource) ProjectExist(ctx context.Context, domain, project string) (bool, error) {
 	opts := append(utils.FromContext(ctx),
-		registry.WithStrKey(GenerateETCDProjectKey(domain, project)),
-		registry.WithCountOnly())
-	rsp, err := backend.Store().Project().Search(ctx, opts...)
+		client.WithStrKey(GenerateETCDProjectKey(domain, project)),
+		client.WithCountOnly())
+	rsp, err := kv.Store().Project().Search(ctx, opts...)
 	if err != nil {
 		return false, err
 	}
diff --git a/datasource/etcd/account_test.go b/datasource/etcd/account_test.go
index 7487015..4bbb3e3 100644
--- a/datasource/etcd/account_test.go
+++ b/datasource/etcd/account_test.go
@@ -1,13 +1,9 @@
-package etcd
+package etcd_test
 
 import (
 	"context"
 	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/pkg/rbacframe"
-	mgr "github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery/etcd"
-	etcd2 "github.com/apache/servicecomb-service-center/server/plugin/registry/etcd"
-	"github.com/apache/servicecomb-service-center/server/plugin/tracing/pzipkin"
 	"github.com/astaxie/beego"
 	"github.com/stretchr/testify/assert"
 	"testing"
@@ -34,20 +30,6 @@ var (
 
 func init() {
 	beego.AppConfig.Set("registry_plugin", "etcd")
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.REGISTRY, Name: "etcd", New: etcd2.NewRegistry})
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.DISCOVERY, Name: "buildin", New: etcd.NewRepository})
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.DISCOVERY, Name: "etcd", New: etcd.NewRepository})
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.TRACING, Name: "buildin", New: pzipkin.New})
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: "etcd",
-	})
-	if err != nil {
-		panic("failed to register etcd auth plugin")
-	}
 }
 
 func TestAccount(t *testing.T) {
diff --git a/server/mux/mux.go b/datasource/etcd/bootstrap/bootstrap.go
similarity index 51%
copy from server/mux/mux.go
copy to datasource/etcd/bootstrap/bootstrap.go
index c4f9d79..bef6cd6 100644
--- a/server/mux/mux.go
+++ b/datasource/etcd/bootstrap/bootstrap.go
@@ -15,34 +15,21 @@
  * limitations under the License.
  */
 
-package mux
+package bootstrap
 
-import (
-	"github.com/apache/servicecomb-service-center/pkg/etcdsync"
-	"reflect"
-	"unsafe"
-)
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd"
 
-type Type string
+//registry is buildin
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/client/buildin"
 
-func (m *Type) String() (s string) {
-	pMT := (*reflect.StringHeader)(unsafe.Pointer(m))
-	pStr := (*reflect.StringHeader)(unsafe.Pointer(&s))
-	pStr.Data = pMT.Data
-	pStr.Len = pMT.Len
-	return
-}
+//registry etcd
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/client/remote"
 
-const (
-	GlobalLock       Type = "/cse-sr/lock/global"
-	DepQueueLock     Type = "/cse-sr/lock/dep-queue"
-	ServiceClearLock Type = "/cse-sr/lock/service-clear"
-)
+//registry etcd
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/client/embedded"
 
-func Lock(t Type) (*etcdsync.DLock, error) {
-	return etcdsync.Lock(t.String(), -1, true)
-}
-
-func Try(t Type) (*etcdsync.DLock, error) {
-	return etcdsync.Lock(t.String(), -1, false)
-}
+//discovery
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/sd/aggregate"
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/sd/servicecenter"
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/sd/etcd"
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/sd/k8s"
diff --git a/server/plugin/registry/buildin/buildin.go b/datasource/etcd/client/buildin/buildin.go
similarity index 65%
rename from server/plugin/registry/buildin/buildin.go
rename to datasource/etcd/client/buildin/buildin.go
index 989201f..7d1a910 100644
--- a/server/plugin/registry/buildin/buildin.go
+++ b/datasource/etcd/client/buildin/buildin.go
@@ -19,18 +19,17 @@ package buildin
 
 import (
 	"context"
-	mgr "github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 )
 
 var (
 	closeCh    = make(chan struct{})
-	noResponse = &registry.PluginResponse{}
+	noResponse = &client.PluginResponse{}
 )
 
 func init() {
 	close(closeCh)
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.REGISTRY, Name: "buildin", New: NewRegistry})
+	client.Install("buildin", NewRegistry)
 }
 
 type Registry struct {
@@ -43,16 +42,16 @@ func (ec *Registry) Err() (err <-chan error) {
 func (ec *Registry) Ready() <-chan struct{} {
 	return closeCh
 }
-func (ec *Registry) PutNoOverride(ctx context.Context, opts ...registry.PluginOpOption) (bool, error) {
+func (ec *Registry) PutNoOverride(ctx context.Context, opts ...client.PluginOpOption) (bool, error) {
 	return false, nil
 }
-func (ec *Registry) Do(ctx context.Context, opts ...registry.PluginOpOption) (*registry.PluginResponse, error) {
+func (ec *Registry) Do(ctx context.Context, opts ...client.PluginOpOption) (*client.PluginResponse, error) {
 	return noResponse, nil
 }
-func (ec *Registry) Txn(ctx context.Context, ops []registry.PluginOp) (*registry.PluginResponse, error) {
+func (ec *Registry) Txn(ctx context.Context, ops []client.PluginOp) (*client.PluginResponse, error) {
 	return noResponse, nil
 }
-func (ec *Registry) TxnWithCmp(ctx context.Context, success []registry.PluginOp, cmp []registry.CompareOp, fail []registry.PluginOp) (*registry.PluginResponse, error) {
+func (ec *Registry) TxnWithCmp(ctx context.Context, success []client.PluginOp, cmp []client.CompareOp, fail []client.PluginOp) (*client.PluginResponse, error) {
 	return noResponse, nil
 }
 func (ec *Registry) LeaseGrant(ctx context.Context, TTL int64) (leaseID int64, err error) {
@@ -64,7 +63,7 @@ func (ec *Registry) LeaseRenew(ctx context.Context, leaseID int64) (TTL int64, e
 func (ec *Registry) LeaseRevoke(ctx context.Context, leaseID int64) error {
 	return nil
 }
-func (ec *Registry) Watch(ctx context.Context, opts ...registry.PluginOpOption) error {
+func (ec *Registry) Watch(ctx context.Context, opts ...client.PluginOpOption) error {
 	return nil
 }
 func (ec *Registry) Compact(ctx context.Context, reserve int64) error {
@@ -73,7 +72,7 @@ func (ec *Registry) Compact(ctx context.Context, reserve int64) error {
 func (ec *Registry) Close() {
 }
 
-func NewRegistry() mgr.Instance {
+func NewRegistry(opts client.Options) client.Registry {
 	return &Registry{
 		ready: make(chan int),
 	}
diff --git a/datasource/etcd/client/client.go b/datasource/etcd/client/client.go
new file mode 100644
index 0000000..06ef2ef
--- /dev/null
+++ b/datasource/etcd/client/client.go
@@ -0,0 +1,156 @@
+/*
+ * 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 client
+
+import (
+	"context"
+	"errors"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/apache/servicecomb-service-center/pkg/task"
+	"github.com/coreos/etcd/mvcc/mvccpb"
+)
+
+const (
+	// the same as v3rpc.MaxOpsPerTxn = 128
+	MaxTxnNumberOneTime = 128
+)
+
+var ErrNotUnique = errors.New("kv result is not unique")
+
+type Registry interface {
+	Err() <-chan error
+	Ready() <-chan struct{}
+	PutNoOverride(ctx context.Context, opts ...PluginOpOption) (bool, error)
+	Do(ctx context.Context, opts ...PluginOpOption) (*PluginResponse, error)
+	Txn(ctx context.Context, ops []PluginOp) (*PluginResponse, error)
+	TxnWithCmp(ctx context.Context, success []PluginOp, cmp []CompareOp, fail []PluginOp) (*PluginResponse, error)
+	LeaseGrant(ctx context.Context, TTL int64) (leaseID int64, err error)
+	LeaseRenew(ctx context.Context, leaseID int64) (TTL int64, err error)
+	LeaseRevoke(ctx context.Context, leaseID int64) error
+	// this function block util:
+	// 1. connection error
+	// 2. call send function failed
+	// 3. response.Err()
+	// 4. time out to watch, but return nil
+	Watch(ctx context.Context, opts ...PluginOpOption) error
+	Compact(ctx context.Context, reserve int64) error
+	Close()
+}
+
+//Put put kv
+func Put(ctx context.Context, key string, value string) error {
+	_, err := Instance().Do(ctx, PUT, WithStrKey(key), WithStrValue(value))
+	return err
+}
+
+//Put put kv
+func PutBytes(ctx context.Context, key string, value []byte) error {
+	_, err := Instance().Do(ctx, PUT, WithStrKey(key), WithValue(value))
+	return err
+}
+
+//Get get one kv
+func Get(ctx context.Context, key string) (*mvccpb.KeyValue, error) {
+	resp, err := Instance().Do(ctx, GET, WithStrKey(key))
+	if err != nil {
+		return nil, err
+	}
+	if resp.Count != 1 {
+		return nil, ErrNotUnique
+	}
+	return resp.Kvs[0], err
+}
+
+//List get kv list
+func List(ctx context.Context, key string) ([]*mvccpb.KeyValue, int64, error) {
+	resp, err := Instance().Do(ctx, GET, WithStrKey(key), WithPrefix())
+	if err != nil {
+		return nil, 0, err
+	}
+	return resp.Kvs, resp.Count, nil
+}
+
+//Exist get one kv, if can not get return false
+func Exist(ctx context.Context, key string) (bool, error) {
+	resp, err := Instance().Do(ctx, GET, WithStrKey(key), WithCountOnly())
+	if err != nil {
+		return false, err
+	}
+	if resp.Count == 0 {
+		return false, nil
+	}
+	return true, nil
+}
+
+func Delete(ctx context.Context, key string) (bool, error) {
+	resp, err := Instance().Do(ctx, DEL, WithStrKey(key))
+	if err != nil {
+		return false, err
+	}
+	return resp.Count != 0, nil
+}
+
+func BatchCommit(ctx context.Context, opts []PluginOp) error {
+	_, err := BatchCommitWithCmp(ctx, opts, nil, nil)
+	return err
+}
+
+func BatchCommitWithCmp(ctx context.Context, opts []PluginOp,
+	cmp []CompareOp, fail []PluginOp) (resp *PluginResponse, err error) {
+	lenOpts := len(opts)
+	tmpLen := lenOpts
+	var tmpOpts []PluginOp
+	for i := 0; tmpLen > 0; i++ {
+		tmpLen = lenOpts - (i+1)*MaxTxnNumberOneTime
+		if tmpLen > 0 {
+			tmpOpts = opts[i*MaxTxnNumberOneTime : (i+1)*MaxTxnNumberOneTime]
+		} else {
+			tmpOpts = opts[i*MaxTxnNumberOneTime : lenOpts]
+		}
+		resp, err = Instance().TxnWithCmp(ctx, tmpOpts, cmp, fail)
+		if err != nil || !resp.Succeeded {
+			return
+		}
+	}
+	return
+}
+
+// KeepAlive will always return ok when cache is unavailable
+// unless the cache response is LeaseNotFound
+func KeepAlive(ctx context.Context, opts ...PluginOpOption) (int64, error) {
+	op := OpPut(opts...)
+
+	t := NewLeaseAsyncTask(op)
+	if op.Mode == ModeNoCache {
+		log.Debugf("keep alive lease WitchNoCache, request etcd server, op: %s", op)
+		err := t.Do(ctx)
+		ttl := t.TTL
+		return ttl, err
+	}
+
+	err := task.GetService().Add(ctx, t)
+	if err != nil {
+		return 0, err
+	}
+	itf, err := task.GetService().LatestHandled(t.Key())
+	if err != nil {
+		return 0, err
+	}
+	pt := itf.(*LeaseTask)
+	return pt.TTL, pt.Err()
+}
diff --git a/datasource/etcd/client/client_test.go b/datasource/etcd/client/client_test.go
new file mode 100644
index 0000000..a6326f8
--- /dev/null
+++ b/datasource/etcd/client/client_test.go
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package client
+
+import (
+	"context"
+	"errors"
+	"github.com/apache/servicecomb-service-center/pkg/task"
+	"testing"
+)
+
+var closedCh = make(chan struct{})
+
+func init() {
+	close(closedCh)
+}
+
+type mockAsyncTaskService struct {
+	Task task.Task
+}
+
+func (a *mockAsyncTaskService) Run()                   {}
+func (a *mockAsyncTaskService) Stop()                  {}
+func (a *mockAsyncTaskService) Ready() <-chan struct{} { return closedCh }
+func (a *mockAsyncTaskService) Add(ctx context.Context, task task.Task) error {
+	switch task.Key() {
+	case "LeaseAsyncTask_error":
+		return errors.New("error")
+	}
+	return nil
+}
+func (a *mockAsyncTaskService) LatestHandled(key string) (task.Task, error) {
+	switch a.Task.Key() {
+	case key:
+		return a.Task, nil
+	}
+	return nil, errors.New("error")
+}
+
+func TestKeepAlive(t *testing.T) {
+	tt := NewLeaseAsyncTask(OpGet())
+	tt.TTL = 1
+	task.RegisterService(&mockAsyncTaskService{Task: tt})
+
+	// KeepAlive case: add task error
+	ttl, err := KeepAlive(context.Background(), WithKey([]byte("error")))
+	if err == nil || ttl > 0 {
+		t.Fatalf("TestStore failed")
+	}
+
+	// KeepAlive case: get last task error
+	tt.key = "LeaseAsyncTask_a"
+	ttl, err = KeepAlive(context.Background(), WithKey([]byte("b")))
+	if err == nil || ttl > 0 {
+		t.Fatalf("TestStore failed")
+	}
+
+	// KeepAlive case: get last task error
+	tt.key = "LeaseAsyncTask_a"
+	ttl, err = KeepAlive(context.Background(), WithKey([]byte("a")))
+	if err != nil || ttl != 1 {
+		t.Fatalf("TestStore failed")
+	}
+}
diff --git a/server/plugin/discovery/common.go b/datasource/etcd/client/common.go
similarity index 58%
copy from server/plugin/discovery/common.go
copy to datasource/etcd/client/common.go
index 39232aa..420492b 100644
--- a/server/plugin/discovery/common.go
+++ b/datasource/etcd/client/common.go
@@ -14,13 +14,51 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package client
 
 import (
 	"time"
 )
 
 const (
-	DefaultTimeout       = 30 * time.Second
-	DefaultCacheInitSize = 100
+	ActionGet ActionType = iota
+	ActionPut
+	ActionDelete
+)
+
+const (
+	SortNone SortOrder = iota
+	SortAscend
+	SortDescend
+)
+
+const (
+	CmpVersion CompareType = iota
+	CmpCreate
+	CmpMod
+	CmpValue
+)
+
+const (
+	CmpEqual CompareResult = iota
+	CmpGreater
+	CmpLess
+	CmpNotEqual
+)
+
+const (
+	ModeBoth CacheMode = iota
+	ModeCache
+	ModeNoCache
+)
+
+const (
+	// grpc does not allow to transport a large body more then 4MB in a request
+	DefaultPageCount = 4096
+	// the timeout dial to etcd
+	DefaultDialTimeout    = 10 * time.Second
+	DefaultRequestTimeout = 30 * time.Second
+
+	DefaultClusterName = "default"
 )
diff --git a/datasource/etcd/client/config.go b/datasource/etcd/client/config.go
new file mode 100644
index 0000000..a9aa9a1
--- /dev/null
+++ b/datasource/etcd/client/config.go
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package client
+
+import (
+	"github.com/apache/servicecomb-service-center/pkg/types"
+	"strings"
+	"time"
+)
+
+type Config struct {
+	SslEnabled       bool           `json:"-"`
+	ManagerAddress   string         `json:"manageAddress,omitempty"`
+	ClusterName      string         `json:"manageName,omitempty"`
+	ClusterAddresses string         `json:"manageClusters,omitempty"` // the raw string of cluster configuration
+	Clusters         types.Clusters `json:"-"`                        // parsed from ClusterAddresses
+	DialTimeout      time.Duration  `json:"connectTimeout"`
+	RequestTimeOut   time.Duration  `json:"registryTimeout"`
+	AutoSyncInterval time.Duration  `json:"autoSyncInterval"`
+}
+
+//InitClusterInfo re-org address info with node name
+func (c *Config) InitClusterInfo() {
+	c.Clusters = make(types.Clusters)
+	// sc-0=http(s)://host1:port1,http(s)://host2:port2,sc-1=http(s)://host3:port3
+	kvs := strings.Split(c.ClusterAddresses, "=")
+	if l := len(kvs); l >= 2 {
+		var (
+			names []string
+			addrs [][]string
+		)
+		for i := 0; i < l; i++ {
+			ss := strings.Split(kvs[i], ",")
+			sl := len(ss)
+			if i != l-1 {
+				names = append(names, ss[sl-1])
+			}
+			if i != 0 {
+				if sl > 1 && i != l-1 {
+					addrs = append(addrs, ss[:sl-1])
+				} else {
+					addrs = append(addrs, ss)
+				}
+			}
+		}
+		for i, name := range names {
+			c.Clusters[name] = addrs[i]
+		}
+		if len(c.ManagerAddress) > 0 {
+			c.Clusters[c.ClusterName] = strings.Split(c.ManagerAddress, ",")
+		}
+	}
+	if len(c.Clusters) == 0 {
+		c.Clusters[c.ClusterName] = strings.Split(c.ClusterAddresses, ",")
+	}
+}
+
+// RegistryAddresses return the address of current SC's cache cache
+func (c *Config) RegistryAddresses() []string {
+	return c.Clusters[c.ClusterName]
+}
diff --git a/server/plugin/registry/embededetcd/embededetcd.go b/datasource/etcd/client/embedded/embededetcd.go
similarity index 80%
rename from server/plugin/registry/embededetcd/embededetcd.go
rename to datasource/etcd/client/embedded/embededetcd.go
index 140a530..3711a40 100644
--- a/server/plugin/registry/embededetcd/embededetcd.go
+++ b/datasource/etcd/client/embedded/embededetcd.go
@@ -15,18 +15,18 @@
  * limitations under the License.
  */
 
-package embededetcd
+package embedded
 
 import (
 	"context"
 	"errors"
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	mgr "github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 	"github.com/coreos/etcd/compactor"
 	"github.com/coreos/etcd/embed"
 	"github.com/coreos/etcd/etcdserver"
@@ -40,7 +40,7 @@ import (
 )
 
 func init() {
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.REGISTRY, Name: "embeded_etcd", New: getEmbedInstance})
+	client.Install("embeded_etcd", getEmbedInstance)
 }
 
 type EtcdEmbed struct {
@@ -78,16 +78,16 @@ func (s *EtcdEmbed) getPrefixEndKey(prefix []byte) []byte {
 	return endBytes[:l]
 }
 
-func (s *EtcdEmbed) toGetRequest(op registry.PluginOp) *etcdserverpb.RangeRequest {
+func (s *EtcdEmbed) toGetRequest(op client.PluginOp) *etcdserverpb.RangeRequest {
 	endBytes := op.EndKey
 	if op.Prefix {
 		endBytes = s.getPrefixEndKey(op.Key)
 	}
 	order := etcdserverpb.RangeRequest_NONE
 	switch op.SortOrder {
-	case registry.SortAscend:
+	case client.SortAscend:
 		order = etcdserverpb.RangeRequest_ASCEND
-	case registry.SortDescend:
+	case client.SortDescend:
 		order = etcdserverpb.RangeRequest_DESCEND
 	}
 	return &etcdserverpb.RangeRequest{
@@ -101,7 +101,7 @@ func (s *EtcdEmbed) toGetRequest(op registry.PluginOp) *etcdserverpb.RangeReques
 	}
 }
 
-func (s *EtcdEmbed) toPutRequest(op registry.PluginOp) *etcdserverpb.PutRequest {
+func (s *EtcdEmbed) toPutRequest(op client.PluginOp) *etcdserverpb.PutRequest {
 	var valueBytes []byte
 	if len(op.Value) > 0 {
 		valueBytes = op.Value
@@ -115,7 +115,7 @@ func (s *EtcdEmbed) toPutRequest(op registry.PluginOp) *etcdserverpb.PutRequest
 	}
 }
 
-func (s *EtcdEmbed) toDeleteRequest(op registry.PluginOp) *etcdserverpb.DeleteRangeRequest {
+func (s *EtcdEmbed) toDeleteRequest(op client.PluginOp) *etcdserverpb.DeleteRangeRequest {
 	endBytes := op.EndKey
 	if op.Prefix {
 		endBytes = s.getPrefixEndKey(op.Key)
@@ -127,23 +127,23 @@ func (s *EtcdEmbed) toDeleteRequest(op registry.PluginOp) *etcdserverpb.DeleteRa
 	}
 }
 
-func (s *EtcdEmbed) toTxnRequest(opts []registry.PluginOp) []*etcdserverpb.RequestOp {
+func (s *EtcdEmbed) toTxnRequest(opts []client.PluginOp) []*etcdserverpb.RequestOp {
 	etcdOps := []*etcdserverpb.RequestOp{}
 	for _, op := range opts {
 		switch op.Action {
-		case registry.Get:
+		case client.ActionGet:
 			etcdOps = append(etcdOps, &etcdserverpb.RequestOp{
 				Request: &etcdserverpb.RequestOp_RequestRange{
 					RequestRange: s.toGetRequest(op),
 				},
 			})
-		case registry.Put:
+		case client.ActionPut:
 			etcdOps = append(etcdOps, &etcdserverpb.RequestOp{
 				Request: &etcdserverpb.RequestOp_RequestPut{
 					RequestPut: s.toPutRequest(op),
 				},
 			})
-		case registry.Delete:
+		case client.ActionDelete:
 			etcdOps = append(etcdOps, &etcdserverpb.RequestOp{
 				Request: &etcdserverpb.RequestOp_RequestDeleteRange{
 					RequestDeleteRange: s.toDeleteRequest(op),
@@ -154,14 +154,14 @@ func (s *EtcdEmbed) toTxnRequest(opts []registry.PluginOp) []*etcdserverpb.Reque
 	return etcdOps
 }
 
-func (s *EtcdEmbed) toCompares(cmps []registry.CompareOp) []*etcdserverpb.Compare {
+func (s *EtcdEmbed) toCompares(cmps []client.CompareOp) []*etcdserverpb.Compare {
 	etcdCmps := []*etcdserverpb.Compare{}
 	for _, cmp := range cmps {
 		compare := &etcdserverpb.Compare{
 			Key: cmp.Key,
 		}
 		switch cmp.Type {
-		case registry.CmpVersion:
+		case client.CmpVersion:
 			var version int64
 			if cmp.Value != nil {
 				if v, ok := cmp.Value.(int64); ok {
@@ -172,7 +172,7 @@ func (s *EtcdEmbed) toCompares(cmps []registry.CompareOp) []*etcdserverpb.Compar
 			compare.TargetUnion = &etcdserverpb.Compare_Version{
 				Version: version,
 			}
-		case registry.CmpCreate:
+		case client.CmpCreate:
 			var revision int64
 			if cmp.Value != nil {
 				if v, ok := cmp.Value.(int64); ok {
@@ -183,7 +183,7 @@ func (s *EtcdEmbed) toCompares(cmps []registry.CompareOp) []*etcdserverpb.Compar
 			compare.TargetUnion = &etcdserverpb.Compare_CreateRevision{
 				CreateRevision: revision,
 			}
-		case registry.CmpMod:
+		case client.CmpMod:
 			var revision int64
 			if cmp.Value != nil {
 				if v, ok := cmp.Value.(int64); ok {
@@ -194,7 +194,7 @@ func (s *EtcdEmbed) toCompares(cmps []registry.CompareOp) []*etcdserverpb.Compar
 			compare.TargetUnion = &etcdserverpb.Compare_ModRevision{
 				ModRevision: revision,
 			}
-		case registry.CmpValue:
+		case client.CmpValue:
 			var value []byte
 			if cmp.Value != nil {
 				if v, ok := cmp.Value.([]byte); ok {
@@ -207,13 +207,13 @@ func (s *EtcdEmbed) toCompares(cmps []registry.CompareOp) []*etcdserverpb.Compar
 			}
 		}
 		switch cmp.Result {
-		case registry.CmpEqual:
+		case client.CmpEqual:
 			compare.Result = etcdserverpb.Compare_EQUAL
-		case registry.CmpGreater:
+		case client.CmpGreater:
 			compare.Result = etcdserverpb.Compare_GREATER
-		case registry.CmpLess:
+		case client.CmpLess:
 			compare.Result = etcdserverpb.Compare_LESS
-		case registry.CmpNotEqual:
+		case client.CmpNotEqual:
 			compare.Result = etcdserverpb.Compare_NOT_EQUAL
 		}
 		etcdCmps = append(etcdCmps, compare)
@@ -251,10 +251,10 @@ func (s *EtcdEmbed) getLeaderCurrentRevision(ctx context.Context) int64 {
 	return s.Embed.Server.KV().Rev()
 }
 
-func (s *EtcdEmbed) PutNoOverride(ctx context.Context, opts ...registry.PluginOpOption) (bool, error) {
-	op := registry.OpPut(opts...)
-	resp, err := s.TxnWithCmp(ctx, []registry.PluginOp{op}, []registry.CompareOp{
-		registry.OpCmp(registry.CmpCreateRev(op.Key), registry.CmpEqual, 0),
+func (s *EtcdEmbed) PutNoOverride(ctx context.Context, opts ...client.PluginOpOption) (bool, error) {
+	op := client.OpPut(opts...)
+	resp, err := s.TxnWithCmp(ctx, []client.PluginOp{op}, []client.CompareOp{
+		client.OpCmp(client.CmpCreateRev(op.Key), client.CmpEqual, 0),
 	}, nil)
 	log.Debugf("response %s %v %v", op.Key, resp.Succeeded, resp.Revision)
 	if err != nil {
@@ -263,41 +263,41 @@ func (s *EtcdEmbed) PutNoOverride(ctx context.Context, opts ...registry.PluginOp
 	return resp.Succeeded, nil
 }
 
-func (s *EtcdEmbed) Do(ctx context.Context, opts ...registry.PluginOpOption) (*registry.PluginResponse, error) {
-	op := registry.OptionsToOp(opts...)
+func (s *EtcdEmbed) Do(ctx context.Context, opts ...client.PluginOpOption) (*client.PluginResponse, error) {
+	op := client.OptionsToOp(opts...)
 
-	otCtx, cancel := registry.WithTimeout(ctx)
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer cancel()
 	var err error
-	var resp *registry.PluginResponse
+	var resp *client.PluginResponse
 	switch op.Action {
-	case registry.Get:
+	case client.ActionGet:
 		var etcdResp *etcdserverpb.RangeResponse
 		etcdResp, err = s.Embed.Server.Range(otCtx, s.toGetRequest(op))
 		if err != nil {
 			break
 		}
-		resp = &registry.PluginResponse{
+		resp = &client.PluginResponse{
 			Kvs:      etcdResp.Kvs,
 			Count:    etcdResp.Count,
 			Revision: etcdResp.Header.Revision,
 		}
-	case registry.Put:
+	case client.ActionPut:
 		var etcdResp *etcdserverpb.PutResponse
 		etcdResp, err = s.Embed.Server.Put(otCtx, s.toPutRequest(op))
 		if err != nil {
 			break
 		}
-		resp = &registry.PluginResponse{
+		resp = &client.PluginResponse{
 			Revision: etcdResp.Header.Revision,
 		}
-	case registry.Delete:
+	case client.ActionDelete:
 		var etcdResp *etcdserverpb.DeleteRangeResponse
 		etcdResp, err = s.Embed.Server.DeleteRange(otCtx, s.toDeleteRequest(op))
 		if err != nil {
 			break
 		}
-		resp = &registry.PluginResponse{
+		resp = &client.PluginResponse{
 			Revision: etcdResp.Header.Revision,
 		}
 	}
@@ -309,19 +309,19 @@ func (s *EtcdEmbed) Do(ctx context.Context, opts ...registry.PluginOpOption) (*r
 }
 
 // TODO EMBED支持KV().TxnBegin()->TxnID,可惜PROXY模式暂时不支持
-func (s *EtcdEmbed) Txn(ctx context.Context, opts []registry.PluginOp) (*registry.PluginResponse, error) {
+func (s *EtcdEmbed) Txn(ctx context.Context, opts []client.PluginOp) (*client.PluginResponse, error) {
 	resp, err := s.TxnWithCmp(ctx, opts, nil, nil)
 	if err != nil {
 		return nil, err
 	}
-	return &registry.PluginResponse{
+	return &client.PluginResponse{
 		Succeeded: resp.Succeeded,
 		Revision:  resp.Revision,
 	}, nil
 }
 
-func (s *EtcdEmbed) TxnWithCmp(ctx context.Context, success []registry.PluginOp, cmps []registry.CompareOp, fail []registry.PluginOp) (*registry.PluginResponse, error) {
-	otCtx, cancel := registry.WithTimeout(ctx)
+func (s *EtcdEmbed) TxnWithCmp(ctx context.Context, success []client.PluginOp, cmps []client.CompareOp, fail []client.PluginOp) (*client.PluginResponse, error) {
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer cancel()
 
 	etcdCmps := s.toCompares(cmps)
@@ -341,7 +341,7 @@ func (s *EtcdEmbed) TxnWithCmp(ctx context.Context, success []registry.PluginOp,
 		if err.Error() == rpctypes.ErrKeyNotFound.Error() {
 			// etcd return ErrKeyNotFound if key does not exist and
 			// the PUT options contain WithIgnoreLease
-			return &registry.PluginResponse{Succeeded: false}, nil
+			return &client.PluginResponse{Succeeded: false}, nil
 		}
 		return nil, err
 	}
@@ -355,7 +355,7 @@ func (s *EtcdEmbed) TxnWithCmp(ctx context.Context, success []registry.PluginOp,
 		}
 	}
 
-	return &registry.PluginResponse{
+	return &client.PluginResponse{
 		Succeeded: resp.Succeeded,
 		Revision:  resp.Header.Revision,
 		Kvs:       rangeResponse.Kvs,
@@ -364,7 +364,7 @@ func (s *EtcdEmbed) TxnWithCmp(ctx context.Context, success []registry.PluginOp,
 }
 
 func (s *EtcdEmbed) LeaseGrant(ctx context.Context, TTL int64) (int64, error) {
-	otCtx, cancel := registry.WithTimeout(ctx)
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer cancel()
 	etcdResp, err := s.Embed.Server.LeaseGrant(otCtx, &etcdserverpb.LeaseGrantRequest{
 		TTL: TTL,
@@ -376,7 +376,7 @@ func (s *EtcdEmbed) LeaseGrant(ctx context.Context, TTL int64) (int64, error) {
 }
 
 func (s *EtcdEmbed) LeaseRenew(ctx context.Context, leaseID int64) (int64, error) {
-	otCtx, cancel := registry.WithTimeout(ctx)
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer cancel()
 	ttl, err := s.Embed.Server.LeaseRenew(otCtx, lease.LeaseID(leaseID))
 	if err != nil {
@@ -389,7 +389,7 @@ func (s *EtcdEmbed) LeaseRenew(ctx context.Context, leaseID int64) (int64, error
 }
 
 func (s *EtcdEmbed) LeaseRevoke(ctx context.Context, leaseID int64) error {
-	otCtx, cancel := registry.WithTimeout(ctx)
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer cancel()
 	_, err := s.Embed.Server.LeaseRevoke(otCtx, &etcdserverpb.LeaseRevokeRequest{
 		ID: leaseID,
@@ -403,8 +403,8 @@ func (s *EtcdEmbed) LeaseRevoke(ctx context.Context, leaseID int64) error {
 	return nil
 }
 
-func (s *EtcdEmbed) Watch(ctx context.Context, opts ...registry.PluginOpOption) (err error) {
-	op := registry.OpGet(opts...)
+func (s *EtcdEmbed) Watch(ctx context.Context, opts ...client.PluginOpOption) (err error) {
+	op := client.OpGet(opts...)
 
 	if len(op.Key) > 0 {
 		watchable := s.Embed.Server.Watchable()
@@ -448,7 +448,7 @@ func (s *EtcdEmbed) Watch(ctx context.Context, opts ...registry.PluginOpOption)
 }
 
 func (s *EtcdEmbed) readyNotify() {
-	timeout := registry.Configuration().DialTimeout
+	timeout := etcd.Configuration().DialTimeout
 	select {
 	case <-s.Embed.Server.ReadyNotify():
 		close(s.ready)
@@ -470,11 +470,11 @@ func (s *EtcdEmbed) readyNotify() {
 	}
 }
 
-func dispatch(evts []mvccpb.Event, cb registry.WatchCallback) error {
+func dispatch(evts []mvccpb.Event, cb client.WatchCallback) error {
 	l := len(evts)
 	kvs := make([]*mvccpb.KeyValue, l)
 	sIdx, eIdx, rev := 0, 0, int64(0)
-	action, prevEvtType := registry.Put, mvccpb.PUT
+	action, prevEvtType := client.ActionPut, mvccpb.PUT
 
 	for _, evt := range evts {
 		if prevEvtType != evt.Type {
@@ -502,7 +502,7 @@ func dispatch(evts []mvccpb.Event, cb registry.WatchCallback) error {
 	return nil
 }
 
-func setKvsAndConvertAction(kvs []*mvccpb.KeyValue, pIdx int, evt mvccpb.Event) registry.ActionType {
+func setKvsAndConvertAction(kvs []*mvccpb.KeyValue, pIdx int, evt mvccpb.Event) client.ActionType {
 	switch evt.Type {
 	case mvccpb.DELETE:
 		kv := evt.PrevKv
@@ -510,15 +510,15 @@ func setKvsAndConvertAction(kvs []*mvccpb.KeyValue, pIdx int, evt mvccpb.Event)
 			kv = evt.Kv
 		}
 		kvs[pIdx] = kv
-		return registry.Delete
+		return client.ActionDelete
 	default:
 		kvs[pIdx] = evt.Kv
-		return registry.Put
+		return client.ActionPut
 	}
 }
 
-func callback(action registry.ActionType, rev int64, kvs []*mvccpb.KeyValue, cb registry.WatchCallback) error {
-	return cb("key information changed", &registry.PluginResponse{
+func callback(action client.ActionType, rev int64, kvs []*mvccpb.KeyValue, cb client.WatchCallback) error {
+	return cb("key information changed", &client.PluginResponse{
 		Action:    action,
 		Kvs:       kvs,
 		Count:     int64(len(kvs)),
@@ -527,16 +527,16 @@ func callback(action registry.ActionType, rev int64, kvs []*mvccpb.KeyValue, cb
 	})
 }
 
-func getEmbedInstance() mgr.Instance {
+func getEmbedInstance(opts client.Options) client.Registry {
 	log.Warnf("enable embedded registry mode")
 
 	hostName := "sc-0"
-	if len(registry.Configuration().ClusterName) > 0 {
-		hostName = registry.Configuration().ClusterName
+	if len(etcd.Configuration().ClusterName) > 0 {
+		hostName = etcd.Configuration().ClusterName
 	}
 	mgrAddrs := "http://127.0.0.1:2380"
-	if len(registry.Configuration().ManagerAddress) > 0 {
-		mgrAddrs = registry.Configuration().ManagerAddress
+	if len(etcd.Configuration().ManagerAddress) > 0 {
+		mgrAddrs = etcd.Configuration().ManagerAddress
 	}
 
 	inst := &EtcdEmbed{
@@ -545,7 +545,7 @@ func getEmbedInstance() mgr.Instance {
 		goroutine: gopool.New(context.Background()),
 	}
 
-	if registry.Configuration().SslEnabled {
+	if etcd.Configuration().SslEnabled {
 		log.Info("config no use for embedded etcd")
 	}
 
@@ -558,7 +558,7 @@ func getEmbedInstance() mgr.Instance {
 	serverCfg.Dir = "data"
 	// 集群支持
 	serverCfg.Name = hostName
-	serverCfg.InitialCluster = registry.Configuration().ClusterAddresses
+	serverCfg.InitialCluster = etcd.Configuration().ClusterAddresses
 	// 1. 管理端口
 	urls, err := parseURL(mgrAddrs)
 	if err != nil {
diff --git a/server/core/backend/lease.go b/datasource/etcd/client/lease_task.go
similarity index 90%
rename from server/core/backend/lease.go
rename to datasource/etcd/client/lease_task.go
index 39b3691..e7fe8c5 100644
--- a/server/core/backend/lease.go
+++ b/datasource/etcd/client/lease_task.go
@@ -15,20 +15,22 @@
  * limitations under the License.
  */
 
-package backend
+package client
 
 import (
 	"context"
+	"github.com/apache/servicecomb-service-center/datasource"
 	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	simple "github.com/apache/servicecomb-service-center/pkg/time"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 	"time"
 )
 
+const leaseProfTimeFmt = "15:04:05.000"
+
 type LeaseTask struct {
-	Client registry.Registry
+	Client Registry
 
 	key     string
 	LeaseID int64
@@ -45,7 +47,7 @@ func (lat *LeaseTask) Key() string {
 func (lat *LeaseTask) Do(ctx context.Context) (err error) {
 	recv, start := lat.ReceiveTime(), time.Now()
 	lat.TTL, err = lat.Client.LeaseRenew(ctx, lat.LeaseID)
-	ReportHeartbeatCompleted(err, recv)
+	datasource.ReportHeartbeatCompleted(err, recv)
 	if err != nil {
 		log.Errorf(err, "[%s]task[%s] renew lease[%d] failed(recv: %s, send: %s)",
 			time.Since(recv),
@@ -82,9 +84,9 @@ func (lat *LeaseTask) ReceiveTime() time.Time {
 	return lat.recvTime.Local()
 }
 
-func NewLeaseAsyncTask(op registry.PluginOp) *LeaseTask {
+func NewLeaseAsyncTask(op PluginOp) *LeaseTask {
 	return &LeaseTask{
-		Client:   Registry(),
+		Client:   Instance(),
 		key:      ToLeaseAsyncTaskKey(util.BytesToStringWithNoCopy(op.Key)),
 		LeaseID:  op.Lease,
 		recvTime: simple.FromTime(time.Now()),
diff --git a/server/core/backend/lease_test.go b/datasource/etcd/client/lease_task_test.go
similarity index 83%
rename from server/core/backend/lease_test.go
rename to datasource/etcd/client/lease_task_test.go
index 4765c51..eac7f90 100644
--- a/server/core/backend/lease_test.go
+++ b/datasource/etcd/client/lease_task_test.go
@@ -14,16 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package backend
+package client_test
 
 import (
 	"context"
 	"fmt"
+	. "github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client/buildin"
 	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
-	simple "github.com/apache/servicecomb-service-center/pkg/time"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry/buildin"
 	"testing"
-	"time"
 )
 
 type mockRegistry struct {
@@ -40,12 +39,8 @@ func (c *mockRegistry) LeaseRenew(ctx context.Context, leaseID int64) (TTL int64
 
 func TestLeaseTask_Do(t *testing.T) {
 	c := &mockRegistry{}
-	lt := &LeaseTask{
-		Client:   c,
-		key:      ToLeaseAsyncTaskKey("/a"),
-		LeaseID:  1,
-		recvTime: simple.FromTime(time.Now()),
-	}
+	lt := NewLeaseAsyncTask(OptionsToOp(WithStrKey("/a"), WithLease(1)))
+	lt.Client = c
 
 	c.LeaseErr = errorsEx.InternalError("lease not found")
 	err := lt.Do(context.Background())
diff --git a/datasource/etcd/client/manager.go b/datasource/etcd/client/manager.go
new file mode 100644
index 0000000..5d67c14
--- /dev/null
+++ b/datasource/etcd/client/manager.go
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package client
+
+import (
+	"fmt"
+	"github.com/apache/servicecomb-service-center/pkg/backoff"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"time"
+)
+
+type newClientFunc func(opts Options) Registry
+
+var (
+	plugins    = make(map[ImplName]newClientFunc)
+	pluginInst Registry
+)
+
+// load plugins configuration into plugins
+func Install(pluginImplName string, newFunc newClientFunc) {
+	plugins[ImplName(pluginImplName)] = newFunc
+}
+
+// construct storage plugin instance
+// invoked by sc main process
+func Init(opts Options) error {
+	for i := 0; ; i++ {
+		inst, err := New(opts)
+		if err == nil {
+			pluginInst = inst
+			break
+		}
+
+		t := backoff.GetBackoff().Delay(i)
+		log.Errorf(err, "initialize client[%v] failed, retry after %s", opts.PluginImplName, t)
+		<-time.After(t)
+	}
+	log.Info(fmt.Sprintf("client plugin [%s] enabled", opts.PluginImplName))
+	return nil
+}
+
+func New(opts Options) (Registry, error) {
+	if opts.PluginImplName == "" {
+		return nil, fmt.Errorf("plugin implement name is nil")
+	}
+
+	f, ok := plugins[opts.PluginImplName]
+	if !ok {
+		return nil, fmt.Errorf("plugin implement not supported [%s]", opts.PluginImplName)
+	}
+	inst := f(opts)
+	select {
+	case err := <-inst.Err():
+		return nil, err
+	case <-inst.Ready():
+		return inst, nil
+	}
+}
+
+// Instance is the instance of Etcd client
+func Instance() Registry {
+	if pluginInst != nil {
+		<-pluginInst.Ready()
+	}
+	return pluginInst
+}
diff --git a/server/plugin/registry/metrics.go b/datasource/etcd/client/metrics.go
similarity index 99%
rename from server/plugin/registry/metrics.go
rename to datasource/etcd/client/metrics.go
index b1943ea..11fa7a2 100644
--- a/server/plugin/registry/metrics.go
+++ b/datasource/etcd/client/metrics.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package registry
+package client
 
 import (
 	"github.com/apache/servicecomb-service-center/server/metric"
diff --git a/server/plugin/registry/option.go b/datasource/etcd/client/options.go
similarity index 84%
rename from server/plugin/registry/option.go
rename to datasource/etcd/client/options.go
index f137a1e..3231381 100644
--- a/server/plugin/registry/option.go
+++ b/datasource/etcd/client/options.go
@@ -1,25 +1,32 @@
-// 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 registry
+/*
+ * 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 client
 
 import (
 	"bytes"
 	"fmt"
 )
 
+//Options contains configuration for plugins
+type Options struct {
+	PluginImplName ImplName
+}
+
 type PluginOp struct {
 	Action        ActionType
 	Key           []byte
@@ -109,9 +116,9 @@ type Operation func(...PluginOpOption) (op PluginOp)
 type PluginOpOption func(*PluginOp)
 type WatchCallback func(message string, evt *PluginResponse) error
 
-var GET PluginOpOption = func(op *PluginOp) { op.Action = Get }
-var PUT PluginOpOption = func(op *PluginOp) { op.Action = Put }
-var DEL PluginOpOption = func(op *PluginOp) { op.Action = Delete }
+var GET PluginOpOption = func(op *PluginOp) { op.Action = ActionGet }
+var PUT PluginOpOption = func(op *PluginOp) { op.Action = ActionPut }
+var DEL PluginOpOption = func(op *PluginOp) { op.Action = ActionDelete }
 
 func WithKey(key []byte) PluginOpOption      { return func(op *PluginOp) { op.Key = key } }
 func WithEndKey(key []byte) PluginOpOption   { return func(op *PluginOp) { op.EndKey = key } }
@@ -143,17 +150,17 @@ func WatchPrefixOpOptions(key string) []PluginOpOption {
 
 func OpGet(opts ...PluginOpOption) (op PluginOp) {
 	op = OptionsToOp(opts...)
-	op.Action = Get
+	op.Action = ActionGet
 	return
 }
 func OpPut(opts ...PluginOpOption) (op PluginOp) {
 	op = OptionsToOp(opts...)
-	op.Action = Put
+	op.Action = ActionPut
 	return
 }
 func OpDel(opts ...PluginOpOption) (op PluginOp) {
 	op = OptionsToOp(opts...)
-	op.Action = Delete
+	op.Action = ActionDelete
 	return
 }
 func OptionsToOp(opts ...PluginOpOption) (op PluginOp) {
diff --git a/server/plugin/registry/etcd/common.go b/datasource/etcd/client/remote/common.go
similarity index 99%
rename from server/plugin/registry/etcd/common.go
rename to datasource/etcd/client/remote/common.go
index b296c1f..007791c 100644
--- a/server/plugin/registry/etcd/common.go
+++ b/datasource/etcd/client/remote/common.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package etcd
+package remote
 
 import (
 	"math"
diff --git a/server/plugin/registry/etcd/etcd.go b/datasource/etcd/client/remote/etcd.go
similarity index 80%
rename from server/plugin/registry/etcd/etcd.go
rename to datasource/etcd/client/remote/etcd.go
index 159204f..3745283 100644
--- a/server/plugin/registry/etcd/etcd.go
+++ b/datasource/etcd/client/remote/etcd.go
@@ -15,27 +15,27 @@
  * limitations under the License.
  */
 
-package etcd
+package remote
 
 import (
 	"crypto/tls"
 	"errors"
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd"
+	"github.com/apache/servicecomb-service-center/server/plugin/security/tlsconf"
 	"net/url"
 	"strconv"
 	"strings"
 	"time"
 
+	"context"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 	"github.com/apache/servicecomb-service-center/pkg/backoff"
 	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/alarm"
-	mgr "github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
-
-	"context"
 	"github.com/coreos/etcd/clientv3"
 	"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
 	"github.com/coreos/etcd/etcdserver/etcdserverpb"
@@ -46,7 +46,7 @@ var firstEndpoint string
 
 func init() {
 	clientv3.SetLogger(&clientLogger{})
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.REGISTRY, Name: "etcd", New: NewRegistry})
+	client.Install("etcd", NewRegistry)
 }
 
 type Client struct {
@@ -71,20 +71,20 @@ func (c *Client) Initialize() (err error) {
 		// parse the endpoints from config
 		c.parseEndpoints()
 	}
-	if c.TLSConfig == nil && registry.Configuration().SslEnabled {
+	if c.TLSConfig == nil && etcd.Configuration().SslEnabled {
 		var err error
 		// go client tls限制,提供身份证书、不认证服务端、不校验CN
-		c.TLSConfig, err = mgr.Plugins().TLS().ClientConfig()
+		c.TLSConfig, err = tlsconf.ClientConfig()
 		if err != nil {
 			log.Error("get etcd client tls config failed", err)
 			return err
 		}
 	}
 	if c.DialTimeout == 0 {
-		c.DialTimeout = registry.Configuration().DialTimeout
+		c.DialTimeout = etcd.Configuration().DialTimeout
 	}
 	if c.AutoSyncInterval == 0 {
-		c.AutoSyncInterval = registry.Configuration().AutoSyncInterval
+		c.AutoSyncInterval = etcd.Configuration().AutoSyncInterval
 	}
 
 	c.Client, err = c.newClient()
@@ -103,7 +103,7 @@ func (c *Client) Initialize() (err error) {
 }
 
 func (c *Client) newClient() (*clientv3.Client, error) {
-	client, err := clientv3.New(clientv3.Config{
+	inst, err := clientv3.New(clientv3.Config{
 		Endpoints:            c.Endpoints,
 		DialTimeout:          c.DialTimeout,
 		TLS:                  c.TLSConfig,
@@ -119,8 +119,8 @@ func (c *Client) newClient() (*clientv3.Client, error) {
 				log.Error("", err)
 			}
 
-			if client != nil {
-				client.Close()
+			if inst != nil {
+				inst.Close()
 			}
 		}
 	}()
@@ -129,18 +129,18 @@ func (c *Client) newClient() (*clientv3.Client, error) {
 		return nil, err
 	}
 
-	ctx, cancel := context.WithTimeout(client.Ctx(), healthCheckTimeout)
+	ctx, cancel := context.WithTimeout(inst.Ctx(), healthCheckTimeout)
 	defer cancel()
-	resp, err := client.MemberList(ctx)
+	resp, err := inst.MemberList(ctx)
 	if err != nil {
 		return nil, err
 	}
 
-	registry.ReportBackendInstance(len(resp.Members))
+	client.ReportBackendInstance(len(resp.Members))
 
 	if len(c.Endpoints) == 1 {
 		// no need to check remote endpoints
-		return client, nil
+		return inst, nil
 	}
 
 epLoop:
@@ -163,7 +163,7 @@ epLoop:
 		return nil, err
 	}
 
-	return client, nil
+	return inst, nil
 }
 
 func (c *Client) Err() <-chan error {
@@ -195,7 +195,7 @@ func (c *Client) Compact(ctx context.Context, reserve int64) error {
 
 	t := time.Now()
 	_, err := c.Client.Compact(ctx, revToCompact, clientv3.WithCompactPhysical())
-	registry.ReportBackendOperationCompleted(OperationCompact, err, t)
+	client.ReportBackendOperationCompleted(OperationCompact, err, t)
 	if err != nil {
 		log.Errorf(err, "compact %s failed, revision is %d(current: %d, reserve %d)",
 			eps, revToCompact, curRev, reserve)
@@ -203,7 +203,7 @@ func (c *Client) Compact(ctx context.Context, reserve int64) error {
 	}
 	log.InfoOrWarnf(t, "compacted %s, revision is %d(current: %d, reserve %d)", eps, revToCompact, curRev, reserve)
 
-	// TODO can not defrag! because backend will always be unavailable when space in used is too large.
+	// TODO can not defrag! because cache will always be unavailable when space in used is too large.
 	/*for _, ep := range eps {
 		t = time.Now()
 		_, err := c.Client.Defragment(ctx, ep)
@@ -242,7 +242,7 @@ func max(n1, n2 int64) int64 {
 	return n2
 }
 
-func (c *Client) toGetRequest(op registry.PluginOp) []clientv3.OpOption {
+func (c *Client) toGetRequest(op client.PluginOp) []clientv3.OpOption {
 	var opts []clientv3.OpOption
 	if op.Prefix {
 		opts = append(opts, clientv3.WithPrefix())
@@ -262,15 +262,15 @@ func (c *Client) toGetRequest(op registry.PluginOp) []clientv3.OpOption {
 		opts = append(opts, clientv3.WithRev(op.Revision))
 	}
 	switch op.SortOrder {
-	case registry.SortAscend:
+	case client.SortAscend:
 		opts = append(opts, clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend))
-	case registry.SortDescend:
+	case client.SortDescend:
 		opts = append(opts, clientv3.WithSort(clientv3.SortByKey, clientv3.SortDescend))
 	}
 	return opts
 }
 
-func (c *Client) toPutRequest(op registry.PluginOp) []clientv3.OpOption {
+func (c *Client) toPutRequest(op client.PluginOp) []clientv3.OpOption {
 	var opts []clientv3.OpOption
 	if op.PrevKV {
 		opts = append(opts, clientv3.WithPrevKV())
@@ -284,7 +284,7 @@ func (c *Client) toPutRequest(op registry.PluginOp) []clientv3.OpOption {
 	return opts
 }
 
-func (c *Client) toDeleteRequest(op registry.PluginOp) []clientv3.OpOption {
+func (c *Client) toDeleteRequest(op client.PluginOp) []clientv3.OpOption {
 	var opts []clientv3.OpOption
 	if op.Prefix {
 		opts = append(opts, clientv3.WithPrefix())
@@ -297,49 +297,49 @@ func (c *Client) toDeleteRequest(op registry.PluginOp) []clientv3.OpOption {
 	return opts
 }
 
-func (c *Client) toTxnRequest(opts []registry.PluginOp) []clientv3.Op {
+func (c *Client) toTxnRequest(opts []client.PluginOp) []clientv3.Op {
 	var etcdOps []clientv3.Op
 	for _, op := range opts {
 		switch op.Action {
-		case registry.Get:
+		case client.ActionGet:
 			etcdOps = append(etcdOps, clientv3.OpGet(util.BytesToStringWithNoCopy(op.Key), c.toGetRequest(op)...))
-		case registry.Put:
+		case client.ActionPut:
 			var value string
 			if len(op.Value) > 0 {
 				value = util.BytesToStringWithNoCopy(op.Value)
 			}
 			etcdOps = append(etcdOps, clientv3.OpPut(util.BytesToStringWithNoCopy(op.Key), value, c.toPutRequest(op)...))
-		case registry.Delete:
+		case client.ActionDelete:
 			etcdOps = append(etcdOps, clientv3.OpDelete(util.BytesToStringWithNoCopy(op.Key), c.toDeleteRequest(op)...))
 		}
 	}
 	return etcdOps
 }
 
-func (c *Client) toCompares(cmps []registry.CompareOp) []clientv3.Cmp {
+func (c *Client) toCompares(cmps []client.CompareOp) []clientv3.Cmp {
 	var etcdCmps []clientv3.Cmp
 	for _, cmp := range cmps {
 		var cmpType clientv3.Cmp
 		var cmpResult string
 		key := util.BytesToStringWithNoCopy(cmp.Key)
 		switch cmp.Type {
-		case registry.CmpVersion:
+		case client.CmpVersion:
 			cmpType = clientv3.Version(key)
-		case registry.CmpCreate:
+		case client.CmpCreate:
 			cmpType = clientv3.CreateRevision(key)
-		case registry.CmpMod:
+		case client.CmpMod:
 			cmpType = clientv3.ModRevision(key)
-		case registry.CmpValue:
+		case client.CmpValue:
 			cmpType = clientv3.Value(key)
 		}
 		switch cmp.Result {
-		case registry.CmpEqual:
+		case client.CmpEqual:
 			cmpResult = "="
-		case registry.CmpGreater:
+		case client.CmpGreater:
 			cmpResult = ">"
-		case registry.CmpLess:
+		case client.CmpLess:
 			cmpResult = "<"
-		case registry.CmpNotEqual:
+		case client.CmpNotEqual:
 			cmpResult = "!="
 		}
 		etcdCmps = append(etcdCmps, clientv3.Compare(cmpType, cmpResult, cmp.Value))
@@ -347,10 +347,10 @@ func (c *Client) toCompares(cmps []registry.CompareOp) []clientv3.Cmp {
 	return etcdCmps
 }
 
-func (c *Client) PutNoOverride(ctx context.Context, opts ...registry.PluginOpOption) (bool, error) {
-	op := registry.OpPut(opts...)
-	resp, err := c.TxnWithCmp(ctx, []registry.PluginOp{op}, []registry.CompareOp{
-		registry.OpCmp(registry.CmpCreateRev(op.Key), registry.CmpEqual, 0),
+func (c *Client) PutNoOverride(ctx context.Context, opts ...client.PluginOpOption) (bool, error) {
+	op := client.OpPut(opts...)
+	resp, err := c.TxnWithCmp(ctx, []client.PluginOp{op}, []client.CompareOp{
+		client.OpCmp(client.CmpCreateRev(op.Key), client.CmpEqual, 0),
 	}, nil)
 	if err != nil {
 		log.Errorf(err, "PutNoOverride %s failed", op.Key)
@@ -359,7 +359,7 @@ func (c *Client) PutNoOverride(ctx context.Context, opts ...registry.PluginOpOpt
 	return resp.Succeeded, nil
 }
 
-func (c *Client) paging(ctx context.Context, op registry.PluginOp) (*clientv3.GetResponse, error) {
+func (c *Client) paging(ctx context.Context, op client.PluginOp) (*clientv3.GetResponse, error) {
 	var etcdResp *clientv3.GetResponse
 	key := util.BytesToStringWithNoCopy(op.Key)
 
@@ -378,7 +378,7 @@ func (c *Client) paging(ctx context.Context, op registry.PluginOp) (*clientv3.Ge
 
 	tempOp.CountOnly = false
 	tempOp.Prefix = false
-	tempOp.SortOrder = registry.SortAscend
+	tempOp.SortOrder = client.SortAscend
 	tempOp.EndKey = op.EndKey
 	if len(op.EndKey) == 0 {
 		tempOp.EndKey = util.StringToBytesWithNoCopy(clientv3.GetPrefixRangeEnd(key))
@@ -445,7 +445,7 @@ func (c *Client) paging(ctx context.Context, op registry.PluginOp) (*clientv3.Ge
 	}
 
 	// too slow
-	if op.SortOrder == registry.SortDescend {
+	if op.SortOrder == client.SortDescend {
 		t := time.Now()
 		for i, l := 0, len(etcdResp.Kvs); i < l; i++ {
 			last := l - i - 1
@@ -459,24 +459,24 @@ func (c *Client) paging(ctx context.Context, op registry.PluginOp) (*clientv3.Ge
 	return etcdResp, nil
 }
 
-func (c *Client) Do(ctx context.Context, opts ...registry.PluginOpOption) (*registry.PluginResponse, error) {
+func (c *Client) Do(ctx context.Context, opts ...client.PluginOpOption) (*client.PluginResponse, error) {
 	var (
 		err  error
-		resp *registry.PluginResponse
+		resp *client.PluginResponse
 	)
 
 	start := time.Now()
-	op := registry.OptionsToOp(opts...)
+	op := client.OptionsToOp(opts...)
 	span := TracingBegin(ctx, "etcd:do", op)
-	otCtx, cancel := registry.WithTimeout(ctx)
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer func() {
-		registry.ReportBackendOperationCompleted(op.Action.String(), err, start)
+		client.ReportBackendOperationCompleted(op.Action.String(), err, start)
 		TracingEnd(span, err)
 		cancel()
 	}()
 
 	switch op.Action {
-	case registry.Get:
+	case client.ActionGet:
 		var etcdResp *clientv3.GetResponse
 		key := util.BytesToStringWithNoCopy(op.Key)
 
@@ -494,12 +494,12 @@ func (c *Client) Do(ctx context.Context, opts ...registry.PluginOpOption) (*regi
 			}
 		}
 
-		resp = &registry.PluginResponse{
+		resp = &client.PluginResponse{
 			Kvs:      etcdResp.Kvs,
 			Count:    etcdResp.Count,
 			Revision: etcdResp.Header.Revision,
 		}
-	case registry.Put:
+	case client.ActionPut:
 		var value string
 		if len(op.Value) > 0 {
 			value = util.BytesToStringWithNoCopy(op.Value)
@@ -509,16 +509,16 @@ func (c *Client) Do(ctx context.Context, opts ...registry.PluginOpOption) (*regi
 		if err != nil {
 			break
 		}
-		resp = &registry.PluginResponse{
+		resp = &client.PluginResponse{
 			Revision: etcdResp.Header.Revision,
 		}
-	case registry.Delete:
+	case client.ActionDelete:
 		var etcdResp *clientv3.DeleteResponse
 		etcdResp, err = c.Client.Delete(otCtx, util.BytesToStringWithNoCopy(op.Key), c.toDeleteRequest(op)...)
 		if err != nil {
 			break
 		}
-		resp = &registry.PluginResponse{
+		resp = &client.PluginResponse{
 			Revision: etcdResp.Header.Revision,
 		}
 	}
@@ -533,18 +533,18 @@ func (c *Client) Do(ctx context.Context, opts ...registry.PluginOpOption) (*regi
 	return resp, nil
 }
 
-func (c *Client) Txn(ctx context.Context, opts []registry.PluginOp) (*registry.PluginResponse, error) {
+func (c *Client) Txn(ctx context.Context, opts []client.PluginOp) (*client.PluginResponse, error) {
 	resp, err := c.TxnWithCmp(ctx, opts, nil, nil)
 	if err != nil {
 		return nil, err
 	}
-	return &registry.PluginResponse{
+	return &client.PluginResponse{
 		Succeeded: resp.Succeeded,
 		Revision:  resp.Revision,
 	}, nil
 }
 
-func (c *Client) TxnWithCmp(ctx context.Context, success []registry.PluginOp, cmps []registry.CompareOp, fail []registry.PluginOp) (*registry.PluginResponse, error) {
+func (c *Client) TxnWithCmp(ctx context.Context, success []client.PluginOp, cmps []client.CompareOp, fail []client.PluginOp) (*client.PluginResponse, error) {
 	var err error
 
 	start := time.Now()
@@ -552,7 +552,7 @@ func (c *Client) TxnWithCmp(ctx context.Context, success []registry.PluginOp, cm
 	etcdSuccessOps := c.toTxnRequest(success)
 	etcdFailOps := c.toTxnRequest(fail)
 
-	var traceOps []registry.PluginOp
+	var traceOps []client.PluginOp
 	traceOps = append(traceOps, success...)
 	traceOps = append(traceOps, fail...)
 	if len(traceOps) == 0 {
@@ -560,9 +560,9 @@ func (c *Client) TxnWithCmp(ctx context.Context, success []registry.PluginOp, cm
 	}
 
 	span := TracingBegin(ctx, "etcd:txn", traceOps[0])
-	otCtx, cancel := registry.WithTimeout(ctx)
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer func() {
-		registry.ReportBackendOperationCompleted(OperationTxn, err, start)
+		client.ReportBackendOperationCompleted(OperationTxn, err, start)
 		TracingEnd(span, err)
 		cancel()
 	}()
@@ -581,7 +581,7 @@ func (c *Client) TxnWithCmp(ctx context.Context, success []registry.PluginOp, cm
 		if err.Error() == rpctypes.ErrKeyNotFound.Error() {
 			// etcd return ErrKeyNotFound if key does not exist and
 			// the PUT options contain WithIgnoreLease
-			return &registry.PluginResponse{Succeeded: false}, nil
+			return &client.PluginResponse{Succeeded: false}, nil
 		}
 		return nil, err
 	}
@@ -597,7 +597,7 @@ func (c *Client) TxnWithCmp(ctx context.Context, success []registry.PluginOp, cm
 		}
 	}
 
-	return &registry.PluginResponse{
+	return &client.PluginResponse{
 		Succeeded: resp.Succeeded,
 		Revision:  resp.Header.Revision,
 		Kvs:       rangeResponse.Kvs,
@@ -610,10 +610,10 @@ func (c *Client) LeaseGrant(ctx context.Context, TTL int64) (int64, error) {
 
 	start := time.Now()
 	span := TracingBegin(ctx, "etcd:grant",
-		registry.PluginOp{Action: registry.Put, Key: util.StringToBytesWithNoCopy(strconv.FormatInt(TTL, 10))})
-	otCtx, cancel := registry.WithTimeout(ctx)
+		client.PluginOp{Action: client.ActionPut, Key: util.StringToBytesWithNoCopy(strconv.FormatInt(TTL, 10))})
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer func() {
-		registry.ReportBackendOperationCompleted(OperationLeaseGrant, err, start)
+		client.ReportBackendOperationCompleted(OperationLeaseGrant, err, start)
 		TracingEnd(span, err)
 		cancel()
 	}()
@@ -630,10 +630,10 @@ func (c *Client) LeaseRenew(ctx context.Context, leaseID int64) (int64, error) {
 
 	start := time.Now()
 	span := TracingBegin(ctx, "etcd:keepalive",
-		registry.PluginOp{Action: registry.Put, Key: util.StringToBytesWithNoCopy(strconv.FormatInt(leaseID, 10))})
-	otCtx, cancel := registry.WithTimeout(ctx)
+		client.PluginOp{Action: client.ActionPut, Key: util.StringToBytesWithNoCopy(strconv.FormatInt(leaseID, 10))})
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer func() {
-		registry.ReportBackendOperationCompleted(OperationLeaseRenew, err, start)
+		client.ReportBackendOperationCompleted(OperationLeaseRenew, err, start)
 		TracingEnd(span, err)
 		cancel()
 	}()
@@ -654,10 +654,10 @@ func (c *Client) LeaseRevoke(ctx context.Context, leaseID int64) error {
 
 	start := time.Now()
 	span := TracingBegin(ctx, "etcd:revoke",
-		registry.PluginOp{Action: registry.Delete, Key: util.StringToBytesWithNoCopy(strconv.FormatInt(leaseID, 10))})
-	otCtx, cancel := registry.WithTimeout(ctx)
+		client.PluginOp{Action: client.ActionDelete, Key: util.StringToBytesWithNoCopy(strconv.FormatInt(leaseID, 10))})
+	otCtx, cancel := etcd.WithTimeout(ctx)
 	defer func() {
-		registry.ReportBackendOperationCompleted(OperationLeaseRevoke, err, start)
+		client.ReportBackendOperationCompleted(OperationLeaseRevoke, err, start)
 		TracingEnd(span, err)
 		cancel()
 	}()
@@ -673,8 +673,8 @@ func (c *Client) LeaseRevoke(ctx context.Context, leaseID int64) error {
 	return nil
 }
 
-func (c *Client) Watch(ctx context.Context, opts ...registry.PluginOpOption) (err error) {
-	op := registry.OpGet(opts...)
+func (c *Client) Watch(ctx context.Context, opts ...client.PluginOpOption) (err error) {
+	op := client.OpGet(opts...)
 
 	n := len(op.Key)
 	if n > 0 {
@@ -781,7 +781,7 @@ func (c *Client) ReOpen() error {
 
 func (c *Client) parseEndpoints() {
 	// use the default cluster endpoints
-	addrs := registry.Configuration().RegistryAddresses()
+	addrs := etcd.Configuration().RegistryAddresses()
 
 	endpoints := make([]string, 0, len(addrs))
 	for _, addr := range addrs {
@@ -800,7 +800,7 @@ func (c *Client) SyncMembers(ctx context.Context) error {
 	var err error
 
 	start := time.Now()
-	defer registry.ReportBackendOperationCompleted(OperationSyncMembers, err, start)
+	defer client.ReportBackendOperationCompleted(OperationSyncMembers, err, start)
 
 	if err = c.Client.Sync(ctx); err != nil && err != c.Client.Ctx().Err() {
 		return err
@@ -808,11 +808,11 @@ func (c *Client) SyncMembers(ctx context.Context) error {
 	return nil
 }
 
-func dispatch(evts []*clientv3.Event, cb registry.WatchCallback) error {
+func dispatch(evts []*clientv3.Event, cb client.WatchCallback) error {
 	l := len(evts)
 	kvs := make([]*mvccpb.KeyValue, l)
 	sIdx, eIdx, rev := 0, 0, int64(0)
-	action, prevEvtType := registry.Put, mvccpb.PUT
+	action, prevEvtType := client.ActionPut, mvccpb.PUT
 
 	for _, evt := range evts {
 		if prevEvtType != evt.Type {
@@ -840,7 +840,7 @@ func dispatch(evts []*clientv3.Event, cb registry.WatchCallback) error {
 	return nil
 }
 
-func setKvsAndConvertAction(kvs []*mvccpb.KeyValue, pIdx int, evt *clientv3.Event) registry.ActionType {
+func setKvsAndConvertAction(kvs []*mvccpb.KeyValue, pIdx int, evt *clientv3.Event) client.ActionType {
 	switch evt.Type {
 	case mvccpb.DELETE:
 		kv := evt.PrevKv
@@ -848,15 +848,15 @@ func setKvsAndConvertAction(kvs []*mvccpb.KeyValue, pIdx int, evt *clientv3.Even
 			kv = evt.Kv
 		}
 		kvs[pIdx] = kv
-		return registry.Delete
+		return client.ActionDelete
 	default:
 		kvs[pIdx] = evt.Kv
-		return registry.Put
+		return client.ActionPut
 	}
 }
 
-func callback(action registry.ActionType, rev int64, kvs []*mvccpb.KeyValue, cb registry.WatchCallback) error {
-	return cb("key information changed", &registry.PluginResponse{
+func callback(action client.ActionType, rev int64, kvs []*mvccpb.KeyValue, cb client.WatchCallback) error {
+	return cb("key information changed", &client.PluginResponse{
 		Action:    action,
 		Kvs:       kvs,
 		Count:     int64(len(kvs)),
@@ -865,7 +865,7 @@ func callback(action registry.ActionType, rev int64, kvs []*mvccpb.KeyValue, cb
 	})
 }
 
-func NewRegistry() mgr.Instance {
+func NewRegistry(opts client.Options) client.Registry {
 	log.Warnf("enable etcd registry mode")
 
 	inst := &Client{}
diff --git a/server/plugin/registry/etcd/etcd_test.go b/datasource/etcd/client/remote/etcd_test.go
similarity index 54%
rename from server/plugin/registry/etcd/etcd_test.go
rename to datasource/etcd/client/remote/etcd_test.go
index bfdee00..adbfa09 100644
--- a/server/plugin/registry/etcd/etcd_test.go
+++ b/datasource/etcd/client/remote/etcd_test.go
@@ -14,14 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package etcd
+package remote
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd"
 	_ "github.com/apache/servicecomb-service-center/server/plugin/tracing/pzipkin"
 	"github.com/stretchr/testify/assert"
 )
-import _ "github.com/apache/servicecomb-service-center/server/plugin/security/buildin"
-import _ "github.com/apache/servicecomb-service-center/server/plugin/tls/buildin"
+import _ "github.com/apache/servicecomb-service-center/server/plugin/security/cipher/buildin"
+import _ "github.com/apache/servicecomb-service-center/server/plugin/security/tlsconf/buildin"
 import (
 	context2 "context"
 	"fmt"
@@ -31,7 +32,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 
 	"context"
 	"github.com/coreos/etcd/clientv3"
@@ -44,72 +45,72 @@ const (
 )
 
 var (
-	endpoint = registry.Configuration().ClusterAddresses
+	endpoint = etcd.Configuration().ClusterAddresses
 )
 
 func TestInitCluster(t *testing.T) {
 	t.Run("normal", func(t *testing.T) {
-		registry.Configuration().ClusterAddresses = "127.0.0.1:2379"
-		registry.Configuration().InitClusterInfo()
-		if strings.Join(registry.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379" {
-			t.Fatalf("TestInitCluster failed, %v", registry.Configuration().RegistryAddresses())
+		etcd.Configuration().ClusterAddresses = "127.0.0.1:2379"
+		etcd.Configuration().InitClusterInfo()
+		if strings.Join(etcd.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379" {
+			t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().RegistryAddresses())
 		}
 	})
 	t.Run("not normal2", func(t *testing.T) {
-		registry.Configuration().ClusterAddresses = "127.0.0.1:2379,127.0.0.2:2379"
-		registry.Configuration().InitClusterInfo()
-		if strings.Join(registry.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379,127.0.0.2:2379" {
-			t.Fatalf("TestInitCluster failed, %v", registry.Configuration().RegistryAddresses())
+		etcd.Configuration().ClusterAddresses = "127.0.0.1:2379,127.0.0.2:2379"
+		etcd.Configuration().InitClusterInfo()
+		if strings.Join(etcd.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379,127.0.0.2:2379" {
+			t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().RegistryAddresses())
 		}
 	})
 
-	registry.Configuration().ClusterName = "sc-0"
-	registry.Configuration().ClusterAddresses = "sc-0=127.0.0.1:2379,127.0.0.2:2379"
-	registry.Configuration().InitClusterInfo()
-	if strings.Join(registry.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379,127.0.0.2:2379" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().RegistryAddresses())
+	etcd.Configuration().ClusterName = "sc-0"
+	etcd.Configuration().ClusterAddresses = "sc-0=127.0.0.1:2379,127.0.0.2:2379"
+	etcd.Configuration().InitClusterInfo()
+	if strings.Join(etcd.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379,127.0.0.2:2379" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().RegistryAddresses())
 	}
-	if strings.Join(registry.Configuration().Clusters["sc-0"], ",") != "127.0.0.1:2379,127.0.0.2:2379" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().Clusters)
+	if strings.Join(etcd.Configuration().Clusters["sc-0"], ",") != "127.0.0.1:2379,127.0.0.2:2379" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().Clusters)
 	}
-	registry.Configuration().ClusterName = "sc-0"
-	registry.Configuration().ClusterAddresses = "sc-1=127.0.0.1:2379,127.0.0.2:2379,sc-2=127.0.0.3:2379"
-	registry.Configuration().InitClusterInfo()
-	if strings.Join(registry.Configuration().RegistryAddresses(), ",") != "" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().RegistryAddresses())
+	etcd.Configuration().ClusterName = "sc-0"
+	etcd.Configuration().ClusterAddresses = "sc-1=127.0.0.1:2379,127.0.0.2:2379,sc-2=127.0.0.3:2379"
+	etcd.Configuration().InitClusterInfo()
+	if strings.Join(etcd.Configuration().RegistryAddresses(), ",") != "" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().RegistryAddresses())
 	}
-	if strings.Join(registry.Configuration().Clusters["sc-1"], ",") != "127.0.0.1:2379,127.0.0.2:2379" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().Clusters)
+	if strings.Join(etcd.Configuration().Clusters["sc-1"], ",") != "127.0.0.1:2379,127.0.0.2:2379" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().Clusters)
 	}
-	if strings.Join(registry.Configuration().Clusters["sc-2"], ",") != "127.0.0.3:2379" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().Clusters)
+	if strings.Join(etcd.Configuration().Clusters["sc-2"], ",") != "127.0.0.3:2379" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().Clusters)
 	}
-	registry.Configuration().ClusterName = "sc-0"
-	registry.Configuration().ClusterAddresses = "sc-0=127.0.0.1:2379,sc-1=127.0.0.3:2379,127.0.0.4:2379"
-	registry.Configuration().InitClusterInfo()
-	if strings.Join(registry.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().RegistryAddresses())
+	etcd.Configuration().ClusterName = "sc-0"
+	etcd.Configuration().ClusterAddresses = "sc-0=127.0.0.1:2379,sc-1=127.0.0.3:2379,127.0.0.4:2379"
+	etcd.Configuration().InitClusterInfo()
+	if strings.Join(etcd.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().RegistryAddresses())
 	}
-	if strings.Join(registry.Configuration().Clusters["sc-1"], ",") != "127.0.0.3:2379,127.0.0.4:2379" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().Clusters)
+	if strings.Join(etcd.Configuration().Clusters["sc-1"], ",") != "127.0.0.3:2379,127.0.0.4:2379" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().Clusters)
 	}
-	registry.Configuration().ClusterName = "sc-0"
-	registry.Configuration().ManagerAddress = "127.0.0.1:2379,127.0.0.2:2379"
-	registry.Configuration().ClusterAddresses = "sc-0=127.0.0.1:30100,sc-1=127.0.0.2:30100"
-	registry.Configuration().InitClusterInfo()
-	if strings.Join(registry.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379,127.0.0.2:2379" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().RegistryAddresses())
+	etcd.Configuration().ClusterName = "sc-0"
+	etcd.Configuration().ManagerAddress = "127.0.0.1:2379,127.0.0.2:2379"
+	etcd.Configuration().ClusterAddresses = "sc-0=127.0.0.1:30100,sc-1=127.0.0.2:30100"
+	etcd.Configuration().InitClusterInfo()
+	if strings.Join(etcd.Configuration().RegistryAddresses(), ",") != "127.0.0.1:2379,127.0.0.2:2379" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().RegistryAddresses())
 	}
-	if strings.Join(registry.Configuration().Clusters["sc-1"], ",") != "127.0.0.2:30100" {
-		t.Fatalf("TestInitCluster failed, %v", registry.Configuration().Clusters)
+	if strings.Join(etcd.Configuration().Clusters["sc-1"], ",") != "127.0.0.2:30100" {
+		t.Fatalf("TestInitCluster failed, %v", etcd.Configuration().Clusters)
 	}
 }
 
 func TestEtcdClient(t *testing.T) {
-	registry.Configuration().ClusterName = ""
-	registry.Configuration().ManagerAddress = ""
-	registry.Configuration().ClusterAddresses = endpoint
-	registry.Configuration().InitClusterInfo()
+	etcd.Configuration().ClusterName = ""
+	etcd.Configuration().ManagerAddress = ""
+	etcd.Configuration().ClusterAddresses = endpoint
+	etcd.Configuration().InitClusterInfo()
 
 	etcdc := &Client{
 		Endpoints:   []string{endpoint},
@@ -128,16 +129,16 @@ func TestEtcdClient(t *testing.T) {
 	}
 
 	// base test
-	inst := NewRegistry()
+	inst := NewRegistry(client.Options{})
 	if inst == nil || strings.Index(endpoint, firstEndpoint) < 0 {
 		t.Fatalf("TestEtcdClient failed, %s != %s", firstEndpoint, endpoint)
 	}
-	old1 := registry.Configuration().ClusterAddresses
-	old2 := registry.Configuration().DialTimeout
-	registry.Configuration().ClusterAddresses = "x"
-	registry.Configuration().InitClusterInfo()
-	registry.Configuration().DialTimeout = dialTimeout
-	inst = NewRegistry()
+	old1 := etcd.Configuration().ClusterAddresses
+	old2 := etcd.Configuration().DialTimeout
+	etcd.Configuration().ClusterAddresses = "x"
+	etcd.Configuration().InitClusterInfo()
+	etcd.Configuration().DialTimeout = dialTimeout
+	inst = NewRegistry(client.Options{})
 	if inst == nil {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
@@ -146,253 +147,253 @@ func TestEtcdClient(t *testing.T) {
 	default:
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
-	registry.Configuration().ClusterAddresses = old1
-	registry.Configuration().InitClusterInfo()
-	registry.Configuration().DialTimeout = old2
+	etcd.Configuration().ClusterAddresses = old1
+	etcd.Configuration().InitClusterInfo()
+	etcd.Configuration().DialTimeout = old2
 
 	// case: etcdc do
 	// put
-	resp, err := etcdc.Do(context.Background(), registry.PUT, registry.WithStrKey("/test_range/b"),
-		registry.WithStrValue("b"))
+	resp, err := etcdc.Do(context.Background(), client.PUT, client.WithStrKey("/test_range/b"),
+		client.WithStrValue("b"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/b"))
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/b"))
 	if err != nil || !resp.Succeeded || resp.Count != 1 ||
 		string(resp.Kvs[0].Key) != "/test_range/b" || string(resp.Kvs[0].Value) != "b" {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 
-	resp, err = etcdc.Do(context.Background(), registry.PUT, registry.WithStrKey("/test_range/a"),
-		registry.WithStrValue("a"))
+	resp, err = etcdc.Do(context.Background(), client.PUT, client.WithStrKey("/test_range/a"),
+		client.WithStrValue("a"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/a"),
-		registry.WithKeyOnly())
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/a"),
+		client.WithKeyOnly())
 	if err != nil || !resp.Succeeded || resp.Count != 1 ||
 		string(resp.Kvs[0].Key) != "/test_range/a" || resp.Kvs[0].Value != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/a"),
-		registry.WithCountOnly())
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/a"),
+		client.WithCountOnly())
 	if err != nil || !resp.Succeeded || resp.Count != 1 || resp.Kvs != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 
-	resp, err = etcdc.Do(context.Background(), registry.PUT, registry.WithStrKey("/test_range/c"),
-		registry.WithStrValue("c"))
+	resp, err = etcdc.Do(context.Background(), client.PUT, client.WithStrKey("/test_range/c"),
+		client.WithStrValue("c"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.PUT, registry.WithStrKey("/test_range/d"),
-		registry.WithStrValue("d"))
+	resp, err = etcdc.Do(context.Background(), client.PUT, client.WithStrKey("/test_range/d"),
+		client.WithStrValue("d"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.PUT, registry.WithStrKey("/test_range/dd"),
-		registry.WithStrValue("dd"))
+	resp, err = etcdc.Do(context.Background(), client.PUT, client.WithStrKey("/test_range/dd"),
+		client.WithStrValue("dd"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	// get prefix
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/d"),
-		registry.WithPrefix())
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/d"),
+		client.WithPrefix())
 	if err != nil || !resp.Succeeded || resp.Count != 2 ||
 		string(resp.Kvs[0].Key) != "/test_range/d" || string(resp.Kvs[0].Value) != "d" ||
 		string(resp.Kvs[1].Key) != "/test_range/dd" || string(resp.Kvs[1].Value) != "dd" {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/d"),
-		registry.WithPrefix(), registry.WithKeyOnly())
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/d"),
+		client.WithPrefix(), client.WithKeyOnly())
 	if err != nil || !resp.Succeeded || resp.Count != 2 ||
 		string(resp.Kvs[0].Key) != "/test_range/d" || resp.Kvs[0].Value != nil ||
 		string(resp.Kvs[1].Key) != "/test_range/dd" || resp.Kvs[1].Value != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/d"),
-		registry.WithPrefix(), registry.WithCountOnly())
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/d"),
+		client.WithPrefix(), client.WithCountOnly())
 	if err != nil || !resp.Succeeded || resp.Count != 2 || resp.Kvs != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	// get range
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/b"),
-		registry.WithStrEndKey("/test_range/dd")) // [b, dd) !!!
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/b"),
+		client.WithStrEndKey("/test_range/dd")) // [b, dd) !!!
 	if err != nil || !resp.Succeeded || resp.Count != 3 ||
 		string(resp.Kvs[0].Key) != "/test_range/b" || string(resp.Kvs[0].Value) != "b" ||
 		string(resp.Kvs[1].Key) != "/test_range/c" || string(resp.Kvs[1].Value) != "c" ||
 		string(resp.Kvs[2].Key) != "/test_range/d" || string(resp.Kvs[2].Value) != "d" {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/b"),
-		registry.WithStrEndKey("/test_range/dd"), registry.WithKeyOnly()) // [b, dd) !!!
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/b"),
+		client.WithStrEndKey("/test_range/dd"), client.WithKeyOnly()) // [b, dd) !!!
 	if err != nil || !resp.Succeeded || resp.Count != 3 ||
 		string(resp.Kvs[0].Key) != "/test_range/b" || resp.Kvs[0].Value != nil ||
 		string(resp.Kvs[1].Key) != "/test_range/c" || resp.Kvs[1].Value != nil ||
 		string(resp.Kvs[2].Key) != "/test_range/d" || resp.Kvs[2].Value != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/b"),
-		registry.WithStrEndKey("/test_range/dd"), registry.WithCountOnly()) // [b, dd) !!!
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/b"),
+		client.WithStrEndKey("/test_range/dd"), client.WithCountOnly()) // [b, dd) !!!
 	if err != nil || !resp.Succeeded || resp.Count != 3 || resp.Kvs != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	// get prefix paging
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/"), registry.WithPrefix(),
-		registry.WithOffset(2), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/"), client.WithPrefix(),
+		client.WithOffset(2), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 5 || len(resp.Kvs) != 2 ||
 		string(resp.Kvs[0].Key) != "/test_range/c" || string(resp.Kvs[0].Value) != "c" ||
 		string(resp.Kvs[1].Key) != "/test_range/d" || string(resp.Kvs[1].Value) != "d" {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/"), registry.WithPrefix(), registry.WithKeyOnly(),
-		registry.WithOffset(4), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/"), client.WithPrefix(), client.WithKeyOnly(),
+		client.WithOffset(4), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 5 || len(resp.Kvs) != 1 ||
 		string(resp.Kvs[0].Key) != "/test_range/dd" || resp.Kvs[0].Value != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/d"), registry.WithPrefix(), registry.WithKeyOnly(),
-		registry.WithOffset(0), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/d"), client.WithPrefix(), client.WithKeyOnly(),
+		client.WithOffset(0), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 2 || len(resp.Kvs) != 2 ||
 		string(resp.Kvs[0].Key) != "/test_range/d" || resp.Kvs[0].Value != nil ||
 		string(resp.Kvs[1].Key) != "/test_range/dd" || resp.Kvs[1].Value != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/"), registry.WithPrefix(), registry.WithCountOnly(),
-		registry.WithOffset(2), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/"), client.WithPrefix(), client.WithCountOnly(),
+		client.WithOffset(2), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 5 || resp.Kvs != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/"), registry.WithPrefix(),
-		registry.WithOffset(6), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/"), client.WithPrefix(),
+		client.WithOffset(6), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 5 || len(resp.Kvs) != 0 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	// if offset < -1, just paging by limit
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/"), registry.WithPrefix(),
-		registry.WithOffset(-2), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/"), client.WithPrefix(),
+		client.WithOffset(-2), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 5 || len(resp.Kvs) != 5 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	// get range paging
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/b"),
-		registry.WithStrEndKey("/test_range/dd"),
-		registry.WithOffset(2), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/b"),
+		client.WithStrEndKey("/test_range/dd"),
+		client.WithOffset(2), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 3 || len(resp.Kvs) != 1 ||
 		string(resp.Kvs[0].Key) != "/test_range/d" {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/a"),
-		registry.WithStrEndKey("/test_range/dd"),
-		registry.WithOffset(2), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/a"),
+		client.WithStrEndKey("/test_range/dd"),
+		client.WithOffset(2), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 4 || len(resp.Kvs) != 2 ||
 		string(resp.Kvs[0].Key) != "/test_range/c" ||
 		string(resp.Kvs[1].Key) != "/test_range/d" {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/a"),
-		registry.WithStrEndKey("/test_range/dd"), registry.WithKeyOnly(),
-		registry.WithOffset(2), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/a"),
+		client.WithStrEndKey("/test_range/dd"), client.WithKeyOnly(),
+		client.WithOffset(2), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 4 || len(resp.Kvs) != 2 ||
 		string(resp.Kvs[0].Key) != "/test_range/c" || resp.Kvs[0].Value != nil ||
 		string(resp.Kvs[1].Key) != "/test_range/d" || resp.Kvs[1].Value != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/a"),
-		registry.WithStrEndKey("/test_range/dd"), registry.WithCountOnly(),
-		registry.WithOffset(2), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/a"),
+		client.WithStrEndKey("/test_range/dd"), client.WithCountOnly(),
+		client.WithOffset(2), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 4 || resp.Kvs != nil {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/b"),
-		registry.WithStrEndKey("/test_range/dd"),
-		registry.WithOffset(5), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/b"),
+		client.WithStrEndKey("/test_range/dd"),
+		client.WithOffset(5), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 3 || len(resp.Kvs) != 0 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_range/a"),
-		registry.WithStrEndKey("/test_range/dd"),
-		registry.WithOffset(4), registry.WithLimit(2))
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_range/a"),
+		client.WithStrEndKey("/test_range/dd"),
+		client.WithOffset(4), client.WithLimit(2))
 	if err != nil || !resp.Succeeded || resp.Count != 4 || len(resp.Kvs) != 0 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	// delete range
-	resp, err = etcdc.Do(context.Background(), registry.DEL,
-		registry.WithStrKey("/test_range/b"),
-		registry.WithStrEndKey("/test_range/dd")) // [b, d) !!!
+	resp, err = etcdc.Do(context.Background(), client.DEL,
+		client.WithStrKey("/test_range/b"),
+		client.WithStrEndKey("/test_range/dd")) // [b, d) !!!
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Delete failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/"),
-		registry.WithPrefix())
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/"),
+		client.WithPrefix())
 	if err != nil || !resp.Succeeded || len(resp.Kvs) != 2 || string(resp.Kvs[1].Key) != "/test_range/dd" {
 		t.Fatalf("TestEtcdClient_Delete failed, %#v", resp.Kvs)
 	}
 	// delete prefix
-	resp, err = etcdc.Do(context.Background(), registry.DEL, registry.WithStrKey("/test_range/"),
-		registry.WithPrefix())
+	resp, err = etcdc.Do(context.Background(), client.DEL, client.WithStrKey("/test_range/"),
+		client.WithPrefix())
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Delete failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET, registry.WithStrKey("/test_range/"),
-		registry.WithPrefix())
+	resp, err = etcdc.Do(context.Background(), client.GET, client.WithStrKey("/test_range/"),
+		client.WithPrefix())
 	if err != nil || !resp.Succeeded || resp.Count != 0 {
 		t.Fatalf("TestEtcdClient_Delete failed, %#v", err)
 	}
 
 	// large data
 	var wg sync.WaitGroup
-	for i := 0; i < registry.DefaultPageCount+1; i++ {
+	for i := 0; i < client.DefaultPageCount+1; i++ {
 		wg.Add(1)
 		v := strconv.Itoa(i)
 		go func() {
 			defer wg.Done()
-			resp, err = etcdc.Do(context.Background(), registry.PUT, registry.WithStrKey("/test_page/"+v),
-				registry.WithStrValue(v))
+			resp, err = etcdc.Do(context.Background(), client.PUT, client.WithStrKey("/test_page/"+v),
+				client.WithStrValue(v))
 			if err != nil || !resp.Succeeded {
 				t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 			}
 		}()
 	}
 	wg.Wait()
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_page/"),
-		registry.WithStrEndKey("/test_page/9999"))
-	if err != nil || !resp.Succeeded || resp.Count != registry.DefaultPageCount+1 ||
-		len(resp.Kvs) != registry.DefaultPageCount+1 {
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_page/"),
+		client.WithStrEndKey("/test_page/9999"))
+	if err != nil || !resp.Succeeded || resp.Count != client.DefaultPageCount+1 ||
+		len(resp.Kvs) != client.DefaultPageCount+1 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_page/"), registry.WithPrefix(), registry.WithDescendOrder())
-	if err != nil || !resp.Succeeded || resp.Count != registry.DefaultPageCount+1 ||
-		len(resp.Kvs) != registry.DefaultPageCount+1 ||
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_page/"), client.WithPrefix(), client.WithDescendOrder())
+	if err != nil || !resp.Succeeded || resp.Count != client.DefaultPageCount+1 ||
+		len(resp.Kvs) != client.DefaultPageCount+1 ||
 		string(resp.Kvs[0].Key) != "/test_page/999" {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	// delete range
-	resp, err = etcdc.Do(context.Background(), registry.DEL,
-		registry.WithStrKey("/test_page/"),
-		registry.WithStrEndKey("/test_page/9999"))
+	resp, err = etcdc.Do(context.Background(), client.DEL,
+		client.WithStrKey("/test_page/"),
+		client.WithStrEndKey("/test_page/9999"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Delete failed, %#v", err)
 	}
-	resp, err = etcdc.Do(context.Background(), registry.GET,
-		registry.WithStrKey("/test_page/"), registry.WithPrefix())
+	resp, err = etcdc.Do(context.Background(), client.GET,
+		client.WithStrKey("/test_page/"), client.WithPrefix())
 	if err != nil || !resp.Succeeded || resp.Count != 0 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
@@ -435,67 +436,67 @@ func TestEtcdClient_Txn(t *testing.T) {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
 
-	success, err := etcd.PutNoOverride(context.Background(), registry.WithStrKey("/test_txn/a"))
+	success, err := etcd.PutNoOverride(context.Background(), client.WithStrKey("/test_txn/a"))
 	if err != nil || !success {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
-	success, err = etcd.PutNoOverride(context.Background(), registry.WithStrKey("/test_txn/a"), registry.WithStrValue("a"))
+	success, err = etcd.PutNoOverride(context.Background(), client.WithStrKey("/test_txn/a"), client.WithStrValue("a"))
 	if err != nil || success {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
 
-	resp, err = etcd.Txn(context.Background(), []registry.PluginOp{
-		{Action: registry.Put, Key: []byte("/test_txn/a"), Value: []byte("a")},
-		{Action: registry.Put, Key: []byte("/test_txn/b"), Value: []byte("b")},
+	resp, err = etcd.Txn(context.Background(), []client.PluginOp{
+		{Action: client.ActionPut, Key: []byte("/test_txn/a"), Value: []byte("a")},
+		{Action: client.ActionPut, Key: []byte("/test_txn/b"), Value: []byte("b")},
 	})
 	if err != nil || resp == nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
-	resp, err = etcd.Do(context.Background(), registry.GET, registry.WithStrKey("/test_txn/"),
-		registry.WithPrefix(), registry.WithCountOnly())
+	resp, err = etcd.Do(context.Background(), client.GET, client.WithStrKey("/test_txn/"),
+		client.WithPrefix(), client.WithCountOnly())
 	if err != nil || !resp.Succeeded || resp.Count != 2 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 
-	resp, err = etcd.TxnWithCmp(context.Background(), []registry.PluginOp{
-		{Action: registry.Put, Key: []byte("/test_txn/a"), Value: []byte("a")},
-		{Action: registry.Put, Key: []byte("/test_txn/b"), Value: []byte("b")},
-	}, []registry.CompareOp{
-		{[]byte("/test_txn/a"), registry.CmpValue, registry.CmpEqual, "a"},
-	}, []registry.PluginOp{
-		{Action: registry.Put, Key: []byte("/test_txn/c"), Value: []byte("c")},
-		{Action: registry.Put, Key: []byte("/test_txn/d"), Value: []byte("d")},
+	resp, err = etcd.TxnWithCmp(context.Background(), []client.PluginOp{
+		{Action: client.ActionPut, Key: []byte("/test_txn/a"), Value: []byte("a")},
+		{Action: client.ActionPut, Key: []byte("/test_txn/b"), Value: []byte("b")},
+	}, []client.CompareOp{
+		{[]byte("/test_txn/a"), client.CmpValue, client.CmpEqual, "a"},
+	}, []client.PluginOp{
+		{Action: client.ActionPut, Key: []byte("/test_txn/c"), Value: []byte("c")},
+		{Action: client.ActionPut, Key: []byte("/test_txn/d"), Value: []byte("d")},
 	})
 	if err != nil || resp == nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
 
 	// case: range request
-	resp, err = etcd.TxnWithCmp(context.Background(), nil, []registry.CompareOp{
-		{[]byte("/test_txn/c"), registry.CmpValue, registry.CmpEqual, "c"},
-	}, []registry.PluginOp{
-		{Action: registry.Get, Key: []byte("/test_txn/a")},
-		{Action: registry.Get, Key: []byte("/test_txn/"), Prefix: true},
+	resp, err = etcd.TxnWithCmp(context.Background(), nil, []client.CompareOp{
+		{[]byte("/test_txn/c"), client.CmpValue, client.CmpEqual, "c"},
+	}, []client.PluginOp{
+		{Action: client.ActionGet, Key: []byte("/test_txn/a")},
+		{Action: client.ActionGet, Key: []byte("/test_txn/"), Prefix: true},
 	})
 	if err != nil || resp == nil || resp.Succeeded || resp.Count != 3 { // a + [a,b]
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
 
 	// case: test key not exist
-	resp, err = etcd.TxnWithCmp(context.Background(), []registry.PluginOp{
-		{Action: registry.Put, Key: []byte("/test_txn/a"), Value: []byte("a")},
-		{Action: registry.Put, Key: []byte("/test_txn/b"), Value: []byte("b")},
-	}, []registry.CompareOp{
-		{[]byte("/test_txn/c"), registry.CmpValue, registry.CmpEqual, "c"},
-	}, []registry.PluginOp{
-		{Action: registry.Delete, Key: []byte("/test_txn/"), Prefix: true},
+	resp, err = etcd.TxnWithCmp(context.Background(), []client.PluginOp{
+		{Action: client.ActionPut, Key: []byte("/test_txn/a"), Value: []byte("a")},
+		{Action: client.ActionPut, Key: []byte("/test_txn/b"), Value: []byte("b")},
+	}, []client.CompareOp{
+		{[]byte("/test_txn/c"), client.CmpValue, client.CmpEqual, "c"},
+	}, []client.PluginOp{
+		{Action: client.ActionDelete, Key: []byte("/test_txn/"), Prefix: true},
 	})
 	if err != nil || resp == nil || resp.Succeeded {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
 
-	resp, err = etcd.Do(context.Background(), registry.GET, registry.WithStrKey("/test_txn/"),
-		registry.WithPrefix(), registry.WithCountOnly())
+	resp, err = etcd.Do(context.Background(), client.GET, client.WithStrKey("/test_txn/"),
+		client.WithPrefix(), client.WithCountOnly())
 	if err != nil || !resp.Succeeded || resp.Count != 0 {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
@@ -568,8 +569,8 @@ func TestEtcdClient_HealthCheck(t *testing.T) {
 	ctx, _ = context.WithTimeout(context.Background(), 1*time.Second)
 	go etcdc.healthCheckLoop(ctx)
 	for {
-		_, err = etcdc.Do(context.Background(), registry.GET,
-			registry.WithStrKey("/test_health/"))
+		_, err = etcdc.Do(context.Background(), client.GET,
+			client.WithStrKey("/test_health/"))
 		if err != nil {
 			time.Sleep(1 * time.Second)
 			continue
@@ -593,8 +594,8 @@ func TestEtcdClient_Watch(t *testing.T) {
 	defer etcd.Close()
 
 	defer func() {
-		resp, err := etcd.Do(context.Background(), registry.DEL, registry.WithStrKey("/test_watch/"),
-			registry.WithPrefix())
+		resp, err := etcd.Do(context.Background(), client.DEL, client.WithStrKey("/test_watch/"),
+			client.WithPrefix())
 		if err != nil || !resp.Succeeded {
 			t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 		}
@@ -602,7 +603,7 @@ func TestEtcdClient_Watch(t *testing.T) {
 
 	ctx, cancel := context.WithCancel(context.Background())
 	cancel()
-	err = etcd.Watch(ctx, registry.WithStrKey("/test_watch/a"))
+	err = etcd.Watch(ctx, client.WithStrKey("/test_watch/a"))
 	if err != nil {
 		t.Fatalf("TestEtcdClient failed, %#v", err)
 	}
@@ -610,9 +611,9 @@ func TestEtcdClient_Watch(t *testing.T) {
 	ch := make(chan struct{})
 	go func() {
 		defer func() { ch <- struct{}{} }()
-		err = etcd.Watch(context.Background(), registry.WithStrKey("/test_watch/a"),
-			registry.WithWatchCallback(func(message string, evt *registry.PluginResponse) error {
-				if evt.Count != 1 || len(evt.Kvs) != 1 || evt.Action != registry.Put ||
+		err = etcd.Watch(context.Background(), client.WithStrKey("/test_watch/a"),
+			client.WithWatchCallback(func(message string, evt *client.PluginResponse) error {
+				if evt.Count != 1 || len(evt.Kvs) != 1 || evt.Action != client.ActionPut ||
 					string(evt.Kvs[0].Key) != "/test_watch/a" || string(evt.Kvs[0].Value) != "a" {
 					t.Fatalf("TestEtcdClient failed, %#v", evt)
 				}
@@ -624,8 +625,8 @@ func TestEtcdClient_Watch(t *testing.T) {
 	}()
 
 	<-time.After(500 * time.Millisecond)
-	resp, err := etcd.Do(context.Background(), registry.PUT, registry.WithStrKey("/test_watch/a"),
-		registry.WithStrValue("a"))
+	resp, err := etcd.Do(context.Background(), client.PUT, client.WithStrKey("/test_watch/a"),
+		client.WithStrValue("a"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
@@ -633,11 +634,11 @@ func TestEtcdClient_Watch(t *testing.T) {
 
 	go func() {
 		defer func() { ch <- struct{}{} }()
-		err = etcd.Watch(context.Background(), registry.WithStrKey("/test_watch/"),
-			registry.WithPrefix(),
-			registry.WithWatchCallback(func(message string, evt *registry.PluginResponse) error {
-				equalA := evt.Action == registry.Put && string(evt.Kvs[0].Key) == "/test_watch/a" && string(evt.Kvs[0].Value) == "a"
-				equalB := evt.Action == registry.Put && string(evt.Kvs[1].Key) == "/test_watch/b" && string(evt.Kvs[0].Value) == "b"
+		err = etcd.Watch(context.Background(), client.WithStrKey("/test_watch/"),
+			client.WithPrefix(),
+			client.WithWatchCallback(func(message string, evt *client.PluginResponse) error {
+				equalA := evt.Action == client.ActionPut && string(evt.Kvs[0].Key) == "/test_watch/a" && string(evt.Kvs[0].Value) == "a"
+				equalB := evt.Action == client.ActionPut && string(evt.Kvs[1].Key) == "/test_watch/b" && string(evt.Kvs[0].Value) == "b"
 				if evt.Count != 2 || len(evt.Kvs) != 2 || !(equalA || equalB) {
 					t.Fatalf("TestEtcdClient failed, %#v", evt)
 				}
@@ -649,9 +650,9 @@ func TestEtcdClient_Watch(t *testing.T) {
 	}()
 
 	<-time.After(500 * time.Millisecond)
-	resp, err = etcd.Txn(context.Background(), []registry.PluginOp{
-		{Action: registry.Put, Key: []byte("/test_watch/a"), Value: []byte("a")},
-		{Action: registry.Put, Key: []byte("/test_watch/b"), Value: []byte("b")},
+	resp, err = etcd.Txn(context.Background(), []client.PluginOp{
+		{Action: client.ActionPut, Key: []byte("/test_watch/a"), Value: []byte("a")},
+		{Action: client.ActionPut, Key: []byte("/test_watch/b"), Value: []byte("b")},
 	})
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
@@ -662,12 +663,12 @@ func TestEtcdClient_Watch(t *testing.T) {
 	go func() {
 		defer func() { ch <- struct{}{} }()
 		var times = 3
-		err = etcd.Watch(context.Background(), registry.WithStrKey("/test_watch/"),
-			registry.WithPrefix(),
-			registry.WithWatchCallback(func(message string, evt *registry.PluginResponse) error {
-				equalA := evt.Action == registry.Delete && string(evt.Kvs[0].Key) == "/test_watch/a" && evt.Kvs[0].Value == nil
-				equalB := evt.Action == registry.Put && string(evt.Kvs[0].Key) == "/test_watch/b" && string(evt.Kvs[0].Value) == "b"
-				equalC := evt.Action == registry.Put && string(evt.Kvs[0].Key) == "/test_watch/c" && string(evt.Kvs[0].Value) == "c"
+		err = etcd.Watch(context.Background(), client.WithStrKey("/test_watch/"),
+			client.WithPrefix(),
+			client.WithWatchCallback(func(message string, evt *client.PluginResponse) error {
+				equalA := evt.Action == client.ActionDelete && string(evt.Kvs[0].Key) == "/test_watch/a" && evt.Kvs[0].Value == nil
+				equalB := evt.Action == client.ActionPut && string(evt.Kvs[0].Key) == "/test_watch/b" && string(evt.Kvs[0].Value) == "b"
+				equalC := evt.Action == client.ActionPut && string(evt.Kvs[0].Key) == "/test_watch/c" && string(evt.Kvs[0].Value) == "c"
 				if evt.Count != 1 || len(evt.Kvs) != 1 || !(equalA || equalB || equalC) {
 					t.Fatalf("TestEtcdClient failed, %#v", evt)
 				}
@@ -683,10 +684,10 @@ func TestEtcdClient_Watch(t *testing.T) {
 	}()
 
 	<-time.After(500 * time.Millisecond)
-	resp, err = etcd.Txn(context.Background(), []registry.PluginOp{
-		{Action: registry.Put, Key: []byte("/test_watch/c"), Value: []byte("c")},
-		{Action: registry.Delete, Key: []byte("/test_watch/a"), Value: []byte("a")},
-		{Action: registry.Put, Key: []byte("/test_watch/b"), Value: []byte("b")},
+	resp, err = etcd.Txn(context.Background(), []client.PluginOp{
+		{Action: client.ActionPut, Key: []byte("/test_watch/c"), Value: []byte("c")},
+		{Action: client.ActionDelete, Key: []byte("/test_watch/a"), Value: []byte("a")},
+		{Action: client.ActionPut, Key: []byte("/test_watch/b"), Value: []byte("b")},
 	})
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
@@ -694,19 +695,19 @@ func TestEtcdClient_Watch(t *testing.T) {
 	<-ch
 
 	// watch with rev
-	resp, err = etcd.Do(context.Background(), registry.DEL, registry.WithStrKey("/test_watch/c"),
-		registry.WithStrValue("a"))
+	resp, err = etcd.Do(context.Background(), client.DEL, client.WithStrKey("/test_watch/c"),
+		client.WithStrValue("a"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
 	rev := resp.Revision
 	go func() {
 		defer func() { ch <- struct{}{} }()
-		err = etcd.Watch(context.Background(), registry.WithStrKey("/test_watch/"),
-			registry.WithPrefix(),
-			registry.WithRev(rev),
-			registry.WithWatchCallback(func(message string, evt *registry.PluginResponse) error {
-				if evt.Count != 1 || len(evt.Kvs) != 1 || evt.Action != registry.Delete ||
+		err = etcd.Watch(context.Background(), client.WithStrKey("/test_watch/"),
+			client.WithPrefix(),
+			client.WithRev(rev),
+			client.WithWatchCallback(func(message string, evt *client.PluginResponse) error {
+				if evt.Count != 1 || len(evt.Kvs) != 1 || evt.Action != client.ActionDelete ||
 					string(evt.Kvs[0].Key) != "/test_watch/c" || evt.Kvs[0].Value != nil {
 					t.Fatalf("TestEtcdClient failed, %#v", evt)
 				}
@@ -721,10 +722,10 @@ func TestEtcdClient_Watch(t *testing.T) {
 	// delete with prevKV
 	go func() {
 		defer func() { ch <- struct{}{} }()
-		err = etcd.Watch(context.Background(), registry.WithStrKey("/test_watch/"),
-			registry.WithPrefix(), registry.WithPrevKv(),
-			registry.WithWatchCallback(func(message string, evt *registry.PluginResponse) error {
-				if len(evt.Kvs) != 1 || evt.Action != registry.Delete ||
+		err = etcd.Watch(context.Background(), client.WithStrKey("/test_watch/"),
+			client.WithPrefix(), client.WithPrevKv(),
+			client.WithWatchCallback(func(message string, evt *client.PluginResponse) error {
+				if len(evt.Kvs) != 1 || evt.Action != client.ActionDelete ||
 					string(evt.Kvs[0].Key) != "/test_watch/b" || string(evt.Kvs[0].Value) != "b" {
 					t.Fatalf("TestEtcdClient failed, %#v", evt)
 				}
@@ -735,7 +736,7 @@ func TestEtcdClient_Watch(t *testing.T) {
 		}
 	}()
 	<-time.After(500 * time.Millisecond)
-	resp, err = etcd.Do(context.Background(), registry.DEL, registry.WithStrKey("/test_watch/b"))
+	resp, err = etcd.Do(context.Background(), client.DEL, client.WithStrKey("/test_watch/b"))
 	if err != nil || !resp.Succeeded {
 		t.Fatalf("TestEtcdClient_Do failed, %#v", err)
 	}
@@ -824,9 +825,9 @@ func TestEtcdClient_paging(t *testing.T) {
 		},
 	}
 
-	op := registry.PluginOp{
+	op := client.PluginOp{
 		Offset: -1,
-		Limit:  registry.DefaultPageCount,
+		Limit:  client.DefaultPageCount,
 	}
 	r, err := c.paging(context2.Background(), op)
 	if err != nil {
diff --git a/server/plugin/registry/etcd/logger.go b/datasource/etcd/client/remote/logger.go
similarity index 99%
rename from server/plugin/registry/etcd/logger.go
rename to datasource/etcd/client/remote/logger.go
index 5f698c9..6196871 100644
--- a/server/plugin/registry/etcd/logger.go
+++ b/datasource/etcd/client/remote/logger.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package etcd
+package remote
 
 import (
 	"fmt"
diff --git a/server/plugin/registry/etcd/logger_test.go b/datasource/etcd/client/remote/logger_test.go
similarity index 98%
rename from server/plugin/registry/etcd/logger_test.go
rename to datasource/etcd/client/remote/logger_test.go
index b44f7e1..e3c5917 100644
--- a/server/plugin/registry/etcd/logger_test.go
+++ b/datasource/etcd/client/remote/logger_test.go
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package etcd
+package remote
 
 import "testing"
 
diff --git a/server/plugin/registry/etcd/tracing.go b/datasource/etcd/client/remote/tracing.go
similarity index 74%
rename from server/plugin/registry/etcd/tracing.go
rename to datasource/etcd/client/remote/tracing.go
index df65540..8ff4c12 100644
--- a/server/plugin/registry/etcd/tracing.go
+++ b/datasource/etcd/client/remote/tracing.go
@@ -15,29 +15,28 @@
  * limitations under the License.
  */
 
-package etcd
+package remote
 
 import (
 	"context"
-	"github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 	"github.com/apache/servicecomb-service-center/server/plugin/tracing"
 	"net/http"
 )
 
-func TracingBegin(ctx context.Context, operationName string, op registry.PluginOp) tracing.Span {
+func TracingBegin(ctx context.Context, operationName string, op client.PluginOp) tracing.Span {
 	r := &tracing.RegistryRequest{
 		Ctx:      ctx,
 		Options:  op,
 		Endpoint: firstEndpoint,
 	}
-	return plugin.Plugins().Tracing().ClientBegin(operationName, r)
+	return tracing.ClientBegin(operationName, r)
 }
 
 func TracingEnd(span tracing.Span, err error) {
 	if err != nil {
-		plugin.Plugins().Tracing().ClientEnd(span, http.StatusInternalServerError, err.Error())
+		tracing.ClientEnd(span, http.StatusInternalServerError, err.Error())
 		return
 	}
-	plugin.Plugins().Tracing().ClientEnd(span, http.StatusOK, "")
+	tracing.ClientEnd(span, http.StatusOK, "")
 }
diff --git a/server/plugin/registry/types.go b/datasource/etcd/client/types.go
similarity index 69%
rename from server/plugin/registry/types.go
rename to datasource/etcd/client/types.go
index 35458cd..ae9f1bc 100644
--- a/server/plugin/registry/types.go
+++ b/datasource/etcd/client/types.go
@@ -1,19 +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.
-
-package registry
+/*
+ * 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 client
 
 import (
 	"fmt"
@@ -21,15 +23,17 @@ import (
 	"strconv"
 )
 
+type ImplName string
+
 type ActionType int
 
 func (at ActionType) String() string {
 	switch at {
-	case Get:
+	case ActionGet:
 		return "GET"
-	case Put:
+	case ActionPut:
 		return "PUT"
-	case Delete:
+	case ActionDelete:
 		return "DELETE"
 	default:
 		return "ACTION" + strconv.Itoa(int(at))
diff --git a/datasource/etcd/config.go b/datasource/etcd/config.go
new file mode 100644
index 0000000..a16ec9a
--- /dev/null
+++ b/datasource/etcd/config.go
@@ -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 etcd
+
+import (
+	"context"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/apache/servicecomb-service-center/server/core"
+	"github.com/astaxie/beego"
+	"strings"
+	"sync"
+	"time"
+)
+
+var (
+	defaultRegistryConfig client.Config
+	configOnce            sync.Once
+)
+
+func Configuration() *client.Config {
+	configOnce.Do(func() {
+		var err error
+		defaultRegistryConfig.ClusterName = beego.AppConfig.DefaultString("manager_name", client.DefaultClusterName)
+		defaultRegistryConfig.ManagerAddress = beego.AppConfig.String("manager_addr")
+		defaultRegistryConfig.ClusterAddresses = beego.AppConfig.DefaultString("manager_cluster", "http://127.0.0.1:2379")
+		defaultRegistryConfig.InitClusterInfo()
+
+		registryAddresses := strings.Join(defaultRegistryConfig.RegistryAddresses(), ",")
+		defaultRegistryConfig.SslEnabled = core.ServerInfo.Config.SslEnabled &&
+			strings.Contains(strings.ToLower(registryAddresses), "https://")
+
+		defaultRegistryConfig.DialTimeout, err = time.ParseDuration(beego.AppConfig.DefaultString("connect_timeout", "10s"))
+		if err != nil {
+			log.Errorf(err, "connect_timeout is invalid, use default time %s", client.DefaultDialTimeout)
+			defaultRegistryConfig.DialTimeout = client.DefaultDialTimeout
+		}
+		defaultRegistryConfig.RequestTimeOut, err = time.ParseDuration(beego.AppConfig.DefaultString("registry_timeout", "30s"))
+		if err != nil {
+			log.Errorf(err, "registry_timeout is invalid, use default time %s", client.DefaultRequestTimeout)
+			defaultRegistryConfig.RequestTimeOut = client.DefaultRequestTimeout
+		}
+		defaultRegistryConfig.AutoSyncInterval, err = time.ParseDuration(core.ServerInfo.Config.AutoSyncInterval)
+		if err != nil {
+			log.Errorf(err, "auto_sync_interval is invalid")
+		}
+
+		core.ServerInfo.Config.Plugins.Object("discovery").
+			Set("config", defaultRegistryConfig)
+	})
+	return &defaultRegistryConfig
+}
+
+func WithTimeout(ctx context.Context) (context.Context, context.CancelFunc) {
+	return context.WithTimeout(ctx, defaultRegistryConfig.RequestTimeOut)
+}
diff --git a/datasource/etcd/dep.go b/datasource/etcd/dep.go
index 36c6666..c77396b 100644
--- a/datasource/etcd/dep.go
+++ b/datasource/etcd/dep.go
@@ -21,14 +21,13 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 	serviceUtil "github.com/apache/servicecomb-service-center/datasource/etcd/util"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	pb "github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	apt "github.com/apache/servicecomb-service-center/server/core"
-	"github.com/apache/servicecomb-service-center/server/core/backend"
 	"github.com/apache/servicecomb-service-center/server/core/proto"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 	scerr "github.com/apache/servicecomb-service-center/server/scerror"
 )
 
@@ -75,7 +74,7 @@ func (ds *DataSource) DeleteDependency() {
 }
 
 func (ds *DataSource) AddOrUpdateDependencies(ctx context.Context, dependencyInfos []*pb.ConsumerDependency, override bool) (*pb.Response, error) {
-	opts := make([]registry.PluginOp, 0, len(dependencyInfos))
+	opts := make([]client.PluginOp, 0, len(dependencyInfos))
 	domainProject := util.ParseDomainProject(ctx)
 	for _, dependencyInfo := range dependencyInfos {
 		consumerFlag := util.StringJoin([]string{dependencyInfo.Consumer.Environment, dependencyInfo.Consumer.AppId, dependencyInfo.Consumer.ServiceName, dependencyInfo.Consumer.Version}, "/")
@@ -114,10 +113,10 @@ func (ds *DataSource) AddOrUpdateDependencies(ctx context.Context, dependencyInf
 			id = util.GenerateUUID()
 		}
 		key := GenerateConsumerDependencyQueueKey(domainProject, consumerID, id)
-		opts = append(opts, registry.OpPut(registry.WithStrKey(key), registry.WithValue(data)))
+		opts = append(opts, client.OpPut(client.WithStrKey(key), client.WithValue(data)))
 	}
 
-	err := backend.BatchCommit(ctx, opts)
+	err := client.BatchCommit(ctx, opts)
 	if err != nil {
 		log.Errorf(err, "put request into dependency queue failed, override: %t, %v", override, dependencyInfos)
 		return proto.CreateResponse(scerr.ErrInternal, err.Error()), err
@@ -125,5 +124,5 @@ func (ds *DataSource) AddOrUpdateDependencies(ctx context.Context, dependencyInf
 
 	log.Infof("put request into dependency queue successfully, override: %t, %v, from remote %s",
 		override, dependencyInfos, util.GetIPFromContext(ctx))
-	return proto.CreateResponse(proto.Response_SUCCESS, "Create dependency successfully."), nil
+	return proto.CreateResponse(proto.ResponseSuccess, "Create dependency successfully."), nil
 }
diff --git a/datasource/etcd/dep_test.go b/datasource/etcd/dep_test.go
index 64ef8c5..c475e4e 100644
--- a/datasource/etcd/dep_test.go
+++ b/datasource/etcd/dep_test.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package etcd
+package etcd_test
 
 import (
 	"github.com/apache/servicecomb-service-center/datasource"
@@ -23,7 +23,6 @@ import (
 	"github.com/apache/servicecomb-service-center/server/core/proto"
 	scerr "github.com/apache/servicecomb-service-center/server/scerror"
 	"github.com/apache/servicecomb-service-center/server/service/event"
-	"github.com/go-chassis/go-archaius"
 	"github.com/stretchr/testify/assert"
 	"testing"
 )
@@ -31,17 +30,6 @@ import (
 var deh event.DependencyEventHandler
 
 func Test_Creat(t *testing.T) {
-
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		consumerId1 string
 		consumerId2 string
@@ -59,7 +47,7 @@ func Test_Creat(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		consumerId1 = resp.ServiceId
 
 		resp, err = datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
@@ -73,7 +61,7 @@ func Test_Creat(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		consumerId3 = resp.ServiceId
 
 		resp, err = datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
@@ -88,7 +76,7 @@ func Test_Creat(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		consumerId2 = resp.ServiceId
 
 		resp, err = datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
@@ -102,7 +90,7 @@ func Test_Creat(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
@@ -115,7 +103,7 @@ func Test_Creat(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
@@ -129,7 +117,7 @@ func Test_Creat(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("when request is invalid, should be failed", func(t *testing.T) {
@@ -179,7 +167,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		// consumer in diff env
 		consumer.Environment = pb.ENV_PROD
@@ -197,7 +185,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -238,7 +226,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -264,7 +252,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -292,7 +280,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		respPro, err = datasource.Instance().SearchConsumerDependency(depGetContext(), &pb.GetDependenciesRequest{
 			ServiceId: consumerId3,
@@ -314,7 +302,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		// add multiple providers
 		resp, err = datasource.Instance().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
@@ -334,7 +322,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		// add 1.0.0-2.0.0 to override *
 		resp, err = datasource.Instance().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
@@ -351,7 +339,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -377,7 +365,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, respAdd)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAdd.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAdd.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -396,7 +384,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		resp, err = datasource.Instance().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
 			{
@@ -405,7 +393,7 @@ func Test_Creat(t *testing.T) {
 		}, false)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -418,16 +406,6 @@ func Test_Creat(t *testing.T) {
 }
 
 func Test_Get(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		consumerId1 string
 		providerId1 string
@@ -446,7 +424,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		consumerId1 = resp.ServiceId
 
 		resp, err = datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
@@ -460,7 +438,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		providerId1 = resp.ServiceId
 
 		resp, err = datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
@@ -474,7 +452,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		providerId2 = resp.ServiceId
 	})
 
@@ -504,7 +482,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -531,7 +509,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -564,7 +542,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, respCreateF)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateF.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateF.Response.GetCode())
 		finder1 := respCreateF.ServiceId
 
 		resp, err = datasource.Instance().FindInstances(depGetContext(), &pb.FindInstancesRequest{
@@ -575,7 +553,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -593,7 +571,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, respDelP)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respDelP.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respDelP.Response.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
@@ -616,7 +594,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, respCreateF)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateF.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateF.Response.GetCode())
 
 		resp, err = datasource.Instance().FindInstances(depGetContext(), &pb.FindInstancesRequest{
 			ConsumerServiceId: providerId2,
@@ -626,7 +604,7 @@ func Test_Get(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		assert.Equal(t, nil, deh.Handle())
 
diff --git a/datasource/etcd/engine.go b/datasource/etcd/engine.go
new file mode 100644
index 0000000..fcf0b20
--- /dev/null
+++ b/datasource/etcd/engine.go
@@ -0,0 +1,256 @@
+/*
+ * 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 etcd
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource"
+	"github.com/apache/servicecomb-service-center/pkg/gopool"
+	"github.com/apache/servicecomb-service-center/pkg/types"
+	"github.com/apache/servicecomb-service-center/server/core/proto"
+	"strconv"
+	"strings"
+	"time"
+
+	serviceUtil "github.com/apache/servicecomb-service-center/datasource/etcd/util"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	pb "github.com/apache/servicecomb-service-center/pkg/registry"
+	"github.com/apache/servicecomb-service-center/pkg/util"
+	"github.com/apache/servicecomb-service-center/server/core"
+)
+
+func (ds *DataSource) SelfRegister(ctx context.Context) error {
+	err := ds.registryService(ctx)
+	if err != nil {
+		return err
+	}
+	// 实例信息
+	err = ds.registryInstance(ctx)
+	// start send heart beat job
+	ds.autoSelfHeartBeat()
+	// report the metrics
+	datasource.ReportScInstance()
+	return err
+}
+
+func (ds *DataSource) registryService(pCtx context.Context) error {
+	ctx := core.AddDefaultContextValue(pCtx)
+	respE, err := core.ServiceAPI.Exist(ctx, core.GetExistenceRequest())
+	if err != nil {
+		log.Error("query service center existence failed", err)
+		return err
+	}
+	if respE.Response.GetCode() == proto.ResponseSuccess {
+		log.Warnf("service center service[%s] already registered", respE.ServiceId)
+		respG, err := core.ServiceAPI.GetOne(ctx, core.GetServiceRequest(respE.ServiceId))
+		if respG.Response.GetCode() != proto.ResponseSuccess {
+			log.Errorf(err, "query service center service[%s] info failed", respE.ServiceId)
+			return fmt.Errorf("service center service file lost")
+		}
+		core.Service = respG.Service
+		return nil
+	}
+
+	respS, err := core.ServiceAPI.Create(ctx, core.CreateServiceRequest())
+	if err != nil {
+		log.Error("register service center failed", err)
+		return err
+	}
+	core.Service.ServiceId = respS.ServiceId
+	log.Infof("register service center service[%s]", respS.ServiceId)
+	return nil
+}
+
+func (ds *DataSource) registryInstance(pCtx context.Context) error {
+	core.Instance.InstanceId = ""
+	core.Instance.ServiceId = core.Service.ServiceId
+
+	ctx := core.AddDefaultContextValue(pCtx)
+
+	respI, err := core.InstanceAPI.Register(ctx, core.RegisterInstanceRequest())
+	if err != nil {
+		log.Error("register failed", err)
+		return err
+	}
+	if respI.Response.GetCode() != proto.ResponseSuccess {
+		err = fmt.Errorf("register service center[%s] instance failed, %s",
+			core.Instance.ServiceId, respI.Response.GetMessage())
+		log.Error(err.Error(), nil)
+		return err
+	}
+	core.Instance.InstanceId = respI.InstanceId
+	log.Infof("register service center instance[%s/%s], endpoints is %s",
+		core.Service.ServiceId, respI.InstanceId, core.Instance.Endpoints)
+	return nil
+}
+
+func (ds *DataSource) SelfUnregister(pCtx context.Context) error {
+	if len(core.Instance.InstanceId) == 0 {
+		return nil
+	}
+	ctx := core.AddDefaultContextValue(pCtx)
+	respI, err := core.InstanceAPI.Unregister(ctx, core.UnregisterInstanceRequest())
+	if err != nil {
+		log.Error("unregister failed", err)
+		return err
+	}
+	if respI.Response.GetCode() != proto.ResponseSuccess {
+		err = fmt.Errorf("unregister service center instance[%s/%s] failed, %s",
+			core.Instance.ServiceId, core.Instance.InstanceId, respI.Response.GetMessage())
+		log.Error(err.Error(), nil)
+		return err
+	}
+	log.Warnf("unregister service center instance[%s/%s]",
+		core.Service.ServiceId, core.Instance.InstanceId)
+	return nil
+}
+
+func (ds *DataSource) selfHeartBeat(pCtx context.Context) error {
+	ctx := core.AddDefaultContextValue(pCtx)
+	respI, err := core.InstanceAPI.Heartbeat(ctx, core.HeartbeatRequest())
+	if err != nil {
+		log.Error("sen heartbeat failed", err)
+		return err
+	}
+	if respI.Response.GetCode() == proto.ResponseSuccess {
+		log.Debugf("update service center instance[%s/%s] heartbeat",
+			core.Instance.ServiceId, core.Instance.InstanceId)
+		return nil
+	}
+	log.Errorf(err, "update service center instance[%s/%s] heartbeat failed",
+		core.Instance.ServiceId, core.Instance.InstanceId)
+
+	//服务不存在,创建服务
+	err = ds.SelfRegister(pCtx)
+	if err != nil {
+		log.Errorf(err, "retry to register[%s/%s/%s/%s] failed",
+			core.Service.Environment, core.Service.AppId, core.Service.ServiceName, core.Service.Version)
+	}
+	return err
+}
+
+func (ds *DataSource) autoSelfHeartBeat() {
+	gopool.Go(func(ctx context.Context) {
+		for {
+			select {
+			case <-ctx.Done():
+				return
+			case <-time.After(time.Duration(core.Instance.HealthCheck.Interval) * time.Second):
+				_ = ds.selfHeartBeat(ctx)
+			}
+		}
+	})
+}
+
+// ClearNoInstanceService clears services which have no instance
+func (ds *DataSource) ClearNoInstanceServices(ctx context.Context, serviceTTL time.Duration) error {
+	services, err := serviceUtil.GetAllServicesAcrossDomainProject(ctx)
+	if err != nil {
+		return err
+	}
+	if len(services) == 0 {
+		log.Info("no service found, no need to clear")
+		return nil
+	}
+	timeLimit := time.Now().Add(0 - serviceTTL)
+	log.Infof("clear no-instance services created before %s", timeLimit)
+	timeLimitStamp := strconv.FormatInt(timeLimit.Unix(), 10)
+
+	for domainProject, svcList := range services {
+		if len(svcList) == 0 {
+			continue
+		}
+		ctx, err := ctxFromDomainProject(ctx, domainProject)
+		if err != nil {
+			log.Errorf(err, "get domain project context failed")
+			continue
+		}
+		for _, svc := range svcList {
+			if svc == nil {
+				continue
+			}
+			ok, err := shouldClear(ctx, timeLimitStamp, svc)
+			if err != nil {
+				log.Errorf(err, "check service clear necessity failed")
+				continue
+			}
+			if !ok {
+				continue
+			}
+			//delete this service
+			svcCtxStr := "domainProject: " + domainProject + ", " +
+				"env: " + svc.Environment + ", " +
+				"service: " + util.StringJoin([]string{svc.AppId, svc.ServiceName, svc.Version}, core.SPLIT)
+			delSvcReq := &pb.DeleteServiceRequest{
+				ServiceId: svc.ServiceId,
+				Force:     true, //force delete
+			}
+			delSvcResp, err := core.ServiceAPI.Delete(ctx, delSvcReq)
+			if err != nil {
+				log.Errorf(err, "clear service failed, %s", svcCtxStr)
+				continue
+			}
+			if delSvcResp.Response.GetCode() != proto.ResponseSuccess {
+				log.Errorf(nil, "clear service failed, %s, %s", delSvcResp.Response.GetMessage(), svcCtxStr)
+				continue
+			}
+			log.Warnf("clear service success, %s", svcCtxStr)
+		}
+	}
+	return nil
+}
+
+func ctxFromDomainProject(pCtx context.Context, domainProject string) (ctx context.Context, err error) {
+	splitIndex := strings.Index(domainProject, core.SPLIT)
+	if splitIndex == -1 {
+		return nil, errors.New("invalid domainProject: " + domainProject)
+	}
+	domain := domainProject[:splitIndex]
+	project := domainProject[splitIndex+1:]
+	return util.SetDomainProject(pCtx, domain, project), nil
+}
+
+//check whether a service should be cleared
+func shouldClear(ctx context.Context, timeLimitStamp string, svc *pb.MicroService) (bool, error) {
+	//ignore a service if it is created after timeLimitStamp
+	if svc.Timestamp > timeLimitStamp {
+		return false, nil
+	}
+	getInstsReq := &pb.GetInstancesRequest{
+		ConsumerServiceId: svc.ServiceId,
+		ProviderServiceId: svc.ServiceId,
+	}
+	getInstsResp, err := core.InstanceAPI.GetInstances(ctx, getInstsReq)
+	if err != nil {
+		return false, err
+	}
+	if getInstsResp.Response.GetCode() != proto.ResponseSuccess {
+		return false, errors.New("get instance failed: " + getInstsResp.Response.GetMessage())
+	}
+	//ignore a service if it has instances
+	if len(getInstsResp.Instances) > 0 {
+		return false, nil
+	}
+	return true, nil
+}
+
+func (ds *DataSource) GetClusters(ctx context.Context) (types.Clusters, error) {
+	return Configuration().Clusters, nil
+}
diff --git a/server/task/clear_service_test.go b/datasource/etcd/engine_test.go
similarity index 65%
rename from server/task/clear_service_test.go
rename to datasource/etcd/engine_test.go
index e9b7b05..28eab3c 100644
--- a/server/task/clear_service_test.go
+++ b/datasource/etcd/engine_test.go
@@ -1,58 +1,42 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package task_test
+/*
+ * 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 etcd_test
 
 // initialize
-import (
-	_ "github.com/apache/servicecomb-service-center/server/bootstrap"
-	"github.com/apache/servicecomb-service-center/server/core/proto"
-)
+import _ "github.com/apache/servicecomb-service-center/datasource/etcd/client/buildin"
 import _ "github.com/apache/servicecomb-service-center/server"
 
 import (
 	"context"
 	"fmt"
-	"testing"
 	"time"
 
+	"github.com/apache/servicecomb-service-center/datasource"
 	pb "github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	apt "github.com/apache/servicecomb-service-center/server/core"
-	"github.com/apache/servicecomb-service-center/server/task"
-	"github.com/astaxie/beego"
-
+	"github.com/apache/servicecomb-service-center/server/core/proto"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 )
 
-func init() {
-	testing.Init()
-	apt.Initialize()
-}
-
-var _ = BeforeSuite(func() {
-	beego.AppConfig.Set("registry_plugin", "etcd")
-	//clear service created in last test
-	time.Sleep(timeLimit)
-	task.ClearNoInstanceServices(timeLimit)
-})
-
 // map[domainProject][serviceName]*serviceCleanInfo
 var svcCleanInfos = make(map[string]map[string]*serviceCleanInfo)
-var timeLimit = 2 * time.Second
 
 type serviceCleanInfo struct {
 	ServiceName  string
@@ -61,12 +45,7 @@ type serviceCleanInfo struct {
 	ShouldClear  bool
 }
 
-func TestTask(t *testing.T) {
-	RegisterFailHandler(Fail)
-	RunSpecs(t, "Task Suite")
-}
-
-func getContext(domain string, project string) context.Context {
+func getContextWith(domain string, project string) context.Context {
 	return util.SetContext(
 		util.SetDomainProject(context.Background(), domain, project),
 		util.CtxNocache, "1")
@@ -89,11 +68,11 @@ func createService(domain string, project string, name string, withInstance bool
 			},
 		}
 	}
-	ctx := getContext(domain, project)
+	ctx := getContextWith(domain, project)
 	svcResp, err := apt.ServiceAPI.Create(ctx, svc)
 	Expect(err).To(BeNil())
 	Expect(svcResp).NotTo(BeNil())
-	Expect(svcResp.Response.GetCode()).To(Equal(proto.Response_SUCCESS))
+	Expect(svcResp.Response.GetCode()).To(Equal(proto.ResponseSuccess))
 	info := &serviceCleanInfo{
 		ServiceName:  name,
 		ServiceId:    svcResp.ServiceId,
@@ -117,11 +96,11 @@ func checkServiceCleared(domain string, project string) {
 		getSvcReq := &pb.GetServiceRequest{
 			ServiceId: v.ServiceId,
 		}
-		ctx := getContext(domain, project)
+		ctx := getContextWith(domain, project)
 		getSvcResp, err := apt.ServiceAPI.GetOne(ctx, getSvcReq)
 		Expect(err).To(BeNil())
 		Expect(getSvcResp).NotTo(BeNil())
-		Expect(getSvcResp.Response.GetCode() == proto.Response_SUCCESS).To(Equal(!v.ShouldClear))
+		Expect(getSvcResp.Response.GetCode() == proto.ResponseSuccess).To(Equal(!v.ShouldClear))
 	}
 }
 
@@ -140,7 +119,7 @@ func serviceClearCheckFunc(domain string, project string) func() {
 			createService(domain, project, "svc3", withNoInstance, shouldNotClear)
 			createService(domain, project, "svc4", withInstance, shouldNotClear)
 
-			err = task.ClearNoInstanceServices(timeLimit)
+			err = datasource.Instance().ClearNoInstanceServices(context.Background(), timeLimit)
 			Expect(err).To(BeNil())
 
 			checkServiceCleared(domain, project)
@@ -152,7 +131,3 @@ var _ = Describe("clear service", func() {
 	Describe("domain project 1", serviceClearCheckFunc("default1", "default"))
 	Describe("domain project 2", serviceClearCheckFunc("default2", "default"))
 })
-var _ = func() bool {
-
-	return true
-}()
diff --git a/datasource/etcd/etcd.go b/datasource/etcd/etcd.go
index 6b5cdab..e31c169 100644
--- a/datasource/etcd/etcd.go
+++ b/datasource/etcd/etcd.go
@@ -16,42 +16,107 @@
 package etcd
 
 import (
-	"errors"
+	"context"
 	"github.com/apache/servicecomb-service-center/datasource"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/job"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/kv"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/mux"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
+	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/log"
+	"time"
 )
 
-// TODO: define error with names here
-
-var ErrNotUnique = errors.New("kv result is not unique")
-
 func init() {
-	// TODO: set logger
-	// TODO: register storage plugin to plugin manager
+	datasource.Install("etcd", NewDataSource)
+	datasource.Install("embeded_etcd", NewDataSource)
 }
 
 type DataSource struct {
-	// schemaEditable determines whether schema modification is allowed for
+	// SchemaEditable determines whether schema modification is allowed for
 	SchemaEditable bool
-	ttlFromEnv     int64
+	// TTL options
+	ttlFromEnv int64
+	// Compact options
+	CompactIndexDelta int64
+	CompactInterval   time.Duration
 }
 
-func NewDataSource(opts datasource.Options) *DataSource {
+func NewDataSource(opts datasource.Options) (datasource.DataSource, error) {
 	// TODO: construct a reasonable DataSource instance
 	log.Warnf("dependency data source enable etcd mode")
 
 	inst := &DataSource{
-		SchemaEditable: opts.SchemaEditable,
-		ttlFromEnv:     opts.TTL,
+		SchemaEditable:    opts.SchemaEditable,
+		ttlFromEnv:        opts.TTL,
+		CompactInterval:   opts.CompactInterval,
+		CompactIndexDelta: opts.CompactIndexDelta,
 	}
 	// TODO: deal with exception
 	if err := inst.initialize(); err != nil {
-		return inst
+		return nil, err
 	}
-	return inst
+	return inst, nil
 }
 
 func (ds *DataSource) initialize() error {
 	// TODO: init dependency members
+	// init client/sd plugins
+	ds.initPlugins()
+	// Wait for kv store ready
+	ds.initKvStore()
+	// Compact
+	ds.autoCompact()
+	// Jobs
+	job.ClearNoInstanceServices()
 	return nil
 }
+
+func (ds *DataSource) initPlugins() {
+	err := client.Init(client.Options{PluginImplName: "etcd"})
+	if err != nil {
+		log.Fatalf(err, "client init failed")
+	}
+	err = sd.Init(sd.Options{PluginImplName: "etcd"})
+	if err != nil {
+		log.Fatalf(err, "sd init failed")
+	}
+}
+
+func (ds *DataSource) initKvStore() {
+	kv.Store().Run()
+	<-kv.Store().Ready()
+}
+
+func (ds *DataSource) autoCompact() {
+	delta := ds.CompactIndexDelta
+	interval := ds.CompactInterval
+	if delta <= 0 || interval == 0 {
+		return
+	}
+	gopool.Go(func(ctx context.Context) {
+		log.Infof("enabled the automatic compact mechanism, compact once every %s, reserve %d", interval, delta)
+		for {
+			select {
+			case <-ctx.Done():
+				return
+			case <-time.After(interval):
+				lock, err := mux.Try(mux.GlobalLock)
+				if err != nil {
+					log.Errorf(err, "can not compact backend by this service center instance now")
+					continue
+				}
+
+				err = client.Instance().Compact(ctx, delta)
+				if err != nil {
+					log.Error("", err)
+				}
+
+				if err := lock.Unlock(); err != nil {
+					log.Error("", err)
+				}
+			}
+		}
+	})
+}
diff --git a/datasource/etcd/etcd_suite_test.go b/datasource/etcd/etcd_suite_test.go
index aa275a0..6883921 100644
--- a/datasource/etcd/etcd_suite_test.go
+++ b/datasource/etcd/etcd_suite_test.go
@@ -14,16 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package etcd
+package etcd_test
 
 // initialize
-import (
-	_ "github.com/apache/servicecomb-service-center/server/bootstrap"
-	"github.com/apache/servicecomb-service-center/server/core/proto"
-	"github.com/apache/servicecomb-service-center/server/service"
-)
+import _ "github.com/apache/servicecomb-service-center/server/bootstrap"
 import (
 	"context"
+	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/core"
 	"github.com/astaxie/beego"
@@ -31,21 +28,22 @@ import (
 	"github.com/onsi/ginkgo/reporters"
 	. "github.com/onsi/gomega"
 	"testing"
+	"time"
 )
 
-var serviceResource proto.ServiceCtrlServer
-var instanceResource proto.ServiceInstanceCtrlServerEx
+var timeLimit = 2 * time.Second
 
 func init() {
 	beego.AppConfig.Set("registry_plugin", "etcd")
 	testing.Init()
-	core.Initialize()
 }
 
 var _ = BeforeSuite(func() {
 	//init plugin
 	core.ServerInfo.Config.EnableCache = false
-	serviceResource, instanceResource = service.AssembleResources()
+	//clear service created in last test
+	time.Sleep(timeLimit)
+	_ = datasource.Instance().ClearNoInstanceServices(context.Background(), timeLimit)
 })
 
 func getContext() context.Context {
@@ -60,8 +58,8 @@ func depGetContext() context.Context {
 		util.CtxNocache, "1")
 }
 
-func TestGrpc(t *testing.T) {
+func TestEtcd(t *testing.T) {
 	RegisterFailHandler(Fail)
-	junitReporter := reporters.NewJUnitReporter("model.junit.xml")
-	RunSpecsWithDefaultAndCustomReporters(t, "model Suite", []Reporter{junitReporter})
+	junitReporter := reporters.NewJUnitReporter("etcd.junit.xml")
+	RunSpecsWithDefaultAndCustomReporters(t, "etcd Suite", []Reporter{junitReporter})
 }
diff --git a/datasource/etcd/job/job.go b/datasource/etcd/job/job.go
new file mode 100644
index 0000000..91aeffb
--- /dev/null
+++ b/datasource/etcd/job/job.go
@@ -0,0 +1,62 @@
+/*
+ * 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 job
+
+import (
+	"context"
+	"github.com/apache/servicecomb-service-center/datasource"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/mux"
+	"github.com/apache/servicecomb-service-center/pkg/gopool"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/apache/servicecomb-service-center/server/core"
+	"time"
+)
+
+// clear services who have no instance
+func ClearNoInstanceServices() {
+	if !core.ServerInfo.Config.ServiceClearEnabled {
+		return
+	}
+	log.Infof("service clear enabled, interval: %s, service TTL: %s",
+		core.ServerInfo.Config.ServiceClearInterval,
+		core.ServerInfo.Config.ServiceTTL)
+
+	gopool.Go(func(ctx context.Context) {
+		for {
+			select {
+			case <-ctx.Done():
+				return
+			case <-time.After(core.ServerInfo.Config.ServiceClearInterval):
+				lock, err := mux.Try(mux.ServiceClearLock)
+				if err != nil {
+					log.Errorf(err, "can not clear no instance services by this service center instance now")
+					continue
+				}
+				err = datasource.Instance().ClearNoInstanceServices(ctx, core.ServerInfo.Config.ServiceTTL)
+				if err := lock.Unlock(); err != nil {
+					log.Error("", err)
+				}
+				if err != nil {
+					log.Errorf(err, "no-instance services cleanup failed")
+					continue
+				}
+				log.Info("no-instance services cleanup succeed")
+			}
+		}
+	})
+}
diff --git a/datasource/etcd/key_generator_test.go b/datasource/etcd/key_generator_test.go
index 4fe7a66..bdf2cd8 100644
--- a/datasource/etcd/key_generator_test.go
+++ b/datasource/etcd/key_generator_test.go
@@ -1,18 +1,19 @@
-package etcd
+package etcd_test
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd"
 	"github.com/stretchr/testify/assert"
 	"testing"
 )
 
 func TestGenerateETCDAccountKey(t *testing.T) {
-	assert.Equal(t, "/cse-sr/accounts/admin", GenerateETCDAccountKey("admin"))
+	assert.Equal(t, "/cse-sr/accounts/admin", etcd.GenerateETCDAccountKey("admin"))
 }
 
 func TestGenerateETCDProjectKey(t *testing.T) {
-	assert.Equal(t, "/cse-sr/projects/domain/project", GenerateETCDProjectKey("domain", "project"))
+	assert.Equal(t, "/cse-sr/projects/domain/project", etcd.GenerateETCDProjectKey("domain", "project"))
 }
 
 func TestGenerateETCDDomainKey(t *testing.T) {
-	assert.Equal(t, "/cse-sr/domains/domain", GenerateETCDDomainKey("domain"))
+	assert.Equal(t, "/cse-sr/domains/domain", etcd.GenerateETCDDomainKey("domain"))
 }
diff --git a/server/core/backend/addon.go b/datasource/etcd/kv/addon.go
similarity index 80%
rename from server/core/backend/addon.go
rename to datasource/etcd/kv/addon.go
index a372b97..77c86cf 100644
--- a/server/core/backend/addon.go
+++ b/datasource/etcd/kv/addon.go
@@ -15,31 +15,31 @@
  * limitations under the License.
  */
 
-package backend
+package kv
 
 import (
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 )
 
 type AddOn interface {
 	Name() string
-	Config() *discovery.Config
+	Config() *sd.Config
 }
 
 type addOn struct {
 	name string
-	cfg  *discovery.Config
+	cfg  *sd.Config
 }
 
 func (e *addOn) Name() string {
 	return e.name
 }
 
-func (e *addOn) Config() *discovery.Config {
+func (e *addOn) Config() *sd.Config {
 	return e.cfg
 }
 
-func NewAddOn(name string, cfg *discovery.Config) AddOn {
+func NewAddOn(name string, cfg *sd.Config) AddOn {
 	return &addOn{
 		name: name,
 		cfg:  cfg,
diff --git a/server/core/backend/defer_instance.go b/datasource/etcd/kv/instance_event_handler.go
similarity index 86%
rename from server/core/backend/defer_instance.go
rename to datasource/etcd/kv/instance_event_handler.go
index ffd801d..c0fbf30 100644
--- a/server/core/backend/defer_instance.go
+++ b/datasource/etcd/kv/instance_event_handler.go
@@ -15,37 +15,37 @@
  * limitations under the License.
  */
 
-package backend
+package kv
 
 import (
 	"context"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 	"sync"
 	"time"
 )
 
 type deferItem struct {
 	ttl   int32 // in seconds
-	event discovery.KvEvent
+	event sd.KvEvent
 }
 
 type InstanceEventDeferHandler struct {
 	Percent float64
 
-	cache     discovery.CacheReader
+	cache     sd.CacheReader
 	once      sync.Once
 	enabled   bool
 	items     map[string]*deferItem
-	pendingCh chan []discovery.KvEvent
-	deferCh   chan discovery.KvEvent
+	pendingCh chan []sd.KvEvent
+	deferCh   chan sd.KvEvent
 	resetCh   chan struct{}
 }
 
-func (iedh *InstanceEventDeferHandler) OnCondition(cache discovery.CacheReader, evts []discovery.KvEvent) bool {
+func (iedh *InstanceEventDeferHandler) OnCondition(cache sd.CacheReader, evts []sd.KvEvent) bool {
 	if iedh.Percent <= 0 {
 		return false
 	}
@@ -53,8 +53,8 @@ func (iedh *InstanceEventDeferHandler) OnCondition(cache discovery.CacheReader,
 	iedh.once.Do(func() {
 		iedh.cache = cache
 		iedh.items = make(map[string]*deferItem)
-		iedh.pendingCh = make(chan []discovery.KvEvent, eventBlockSize)
-		iedh.deferCh = make(chan discovery.KvEvent, eventBlockSize)
+		iedh.pendingCh = make(chan []sd.KvEvent, eventBlockSize)
+		iedh.deferCh = make(chan sd.KvEvent, eventBlockSize)
 		iedh.resetCh = make(chan struct{})
 		gopool.Go(iedh.check)
 	})
@@ -63,7 +63,7 @@ func (iedh *InstanceEventDeferHandler) OnCondition(cache discovery.CacheReader,
 	return true
 }
 
-func (iedh *InstanceEventDeferHandler) recoverOrDefer(evt discovery.KvEvent) {
+func (iedh *InstanceEventDeferHandler) recoverOrDefer(evt sd.KvEvent) {
 	if evt.KV == nil {
 		log.Errorf(nil, "defer or recover a %s nil KV", evt.Type)
 		return
@@ -99,7 +99,7 @@ func (iedh *InstanceEventDeferHandler) recoverOrDefer(evt discovery.KvEvent) {
 	}
 }
 
-func (iedh *InstanceEventDeferHandler) HandleChan() <-chan discovery.KvEvent {
+func (iedh *InstanceEventDeferHandler) HandleChan() <-chan sd.KvEvent {
 	return iedh.deferCh
 }
 
@@ -170,7 +170,7 @@ func (iedh *InstanceEventDeferHandler) check(ctx context.Context) {
 	}
 }
 
-func (iedh *InstanceEventDeferHandler) recover(evt discovery.KvEvent) {
+func (iedh *InstanceEventDeferHandler) recover(evt sd.KvEvent) {
 	key := util.BytesToStringWithNoCopy(evt.KV.Key)
 	delete(iedh.items, key)
 	iedh.deferCh <- evt
diff --git a/server/core/backend/defer_test.go b/datasource/etcd/kv/instance_event_handler_test.go
similarity index 72%
rename from server/core/backend/defer_test.go
rename to datasource/etcd/kv/instance_event_handler_test.go
index fbefa28..c8053cd 100644
--- a/server/core/backend/defer_test.go
+++ b/datasource/etcd/kv/instance_event_handler_test.go
@@ -14,33 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package backend
+package kv
 
 import (
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	pb "github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 	"testing"
 	"time"
 )
 
 type mockCache struct {
-	c map[string]*discovery.KeyValue
+	c map[string]*sd.KeyValue
 }
 
-func (n *mockCache) Name() string                     { return "mock" }
-func (n *mockCache) Size() int                        { return 0 }
-func (n *mockCache) Get(k string) *discovery.KeyValue { return nil }
-func (n *mockCache) GetAll(arr *[]*discovery.KeyValue) (i int) {
+func (n *mockCache) Name() string              { return "mock" }
+func (n *mockCache) Size() int                 { return 0 }
+func (n *mockCache) Get(k string) *sd.KeyValue { return nil }
+func (n *mockCache) GetAll(arr *[]*sd.KeyValue) (i int) {
 	for range n.c {
 		i++
 	}
 	return i
 }
-func (n *mockCache) GetPrefix(prefix string, arr *[]*discovery.KeyValue) int        { return 0 }
-func (n *mockCache) ForEach(iter func(k string, v *discovery.KeyValue) (next bool)) {}
-func (n *mockCache) Put(k string, v *discovery.KeyValue)                            { n.c[k] = v }
+func (n *mockCache) GetPrefix(prefix string, arr *[]*sd.KeyValue) int        { return 0 }
+func (n *mockCache) ForEach(iter func(k string, v *sd.KeyValue) (next bool)) {}
+func (n *mockCache) Put(k string, v *sd.KeyValue)                            { n.c[k] = v }
 
 func TestInstanceEventDeferHandler_OnCondition(t *testing.T) {
 	iedh := &InstanceEventDeferHandler{
@@ -64,34 +64,34 @@ func TestInstanceEventDeferHandler_HandleChan(t *testing.T) {
 			Times:    0,
 		},
 	}
-	kv1 := &discovery.KeyValue{
+	kv1 := &sd.KeyValue{
 		Key:   util.StringToBytesWithNoCopy("/1"),
 		Value: b,
 	}
-	kv2 := &discovery.KeyValue{
+	kv2 := &sd.KeyValue{
 		Key:   util.StringToBytesWithNoCopy("/2"),
 		Value: b,
 	}
-	kv3 := &discovery.KeyValue{
+	kv3 := &sd.KeyValue{
 		Key:   util.StringToBytesWithNoCopy("/3"),
 		Value: b,
 	}
-	kv4 := &discovery.KeyValue{
+	kv4 := &sd.KeyValue{
 		Key:   util.StringToBytesWithNoCopy("/4"),
 		Value: b,
 	}
-	kv5 := &discovery.KeyValue{
+	kv5 := &sd.KeyValue{
 		Key:   util.StringToBytesWithNoCopy("/5"),
 		Value: b,
 	}
-	kv6 := &discovery.KeyValue{
+	kv6 := &sd.KeyValue{
 		Key:   util.StringToBytesWithNoCopy("/6"),
 		Value: b,
 	}
 
-	cache := &mockCache{c: make(map[string]*discovery.KeyValue)}
-	cache.Put("/1", kv1)
-	evts0 := []discovery.KvEvent{
+	c := &mockCache{c: make(map[string]*sd.KeyValue)}
+	c.Put("/1", kv1)
+	evts0 := []sd.KvEvent{
 		{
 			Type: pb.EVT_DELETE,
 			KV:   kv1,
@@ -101,7 +101,7 @@ func TestInstanceEventDeferHandler_HandleChan(t *testing.T) {
 	iedh := &InstanceEventDeferHandler{
 		Percent: 1,
 	}
-	iedh.OnCondition(cache, evts0)
+	iedh.OnCondition(c, evts0)
 	select {
 	case evt := <-iedh.HandleChan():
 		if string(evt.KV.Key) != "/1" || evt.Type != pb.EVT_DELETE {
@@ -111,14 +111,14 @@ func TestInstanceEventDeferHandler_HandleChan(t *testing.T) {
 		t.Fatalf(`TestInstanceEventDeferHandler_HandleChan DELETE timed out`)
 	}
 
-	cache.Put("/1", kv1)
-	cache.Put("/2", kv2)
-	cache.Put("/3", kv3)
-	cache.Put("/4", kv4)
-	cache.Put("/5", kv5)
-	cache.Put("/6", kv6)
+	c.Put("/1", kv1)
+	c.Put("/2", kv2)
+	c.Put("/3", kv3)
+	c.Put("/4", kv4)
+	c.Put("/5", kv5)
+	c.Put("/6", kv6)
 
-	evts1 := []discovery.KvEvent{
+	evts1 := []sd.KvEvent{
 		{
 			Type: pb.EVT_CREATE,
 			KV:   kv1,
@@ -128,7 +128,7 @@ func TestInstanceEventDeferHandler_HandleChan(t *testing.T) {
 			KV:   kv1,
 		},
 	}
-	evts2 := []discovery.KvEvent{
+	evts2 := []sd.KvEvent{
 		{
 			Type: pb.EVT_DELETE,
 			KV:   kv2,
@@ -150,7 +150,7 @@ func TestInstanceEventDeferHandler_HandleChan(t *testing.T) {
 			KV:   kv6,
 		},
 	}
-	evts3 := []discovery.KvEvent{
+	evts3 := []sd.KvEvent{
 		{
 			Type: pb.EVT_CREATE,
 			KV:   kv2,
@@ -170,16 +170,16 @@ func TestInstanceEventDeferHandler_HandleChan(t *testing.T) {
 	}
 
 	iedh.Percent = 0.01
-	iedh.OnCondition(cache, evts1)
-	iedh.OnCondition(cache, evts2)
-	iedh.OnCondition(cache, evts3)
+	iedh.OnCondition(c, evts1)
+	iedh.OnCondition(c, evts2)
+	iedh.OnCondition(c, evts3)
 
 	getEvents(t, iedh)
 
 	iedh.Percent = 0.9
-	iedh.OnCondition(cache, evts1)
-	iedh.OnCondition(cache, evts2)
-	iedh.OnCondition(cache, evts3)
+	iedh.OnCondition(c, evts1)
+	iedh.OnCondition(c, evts2)
+	iedh.OnCondition(c, evts3)
 
 	getEvents(t, iedh)
 }
@@ -187,7 +187,7 @@ func TestInstanceEventDeferHandler_HandleChan(t *testing.T) {
 func getEvents(t *testing.T, iedh *InstanceEventDeferHandler) {
 	fmt.Println(time.Now())
 	c := time.After(3500 * time.Millisecond)
-	var evt3 *discovery.KvEvent
+	var evt3 *sd.KvEvent
 	for {
 		select {
 		case evt := <-iedh.HandleChan():
@@ -209,7 +209,7 @@ func getEvents(t *testing.T, iedh *InstanceEventDeferHandler) {
 }
 
 func TestConvert(t *testing.T) {
-	value := discovery.NewKeyValue()
+	value := sd.NewKeyValue()
 	_, ok := value.Value.(*pb.MicroServiceInstance)
 	if ok {
 		t.Fatal("TestConvert failed")
diff --git a/datasource/etcd/kv/kv.go b/datasource/etcd/kv/kv.go
new file mode 100644
index 0000000..5917c7e
--- /dev/null
+++ b/datasource/etcd/kv/kv.go
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+// kv package provides a TypeStore to manage the implementations of sd package, see types.go
+package kv
+
+import (
+	"context"
+	"errors"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
+	"github.com/apache/servicecomb-service-center/pkg/gopool"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/apache/servicecomb-service-center/pkg/util"
+	"github.com/apache/servicecomb-service-center/server/core"
+	"time"
+)
+
+var store = &TypeStore{}
+
+func init() {
+	store.Initialize()
+	registerInnerTypes()
+}
+
+type TypeStore struct {
+	AddOns    map[sd.Type]AddOn
+	adaptors  util.ConcurrentMap
+	ready     chan struct{}
+	goroutine *gopool.Pool
+	isClose   bool
+	rev       int64
+}
+
+func (s *TypeStore) Initialize() {
+	s.AddOns = make(map[sd.Type]AddOn)
+	s.ready = make(chan struct{})
+	s.goroutine = gopool.New(context.Background())
+}
+
+func (s *TypeStore) OnCacheEvent(evt sd.KvEvent) {
+	if s.rev < evt.Revision {
+		s.rev = evt.Revision
+	}
+}
+
+func (s *TypeStore) InjectConfig(cfg *sd.Config) *sd.Config {
+	return cfg.AppendEventFunc(s.OnCacheEvent)
+}
+
+func (s *TypeStore) repo() sd.AdaptorRepository {
+	return sd.Instance()
+}
+
+func (s *TypeStore) getOrCreateAdaptor(t sd.Type) sd.Adaptor {
+	v, _ := s.adaptors.Fetch(t, func() (interface{}, error) {
+		addOn, ok := s.AddOns[t]
+		if ok {
+			adaptor := s.repo().New(t, addOn.(AddOn).Config())
+			adaptor.Run()
+			return adaptor, nil
+		}
+		log.Warnf("type '%s' not found", t)
+		return nil, nil
+	})
+	return v.(sd.Adaptor)
+}
+
+func (s *TypeStore) Run() {
+	s.goroutine.Do(s.store)
+	s.goroutine.Do(s.autoClearCache)
+}
+
+func (s *TypeStore) store(ctx context.Context) {
+	// new all types
+	for _, t := range sd.Types {
+		select {
+		case <-ctx.Done():
+			return
+		case <-s.getOrCreateAdaptor(t).Ready():
+		}
+	}
+
+	util.SafeCloseChan(s.ready)
+
+	log.Debugf("all adaptors are ready")
+}
+
+func (s *TypeStore) autoClearCache(ctx context.Context) {
+	if core.ServerInfo.Config.CacheTTL == 0 {
+		return
+	}
+
+	log.Infof("start auto clear cache in %v", core.ServerInfo.Config.CacheTTL)
+	for {
+		select {
+		case <-ctx.Done():
+			return
+		case <-time.After(core.ServerInfo.Config.CacheTTL):
+			for _, t := range sd.Types {
+				cache, ok := s.getOrCreateAdaptor(t).Cache().(sd.Cache)
+				if !ok {
+					log.Error("the discovery adaptor does not implement the Cache", nil)
+					continue
+				}
+				cache.MarkDirty()
+			}
+			log.Warnf("caches are marked dirty!")
+		}
+	}
+}
+
+func (s *TypeStore) Stop() {
+	if s.isClose {
+		return
+	}
+	s.isClose = true
+
+	s.adaptors.ForEach(func(item util.MapItem) bool {
+		item.Value.(sd.Adaptor).Stop()
+		return true
+	})
+
+	s.goroutine.Close(true)
+
+	util.SafeCloseChan(s.ready)
+
+	log.Debugf("store daemon stopped")
+}
+
+func (s *TypeStore) Ready() <-chan struct{} {
+	return s.ready
+}
+
+func (s *TypeStore) Install(addOn AddOn) (id sd.Type, err error) {
+	if addOn == nil || len(addOn.Name()) == 0 || addOn.Config() == nil {
+		return sd.TypeError, errors.New("invalid parameter")
+	}
+
+	id, err = sd.RegisterType(addOn.Name())
+	if err != nil {
+		return
+	}
+
+	sd.EventProxy(id).InjectConfig(addOn.Config())
+
+	s.InjectConfig(addOn.Config())
+
+	s.AddOns[id] = addOn
+
+	log.Infof("install new type %d:%s->%s", id, addOn.Name(), addOn.Config().Key)
+	return
+}
+
+func (s *TypeStore) MustInstall(addOn AddOn) sd.Type {
+	id, err := s.Install(addOn)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+func (s *TypeStore) Adaptors(id sd.Type) sd.Adaptor { return s.getOrCreateAdaptor(id) }
+func (s *TypeStore) Service() sd.Adaptor            { return s.Adaptors(SERVICE) }
+func (s *TypeStore) SchemaSummary() sd.Adaptor      { return s.Adaptors(SchemaSummary) }
+func (s *TypeStore) Instance() sd.Adaptor           { return s.Adaptors(INSTANCE) }
+func (s *TypeStore) Lease() sd.Adaptor              { return s.Adaptors(LEASE) }
+func (s *TypeStore) ServiceIndex() sd.Adaptor       { return s.Adaptors(ServiceIndex) }
+func (s *TypeStore) ServiceAlias() sd.Adaptor       { return s.Adaptors(ServiceAlias) }
+func (s *TypeStore) ServiceTag() sd.Adaptor         { return s.Adaptors(ServiceTag) }
+func (s *TypeStore) Rule() sd.Adaptor               { return s.Adaptors(RULE) }
+func (s *TypeStore) RuleIndex() sd.Adaptor          { return s.Adaptors(RuleIndex) }
+func (s *TypeStore) Schema() sd.Adaptor             { return s.Adaptors(SCHEMA) }
+func (s *TypeStore) DependencyRule() sd.Adaptor     { return s.Adaptors(DependencyRule) }
+func (s *TypeStore) DependencyQueue() sd.Adaptor    { return s.Adaptors(DependencyQueue) }
+func (s *TypeStore) Domain() sd.Adaptor             { return s.Adaptors(DOMAIN) }
+func (s *TypeStore) Project() sd.Adaptor            { return s.Adaptors(PROJECT) }
+
+func Store() *TypeStore {
+	return store
+}
+
+func Revision() int64 {
+	return store.rev
+}
diff --git a/datasource/etcd/kv/kv_test.go b/datasource/etcd/kv/kv_test.go
new file mode 100644
index 0000000..d1f2874
--- /dev/null
+++ b/datasource/etcd/kv/kv_test.go
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package kv
+
+import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
+	"testing"
+)
+
+type extend struct {
+	evts []sd.KvEvent
+	cfg  *sd.Config
+}
+
+func (e *extend) Name() string {
+	return "test"
+}
+
+func (e *extend) Config() *sd.Config {
+	return e.cfg
+}
+
+func TestInstallType(t *testing.T) {
+	s := &TypeStore{}
+	s.Initialize()
+
+	// case: normal
+	e := &extend{cfg: sd.Configure()}
+	e.cfg.WithPrefix("/test").WithEventFunc(func(evt sd.KvEvent) {
+		e.evts = append(e.evts, evt)
+	})
+	id, err := s.Install(e)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if id == sd.TypeError {
+		t.Fatal(err)
+	}
+	if id.String() != "test" {
+		t.Fatalf("TestInstallType failed")
+	}
+
+	// case: inject config
+	itf, _ := s.AddOns[id]
+	cfg := itf.(AddOn).Config()
+	if cfg == nil || cfg.OnEvent == nil {
+		t.Fatal("installType fail", err)
+	}
+
+	cfg.OnEvent(sd.KvEvent{Revision: 1})
+	if s.rev != 1 || len(e.evts) != 1 {
+		t.Fatalf("TestInstallType failed")
+	}
+
+	// case: install again
+	cfg = sd.Configure().WithPrefix("/test")
+	id, err = s.Install(NewAddOn("test", cfg))
+	if id != sd.TypeError || err == nil {
+		t.Fatal("installType fail", err)
+	}
+}
+
+func TestNewAddOn(t *testing.T) {
+	s := &TypeStore{}
+	s.Initialize()
+
+	id, err := s.Install(NewAddOn("TestNewAddOn", nil))
+	if id != sd.TypeError || err == nil {
+		t.Fatalf("TestNewAddOn failed")
+	}
+	id, err = s.Install(NewAddOn("", sd.Configure()))
+	if id != sd.TypeError || err == nil {
+		t.Fatalf("TestNewAddOn failed")
+	}
+	id, err = s.Install(nil)
+	if id != sd.TypeError || err == nil {
+		t.Fatalf("TestNewAddOn failed")
+	}
+	id, err = s.Install(NewAddOn("TestNewAddOn", sd.Configure()))
+	if id == sd.TypeError || err != nil {
+		t.Fatalf("TestNewAddOn failed")
+	}
+	_, err = s.Install(NewAddOn("TestNewAddOn", sd.Configure()))
+	if err == nil {
+		t.Fatalf("TestNewAddOn failed")
+	}
+}
diff --git a/datasource/etcd/kv/types.go b/datasource/etcd/kv/types.go
new file mode 100644
index 0000000..b1d61d3
--- /dev/null
+++ b/datasource/etcd/kv/types.go
@@ -0,0 +1,96 @@
+/*
+ * 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 kv
+
+import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
+	"github.com/apache/servicecomb-service-center/server/core"
+	"github.com/apache/servicecomb-service-center/server/core/proto"
+	"time"
+)
+
+const (
+	eventBlockSize             = 1000
+	deferCheckWindow           = 2 * time.Second // instance DELETE event will be delay.
+	selfPreservationPercentage = 0.8
+	selfPreservationMaxTTL     = 10 * 60 // 10min
+	selfPreservationInitCount  = 5
+)
+
+var (
+	DOMAIN          sd.Type
+	PROJECT         sd.Type
+	SERVICE         sd.Type
+	ServiceIndex    sd.Type
+	ServiceAlias    sd.Type
+	ServiceTag      sd.Type
+	RULE            sd.Type
+	RuleIndex       sd.Type
+	DependencyRule  sd.Type
+	DependencyQueue sd.Type
+	SCHEMA          sd.Type
+	SchemaSummary   sd.Type
+	INSTANCE        sd.Type
+	LEASE           sd.Type
+)
+
+func registerInnerTypes() {
+	SERVICE = Store().MustInstall(NewAddOn("SERVICE",
+		sd.Configure().WithPrefix(core.GetServiceRootKey("")).
+			WithInitSize(500).WithParser(proto.ServiceParser)))
+	INSTANCE = Store().MustInstall(NewAddOn("INSTANCE",
+		sd.Configure().WithPrefix(core.GetInstanceRootKey("")).
+			WithInitSize(1000).WithParser(proto.InstanceParser).
+			WithDeferHandler(NewInstanceEventDeferHandler())))
+	DOMAIN = Store().MustInstall(NewAddOn("DOMAIN",
+		sd.Configure().WithPrefix(core.GetDomainRootKey()+core.SPLIT).
+			WithInitSize(100).WithParser(proto.StringParser)))
+	SCHEMA = Store().MustInstall(NewAddOn("SCHEMA",
+		sd.Configure().WithPrefix(core.GetServiceSchemaRootKey("")).
+			WithInitSize(0)))
+	SchemaSummary = Store().MustInstall(NewAddOn("SCHEMA_SUMMARY",
+		sd.Configure().WithPrefix(core.GetServiceSchemaSummaryRootKey("")).
+			WithInitSize(100).WithParser(proto.StringParser)))
+	RULE = Store().MustInstall(NewAddOn("RULE",
+		sd.Configure().WithPrefix(core.GetServiceRuleRootKey("")).
+			WithInitSize(100).WithParser(proto.RuleParser)))
+	LEASE = Store().MustInstall(NewAddOn("LEASE",
+		sd.Configure().WithPrefix(core.GetInstanceLeaseRootKey("")).
+			WithInitSize(1000).WithParser(proto.StringParser)))
+	ServiceIndex = Store().MustInstall(NewAddOn("SERVICE_INDEX",
+		sd.Configure().WithPrefix(core.GetServiceIndexRootKey("")).
+			WithInitSize(500).WithParser(proto.StringParser)))
+	ServiceAlias = Store().MustInstall(NewAddOn("SERVICE_ALIAS",
+		sd.Configure().WithPrefix(core.GetServiceAliasRootKey("")).
+			WithInitSize(100).WithParser(proto.StringParser)))
+	ServiceTag = Store().MustInstall(NewAddOn("SERVICE_TAG",
+		sd.Configure().WithPrefix(core.GetServiceTagRootKey("")).
+			WithInitSize(100).WithParser(proto.MapParser)))
+	RuleIndex = Store().MustInstall(NewAddOn("RULE_INDEX",
+		sd.Configure().WithPrefix(core.GetServiceRuleIndexRootKey("")).
+			WithInitSize(100).WithParser(proto.StringParser)))
+	DependencyRule = Store().MustInstall(NewAddOn("DEPENDENCY_RULE",
+		sd.Configure().WithPrefix(core.GetServiceDependencyRuleRootKey("")).
+			WithInitSize(100).WithParser(proto.DependencyRuleParser)))
+	DependencyQueue = Store().MustInstall(NewAddOn("DEPENDENCY_QUEUE",
+		sd.Configure().WithPrefix(core.GetServiceDependencyQueueRootKey("")).
+			WithInitSize(100).WithParser(proto.DependencyQueueParser)))
+	PROJECT = Store().MustInstall(NewAddOn("PROJECT",
+		sd.Configure().WithPrefix(core.GetProjectRootKey("")).
+			WithInitSize(100).WithParser(proto.StringParser)))
+}
diff --git a/datasource/etcd/ms.go b/datasource/etcd/ms.go
index b7d29f3..5c2bd89 100644
--- a/datasource/etcd/ms.go
+++ b/datasource/etcd/ms.go
@@ -22,18 +22,18 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	registry "github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/kv"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	serviceUtil "github.com/apache/servicecomb-service-center/datasource/etcd/util"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	pb "github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	apt "github.com/apache/servicecomb-service-center/server/core"
-	"github.com/apache/servicecomb-service-center/server/core/backend"
 	"github.com/apache/servicecomb-service-center/server/core/proto"
-	"github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 	"github.com/apache/servicecomb-service-center/server/plugin/quota"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 	scerr "github.com/apache/servicecomb-service-center/server/scerror"
 	"github.com/apache/servicecomb-service-center/server/service/cache"
 	"sort"
@@ -45,7 +45,7 @@ var clustersIndex = make(map[string]int)
 
 func init() {
 	var clusters []string
-	for name := range registry.Configuration().Clusters {
+	for name := range Configuration().Clusters {
 		clusters = append(clusters, name)
 	}
 	sort.Strings(clusters)
@@ -70,7 +70,7 @@ func (ds *DataSource) RegisterService(ctx context.Context, request *pb.CreateSer
 			Response: proto.CreateResponse(scerr.ErrInternal, err.Error()),
 		}, err
 	}
-	resp, err := backend.Registry().TxnWithCmp(ctx, opts, uniqueCmpOpts, failOpts)
+	resp, err := client.Instance().TxnWithCmp(ctx, opts, uniqueCmpOpts, failOpts)
 
 	return newRegisterServiceResp(ctx, serviceBody, resp, err)
 }
@@ -86,7 +86,7 @@ func (ds *DataSource) GetServices(ctx context.Context, request *pb.GetServicesRe
 	}
 
 	return &pb.GetServicesResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get all services successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get all services successfully."),
 		Services: services,
 	}, nil
 }
@@ -109,7 +109,7 @@ func (ds *DataSource) GetService(ctx context.Context, request *pb.GetServiceRequ
 		}, nil
 	}
 	return &pb.GetServiceResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get service successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get service successfully."),
 		Service:  singleService,
 	}, nil
 }
@@ -169,7 +169,7 @@ func (ds *DataSource) GetServiceDetail(ctx context.Context, request *pb.GetServi
 	serviceInfo.MicroService = service
 	serviceInfo.MicroServiceVersions = versions
 	return &pb.GetServiceDetailResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get service successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get service successfully."),
 		Service:  serviceInfo,
 	}, nil
 }
@@ -204,7 +204,7 @@ func (ds *DataSource) GetServicesInfo(ctx context.Context, request *pb.GetServic
 		}
 		if len(optionMap) == 1 {
 			return &pb.GetServicesInfoResponse{
-				Response:   proto.CreateResponse(proto.Response_SUCCESS, "Statistics successfully."),
+				Response:   proto.CreateResponse(proto.ResponseSuccess, "Statistics successfully."),
 				Statistics: st,
 			}, nil
 		}
@@ -250,7 +250,7 @@ func (ds *DataSource) GetServicesInfo(ctx context.Context, request *pb.GetServic
 	}
 
 	return &pb.GetServicesInfoResponse{
-		Response:          proto.CreateResponse(proto.Response_SUCCESS, "Get services info successfully."),
+		Response:          proto.CreateResponse(proto.ResponseSuccess, "Get services info successfully."),
 		AllServicesDetail: allServiceDetails,
 		Statistics:        st,
 	}, nil
@@ -265,14 +265,14 @@ func (ds *DataSource) GetApplications(ctx context.Context, request *pb.GetAppsRe
 		registry.WithPrefix(),
 		registry.WithKeyOnly())
 
-	resp, err := backend.Store().ServiceIndex().Search(ctx, opts...)
+	resp, err := kv.Store().ServiceIndex().Search(ctx, opts...)
 	if err != nil {
 		return nil, err
 	}
 	l := len(resp.Kvs)
 	if l == 0 {
 		return &pb.GetAppsResponse{
-			Response: proto.CreateResponse(proto.Response_SUCCESS, "Get all applications successfully."),
+			Response: proto.CreateResponse(proto.ResponseSuccess, "Get all applications successfully."),
 		}, nil
 	}
 
@@ -291,11 +291,19 @@ func (ds *DataSource) GetApplications(ctx context.Context, request *pb.GetAppsRe
 	}
 
 	return &pb.GetAppsResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get all applications successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get all applications successfully."),
 		AppIds:   apps,
 	}, nil
 }
 
+func (ds *DataSource) ExistServiceByID(ctx context.Context, request *pb.GetExistenceByIDRequest) (*pb.GetExistenceByIDResponse, error) {
+	domainProject := util.ParseDomainProject(ctx)
+	return &pb.GetExistenceByIDResponse{
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get all applications successfully."),
+		Exist:    serviceUtil.ServiceExist(ctx, domainProject, request.ServiceId),
+	}, nil
+}
+
 func (ds *DataSource) ExistService(ctx context.Context, request *pb.GetExistenceRequest) (*pb.GetExistenceResponse,
 	error) {
 	domainProject := util.ParseDomainProject(ctx)
@@ -329,7 +337,7 @@ func (ds *DataSource) ExistService(ctx context.Context, request *pb.GetExistence
 		}, nil
 	}
 	return &pb.GetExistenceResponse{
-		Response:  proto.CreateResponse(proto.Response_SUCCESS, "get service id successfully."),
+		Response:  proto.CreateResponse(proto.ResponseSuccess, "get service id successfully."),
 		ServiceId: ids[0], // 约定多个时,取较新版本
 	}, nil
 }
@@ -370,11 +378,11 @@ func (ds *DataSource) UpdateService(ctx context.Context, request *pb.UpdateServi
 	}
 
 	// Set key file
-	resp, err := backend.Registry().TxnWithCmp(ctx,
-		[]registry.PluginOp{registry.OpPut(registry.WithStrKey(key), registry.WithValue(data))},
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(key)),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.Instance().TxnWithCmp(ctx,
+		[]client.PluginOp{client.OpPut(client.WithStrKey(key), client.WithValue(data))},
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(key)),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		log.Errorf(err, "update service[%s] properties failed, operator: %s", request.ServiceId, remoteIP)
@@ -392,7 +400,7 @@ func (ds *DataSource) UpdateService(ctx context.Context, request *pb.UpdateServi
 
 	log.Infof("update service[%s] properties successfully, operator: %s", request.ServiceId, remoteIP)
 	return &pb.UpdateServicePropsResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "update service successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "update service successfully."),
 	}, nil
 }
 
@@ -427,7 +435,7 @@ func (ds *DataSource) RegisterInstance(ctx context.Context, request *pb.Register
 			}, nil
 		}
 		switch resp.Response.GetCode() {
-		case proto.Response_SUCCESS:
+		case proto.ResponseSuccess:
 			log.Infof("register instance successful, reuse instance[%s/%s], operator %s",
 				instance.ServiceId, instance.InstanceId, remoteIP)
 			return &pb.RegisterInstanceResponse{
@@ -467,7 +475,7 @@ func (ds *DataSource) RegisterInstance(ctx context.Context, request *pb.Register
 	if !apt.IsSCInstance(ctx) {
 		res := quota.NewApplyQuotaResource(quota.MicroServiceInstanceQuotaType,
 			domainProject, request.Instance.ServiceId, 1)
-		reporter = plugin.Plugins().Quota().Apply4Quotas(ctx, res)
+		reporter = quota.Apply(ctx, res)
 		defer reporter.Close(ctx)
 
 		if reporter.Err != nil {
@@ -494,7 +502,7 @@ func (ds *DataSource) RegisterInstance(ctx context.Context, request *pb.Register
 		}, err
 	}
 
-	leaseID, err := backend.Registry().LeaseGrant(ctx, ttl)
+	leaseID, err := client.Instance().LeaseGrant(ctx, ttl)
 	if err != nil {
 		log.Errorf(err, "grant lease failed, %s, operator: %s", instanceFlag, remoteIP)
 		return &pb.RegisterInstanceResponse{
@@ -506,17 +514,17 @@ func (ds *DataSource) RegisterInstance(ctx context.Context, request *pb.Register
 	key := apt.GenerateInstanceKey(domainProject, instance.ServiceId, instanceID)
 	hbKey := apt.GenerateInstanceLeaseKey(domainProject, instance.ServiceId, instanceID)
 
-	opts := []registry.PluginOp{
-		registry.OpPut(registry.WithStrKey(key), registry.WithValue(data),
-			registry.WithLease(leaseID)),
-		registry.OpPut(registry.WithStrKey(hbKey), registry.WithStrValue(fmt.Sprintf("%d", leaseID)),
-			registry.WithLease(leaseID)),
+	opts := []client.PluginOp{
+		client.OpPut(client.WithStrKey(key), client.WithValue(data),
+			client.WithLease(leaseID)),
+		client.OpPut(client.WithStrKey(hbKey), client.WithStrValue(fmt.Sprintf("%d", leaseID)),
+			client.WithLease(leaseID)),
 	}
 
-	resp, err := backend.Registry().TxnWithCmp(ctx, opts,
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, instance.ServiceId))),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.Instance().TxnWithCmp(ctx, opts,
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, instance.ServiceId))),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		log.Errorf(err,
@@ -544,7 +552,7 @@ func (ds *DataSource) RegisterInstance(ctx context.Context, request *pb.Register
 	log.Infof("register instance %s, instanceID %s, operator %s",
 		instanceFlag, instanceID, remoteIP)
 	return &pb.RegisterInstanceResponse{
-		Response:   proto.CreateResponse(proto.Response_SUCCESS, "Register service instance successfully."),
+		Response:   proto.CreateResponse(proto.ResponseSuccess, "Register service instance successfully."),
 		InstanceId: instanceID,
 	}, nil
 }
@@ -625,7 +633,7 @@ func (ds *DataSource) GetInstance(ctx context.Context, request *pb.GetOneInstanc
 	_ = util.SetContext(ctx, util.CtxResponseRevision, item.Rev)
 
 	return &pb.GetOneInstanceResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get instance successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get instance successfully."),
 		Instance: instance,
 	}, nil
 }
@@ -705,7 +713,7 @@ func (ds *DataSource) GetInstances(ctx context.Context, request *pb.GetInstances
 	_ = util.SetContext(ctx, util.CtxResponseRevision, item.Rev)
 
 	return &pb.GetInstancesResponse{
-		Response:  proto.CreateResponse(proto.Response_SUCCESS, "Query service instances successfully."),
+		Response:  proto.CreateResponse(proto.ResponseSuccess, "Query service instances successfully."),
 		Instances: instances,
 	}, nil
 }
@@ -747,7 +755,7 @@ func (ds *DataSource) BatchGetProviderInstances(ctx context.Context, request *pb
 func (ds *DataSource) findInstances(ctx context.Context, domainProject, serviceID, instanceID string, maxRevs []int64, counts []int64) (instances []*pb.MicroServiceInstance, err error) {
 	key := apt.GenerateInstanceKey(domainProject, serviceID, instanceID)
 	opts := append(serviceUtil.FromContext(ctx), registry.WithStrKey(key), registry.WithPrefix())
-	resp, err := backend.Store().Instance().Search(ctx, opts...)
+	resp, err := kv.Store().Instance().Search(ctx, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -909,7 +917,7 @@ func (ds *DataSource) genFindResult(ctx context.Context, oldRev string, item *ca
 	// TODO support gRPC output context
 	_ = util.SetContext(ctx, util.CtxResponseRevision, item.Rev)
 	return &pb.FindInstancesResponse{
-		Response:  proto.CreateResponse(proto.Response_SUCCESS, "Query service instances successfully."),
+		Response:  proto.CreateResponse(proto.ResponseSuccess, "Query service instances successfully."),
 		Instances: instances,
 	}, nil
 }
@@ -962,7 +970,7 @@ func (ds *DataSource) UpdateInstanceStatus(ctx context.Context, request *pb.Upda
 
 	log.Infof("update instance[%s] status successfully", updateStatusFlag)
 	return &pb.UpdateInstanceStatusResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Update service instance status successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Update service instance status successfully."),
 	}, nil
 }
 
@@ -1001,7 +1009,7 @@ func (ds *DataSource) UpdateInstanceProperties(ctx context.Context, request *pb.
 
 	log.Infof("update instance[%s] properties successfully", instanceFlag)
 	return &pb.UpdateInstancePropsResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Update service instance properties successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Update service instance properties successfully."),
 	}, nil
 }
 
@@ -1042,7 +1050,7 @@ func (ds *DataSource) HeartbeatSet(ctx context.Context, request *pb.HeartbeatSet
 	if !failFlag && successFlag {
 		log.Infof("batch update heartbeats[%s] successfully", count)
 		return &pb.HeartbeatSetResponse{
-			Response:  proto.CreateResponse(proto.Response_SUCCESS, "Heartbeat set successfully."),
+			Response:  proto.CreateResponse(proto.ResponseSuccess, "Heartbeat set successfully."),
 			Instances: instanceHbRstArr,
 		}, nil
 	}
@@ -1056,7 +1064,7 @@ func (ds *DataSource) HeartbeatSet(ctx context.Context, request *pb.HeartbeatSet
 func (ds *DataSource) BatchFind(ctx context.Context, request *pb.BatchFindInstancesRequest) (
 	*pb.BatchFindInstancesResponse, error) {
 	response := &pb.BatchFindInstancesResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Batch query service instances successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Batch query service instances successfully."),
 	}
 
 	var err error
@@ -1170,7 +1178,7 @@ func (ds *DataSource) UnregisterInstance(ctx context.Context, request *pb.Unregi
 
 	log.Infof("unregister instance[%s], operator %s", instanceFlag, remoteIP)
 	return &pb.UnregisterInstanceResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Unregister service instance successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Unregister service instance successfully."),
 	}, nil
 }
 
@@ -1200,7 +1208,7 @@ func (ds *DataSource) Heartbeat(ctx context.Context, request *pb.HeartbeatReques
 			instanceFlag, ttl, remoteIP)
 	}
 	return &pb.HeartbeatResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS,
+		Response: proto.CreateResponse(proto.ResponseSuccess,
 			"Update service instance heartbeat successfully."),
 	}, nil
 }
@@ -1240,7 +1248,7 @@ func (ds *DataSource) ModifySchemas(ctx context.Context, request *pb.ModifySchem
 	}
 
 	return &pb.ModifySchemasResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "modify schemas info successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "modify schemas info successfully."),
 	}, nil
 }
 
@@ -1269,7 +1277,7 @@ func (ds *DataSource) ModifySchema(ctx context.Context, request *pb.ModifySchema
 
 	log.Infof("modify schema[%s/%s] successfully, operator: %s", serviceID, schemaID, remoteIP)
 	return &pb.ModifySchemaResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "modify schema info success"),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "modify schema info success"),
 	}, nil
 }
 
@@ -1307,7 +1315,7 @@ func (ds *DataSource) ExistSchema(ctx context.Context, request *pb.GetExistenceR
 		}, err
 	}
 	return &pb.GetExistenceResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Schema exist."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Schema exist."),
 		SchemaId: request.SchemaId,
 		Summary:  schemaSummary,
 	}, nil
@@ -1325,8 +1333,8 @@ func (ds *DataSource) GetSchema(ctx context.Context, request *pb.GetSchemaReques
 	}
 
 	key := apt.GenerateServiceSchemaKey(domainProject, request.ServiceId, request.SchemaId)
-	opts := append(serviceUtil.FromContext(ctx), registry.WithStrKey(key))
-	resp, errDo := backend.Store().Schema().Search(ctx, opts...)
+	opts := append(serviceUtil.FromContext(ctx), client.WithStrKey(key))
+	resp, errDo := kv.Store().Schema().Search(ctx, opts...)
 	if errDo != nil {
 		log.Errorf(errDo, "get schema[%s/%s] failed", request.ServiceId, request.SchemaId)
 		return &pb.GetSchemaResponse{
@@ -1351,7 +1359,7 @@ func (ds *DataSource) GetSchema(ctx context.Context, request *pb.GetSchemaReques
 	}
 
 	return &pb.GetSchemaResponse{
-		Response:      proto.CreateResponse(proto.Response_SUCCESS, "Get schema info successfully."),
+		Response:      proto.CreateResponse(proto.ResponseSuccess, "Get schema info successfully."),
 		Schema:        util.BytesToStringWithNoCopy(resp.Kvs[0].Value.([]byte)),
 		SchemaSummary: schemaSummary,
 	}, nil
@@ -1378,14 +1386,14 @@ func (ds *DataSource) GetAllSchemas(ctx context.Context, request *pb.GetAllSchem
 	schemasList := service.Schemas
 	if len(schemasList) == 0 {
 		return &pb.GetAllSchemaResponse{
-			Response: proto.CreateResponse(proto.Response_SUCCESS, "Do not have this schema info."),
+			Response: proto.CreateResponse(proto.ResponseSuccess, "Do not have this schema info."),
 			Schemas:  []*pb.Schema{},
 		}, nil
 	}
 
 	key := apt.GenerateServiceSchemaSummaryKey(domainProject, request.ServiceId, "")
-	opts := append(serviceUtil.FromContext(ctx), registry.WithStrKey(key), registry.WithPrefix())
-	resp, errDo := backend.Store().SchemaSummary().Search(ctx, opts...)
+	opts := append(serviceUtil.FromContext(ctx), client.WithStrKey(key), client.WithPrefix())
+	resp, errDo := kv.Store().SchemaSummary().Search(ctx, opts...)
 	if errDo != nil {
 		log.Errorf(errDo, "get service[%s] all schema summaries failed", request.ServiceId)
 		return &pb.GetAllSchemaResponse{
@@ -1393,11 +1401,11 @@ func (ds *DataSource) GetAllSchemas(ctx context.Context, request *pb.GetAllSchem
 		}, errDo
 	}
 
-	respWithSchema := &discovery.Response{}
+	respWithSchema := &sd.Response{}
 	if request.WithSchema {
 		key := apt.GenerateServiceSchemaKey(domainProject, request.ServiceId, "")
-		opts := append(serviceUtil.FromContext(ctx), registry.WithStrKey(key), registry.WithPrefix())
-		respWithSchema, errDo = backend.Store().Schema().Search(ctx, opts...)
+		opts := append(serviceUtil.FromContext(ctx), client.WithStrKey(key), client.WithPrefix())
+		respWithSchema, errDo = kv.Store().Schema().Search(ctx, opts...)
 		if errDo != nil {
 			log.Errorf(errDo, "get service[%s] all schemas failed", request.ServiceId)
 			return &pb.GetAllSchemaResponse{
@@ -1427,7 +1435,7 @@ func (ds *DataSource) GetAllSchemas(ctx context.Context, request *pb.GetAllSchem
 	}
 
 	return &pb.GetAllSchemaResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get all schema info successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get all schema info successfully."),
 		Schemas:  schemas,
 	}, nil
 }
@@ -1462,15 +1470,15 @@ func (ds *DataSource) DeleteSchema(ctx context.Context, request *pb.DeleteSchema
 		}, nil
 	}
 	epSummaryKey := apt.GenerateServiceSchemaSummaryKey(domainProject, request.ServiceId, request.SchemaId)
-	opts := []registry.PluginOp{
-		registry.OpDel(registry.WithStrKey(epSummaryKey)),
-		registry.OpDel(registry.WithStrKey(key)),
+	opts := []client.PluginOp{
+		client.OpDel(client.WithStrKey(epSummaryKey)),
+		client.OpDel(client.WithStrKey(key)),
 	}
 
-	resp, errDo := backend.Registry().TxnWithCmp(ctx, opts,
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
-			registry.CmpNotEqual, 0)},
+	resp, errDo := client.Instance().TxnWithCmp(ctx, opts,
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
+			client.CmpNotEqual, 0)},
 		nil)
 	if errDo != nil {
 		log.Errorf(errDo, "delete schema[%s/%s] failed, operator: %s",
@@ -1490,7 +1498,7 @@ func (ds *DataSource) DeleteSchema(ctx context.Context, request *pb.DeleteSchema
 	log.Infof("delete schema[%s/%s] info successfully, operator: %s",
 		request.ServiceId, request.SchemaId, remoteIP)
 	return &pb.DeleteSchemaResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Delete schema info successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Delete schema info successfully."),
 	}, nil
 }
 
@@ -1509,7 +1517,7 @@ func (ds *DataSource) AddTags(ctx context.Context, request *pb.AddServiceTagsReq
 
 	addTags := request.Tags
 	res := quota.NewApplyQuotaResource(quota.TagQuotaType, domainProject, request.ServiceId, int64(len(addTags)))
-	rst := plugin.Plugins().Quota().Apply4Quotas(ctx, res)
+	rst := quota.Apply(ctx, res)
 	errQuota := rst.Err
 	if errQuota != nil {
 		log.Errorf(errQuota, "add service[%s]'s tags %v failed, operator: %s", request.ServiceId, addTags, remoteIP)
@@ -1552,7 +1560,7 @@ func (ds *DataSource) AddTags(ctx context.Context, request *pb.AddServiceTagsReq
 
 	log.Infof("add service[%s]'s tags %v successfully, operator: %s", request.ServiceId, request.Tags, remoteIP)
 	return &pb.AddServiceTagsResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Add service tags successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Add service tags successfully."),
 	}, nil
 }
 
@@ -1574,7 +1582,7 @@ func (ds *DataSource) GetTags(ctx context.Context, request *pb.GetServiceTagsReq
 	}
 
 	return &pb.GetServiceTagsResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get service tags successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get service tags successfully."),
 		Tags:     tags,
 	}, nil
 }
@@ -1631,7 +1639,7 @@ func (ds *DataSource) UpdateTag(ctx context.Context, request *pb.UpdateServiceTa
 
 	log.Infof("update service[%s]'s tag[%s] successfully, operator: %s", request.ServiceId, tagFlag, remoteIP)
 	return &pb.UpdateServiceTagResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Update service tag success."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Update service tag success."),
 	}, nil
 }
 
@@ -1683,11 +1691,11 @@ func (ds *DataSource) DeleteTags(ctx context.Context, request *pb.DeleteServiceT
 
 	key := apt.GenerateServiceTagKey(domainProject, request.ServiceId)
 
-	resp, err := backend.Registry().TxnWithCmp(ctx,
-		[]registry.PluginOp{registry.OpPut(registry.WithStrKey(key), registry.WithValue(data))},
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.Instance().TxnWithCmp(ctx,
+		[]client.PluginOp{client.OpPut(client.WithStrKey(key), client.WithValue(data))},
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		log.Errorf(err, "delete service[%s]'s tags %v failed, operator: %s",
@@ -1706,7 +1714,7 @@ func (ds *DataSource) DeleteTags(ctx context.Context, request *pb.DeleteServiceT
 
 	log.Infof("delete service[%s]'s tags %v successfully, operator: %s", request.ServiceId, request.Keys, remoteIP)
 	return &pb.DeleteServiceTagsResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Delete service tags successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Delete service tags successfully."),
 	}, nil
 }
 
@@ -1724,7 +1732,7 @@ func (ds *DataSource) AddRule(ctx context.Context, request *pb.AddServiceRulesRe
 		}, nil
 	}
 	res := quota.NewApplyQuotaResource(quota.RuleQuotaType, domainProject, request.ServiceId, int64(len(request.Rules)))
-	rst := plugin.Plugins().Quota().Apply4Quotas(ctx, res)
+	rst := quota.Apply(ctx, res)
 	errQuota := rst.Err
 	if errQuota != nil {
 		log.Errorf(errQuota, "add service[%s] rule failed, operator: %s", request.ServiceId, remoteIP)
@@ -1744,7 +1752,7 @@ func (ds *DataSource) AddRule(ctx context.Context, request *pb.AddServiceRulesRe
 		}, err
 	}
 	ruleIDs := make([]string, 0, len(request.Rules))
-	opts := make([]registry.PluginOp, 0, 2*len(request.Rules))
+	opts := make([]client.PluginOp, 0, 2*len(request.Rules))
 	for _, rule := range request.Rules {
 		//黑白名单只能存在一种,黑名单 or 白名单
 		if len(ruleType) == 0 {
@@ -1792,21 +1800,21 @@ func (ds *DataSource) AddRule(ctx context.Context, request *pb.AddServiceRulesRe
 			}, err
 		}
 
-		opts = append(opts, registry.OpPut(registry.WithStrKey(key), registry.WithValue(data)))
-		opts = append(opts, registry.OpPut(registry.WithStrKey(indexKey), registry.WithStrValue(ruleAdd.RuleId)))
+		opts = append(opts, client.OpPut(client.WithStrKey(key), client.WithValue(data)))
+		opts = append(opts, client.OpPut(client.WithStrKey(indexKey), client.WithStrValue(ruleAdd.RuleId)))
 	}
 	if len(opts) <= 0 {
 		log.Infof("add service[%s] rule successfully, no rules to add, operator: %s",
 			request.ServiceId, remoteIP)
 		return &pb.AddServiceRulesResponse{
-			Response: proto.CreateResponse(proto.Response_SUCCESS, "Service rules has been added."),
+			Response: proto.CreateResponse(proto.ResponseSuccess, "Service rules has been added."),
 		}, nil
 	}
 
-	resp, err := backend.BatchCommitWithCmp(ctx, opts,
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.BatchCommitWithCmp(ctx, opts,
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		log.Errorf(err, "add service[%s] rule failed, operator: %s", request.ServiceId, remoteIP)
@@ -1824,7 +1832,7 @@ func (ds *DataSource) AddRule(ctx context.Context, request *pb.AddServiceRulesRe
 
 	log.Infof("add service[%s] rule %v successfully, operator: %s", request.ServiceId, ruleIDs, remoteIP)
 	return &pb.AddServiceRulesResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Add service rules successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Add service rules successfully."),
 		RuleIds:  ruleIDs,
 	}, nil
 }
@@ -1850,7 +1858,7 @@ func (ds *DataSource) GetRule(ctx context.Context, request *pb.GetServiceRulesRe
 	}
 
 	return &pb.GetServiceRulesResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get service rules successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get service rules successfully."),
 		Rules:    rules,
 	}, nil
 }
@@ -1927,22 +1935,22 @@ func (ds *DataSource) UpdateRule(ctx context.Context, request *pb.UpdateServiceR
 			Response: proto.CreateResponse(scerr.ErrInternal, err.Error()),
 		}, err
 	}
-	var opts []registry.PluginOp
+	var opts []client.PluginOp
 	if isChangeIndex {
 		//加入新的rule index
 		indexKey := apt.GenerateRuleIndexKey(domainProject, request.ServiceId, copyRuleRef.Attribute, copyRuleRef.Pattern)
-		opts = append(opts, registry.OpPut(registry.WithStrKey(indexKey), registry.WithStrValue(copyRuleRef.RuleId)))
+		opts = append(opts, client.OpPut(client.WithStrKey(indexKey), client.WithStrValue(copyRuleRef.RuleId)))
 
 		//删除旧的rule index
 		oldIndexKey := apt.GenerateRuleIndexKey(domainProject, request.ServiceId, oldRuleAttr, oldRulePatten)
-		opts = append(opts, registry.OpDel(registry.WithStrKey(oldIndexKey)))
+		opts = append(opts, client.OpDel(client.WithStrKey(oldIndexKey)))
 	}
-	opts = append(opts, registry.OpPut(registry.WithStrKey(key), registry.WithValue(data)))
+	opts = append(opts, client.OpPut(client.WithStrKey(key), client.WithValue(data)))
 
-	resp, err := backend.Registry().TxnWithCmp(ctx, opts,
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.Instance().TxnWithCmp(ctx, opts,
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		log.Errorf(err, "update service rule[%s/%s] failed, operator: %s", request.ServiceId, request.RuleId, remoteIP)
@@ -1960,7 +1968,7 @@ func (ds *DataSource) UpdateRule(ctx context.Context, request *pb.UpdateServiceR
 
 	log.Infof("update service rule[%s/%s] successfully, operator: %s", request.ServiceId, request.RuleId, remoteIP)
 	return &pb.UpdateServiceRuleResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Get service rules successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Get service rules successfully."),
 	}, nil
 }
 
@@ -1978,7 +1986,7 @@ func (ds *DataSource) DeleteRule(ctx context.Context, request *pb.DeleteServiceR
 		}, nil
 	}
 
-	opts := []registry.PluginOp{}
+	opts := []client.PluginOp{}
 	key := ""
 	indexKey := ""
 	for _, ruleID := range request.RuleIds {
@@ -2001,8 +2009,8 @@ func (ds *DataSource) DeleteRule(ctx context.Context, request *pb.DeleteServiceR
 		}
 		indexKey = apt.GenerateRuleIndexKey(domainProject, request.ServiceId, data.Attribute, data.Pattern)
 		opts = append(opts,
-			registry.OpDel(registry.WithStrKey(key)),
-			registry.OpDel(registry.WithStrKey(indexKey)))
+			client.OpDel(client.WithStrKey(key)),
+			client.OpDel(client.WithStrKey(indexKey)))
 	}
 	if len(opts) <= 0 {
 		log.Errorf(nil, "delete service[%s] rules %v failed, no rule has been deleted, operator: %s",
@@ -2012,10 +2020,10 @@ func (ds *DataSource) DeleteRule(ctx context.Context, request *pb.DeleteServiceR
 		}, nil
 	}
 
-	resp, err := backend.BatchCommitWithCmp(ctx, opts,
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.BatchCommitWithCmp(ctx, opts,
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, request.ServiceId))),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		log.Errorf(err, "delete service[%s] rules %v failed, operator: %s", request.ServiceId, request.RuleIds, remoteIP)
@@ -2033,7 +2041,7 @@ func (ds *DataSource) DeleteRule(ctx context.Context, request *pb.DeleteServiceR
 
 	log.Infof("delete service[%s] rules %v successfully, operator: %s", request.ServiceId, request.RuleIds, remoteIP)
 	return &pb.DeleteServiceRulesResponse{
-		Response: proto.CreateResponse(proto.Response_SUCCESS, "Delete service rules successfully."),
+		Response: proto.CreateResponse(proto.ResponseSuccess, "Delete service rules successfully."),
 	}, nil
 }
 
@@ -2051,11 +2059,11 @@ func (ds *DataSource) modifySchemas(ctx context.Context, domainProject string, s
 	needUpdateSchemas, needAddSchemas, needDeleteSchemas, nonExistSchemaIds :=
 		schemasAnalysis(schemas, schemasFromDatabase, service.Schemas)
 
-	pluginOps := make([]registry.PluginOp, 0)
+	pluginOps := make([]client.PluginOp, 0)
 	if !ds.isSchemaEditable(service) {
 		if len(service.Schemas) == 0 {
 			res := quota.NewApplyQuotaResource(quota.SchemaQuotaType, domainProject, serviceID, int64(len(nonExistSchemaIds)))
-			rst := plugin.Plugins().Quota().Apply4Quotas(ctx, res)
+			rst := quota.Apply(ctx, res)
 			errQuota := rst.Err
 			if errQuota != nil {
 				log.Errorf(errQuota, "modify service[%s] schemas failed, operator: %s", serviceID, remoteIP)
@@ -2082,7 +2090,7 @@ func (ds *DataSource) modifySchemas(ctx context.Context, domainProject string, s
 					return scerr.NewError(scerr.ErrInternal, err.Error())
 				}
 				if !exist {
-					opts := schemaWithDatabaseOpera(registry.OpPut, domainProject, serviceID, needUpdateSchema)
+					opts := schemaWithDatabaseOpera(client.OpPut, domainProject, serviceID, needUpdateSchema)
 					pluginOps = append(pluginOps, opts...)
 				} else {
 					log.Warnf("schema[%s/%s] and it's summary already exist, skip to update, operator: %s",
@@ -2093,14 +2101,14 @@ func (ds *DataSource) modifySchemas(ctx context.Context, domainProject string, s
 
 		for _, schema := range needAddSchemas {
 			log.Infof("add new schema[%s/%s], operator: %s", serviceID, schema.SchemaId, remoteIP)
-			opts := schemaWithDatabaseOpera(registry.OpPut, domainProject, service.ServiceId, schema)
+			opts := schemaWithDatabaseOpera(client.OpPut, domainProject, service.ServiceId, schema)
 			pluginOps = append(pluginOps, opts...)
 		}
 	} else {
 		quotaSize := len(needAddSchemas) - len(needDeleteSchemas)
 		if quotaSize > 0 {
 			res := quota.NewApplyQuotaResource(quota.SchemaQuotaType, domainProject, serviceID, int64(quotaSize))
-			rst := plugin.Plugins().Quota().Apply4Quotas(ctx, res)
+			rst := quota.Apply(ctx, res)
 			err := rst.Err
 			if err != nil {
 				log.Errorf(err, "modify service[%s] schemas failed, operator: %s", serviceID, remoteIP)
@@ -2111,21 +2119,21 @@ func (ds *DataSource) modifySchemas(ctx context.Context, domainProject string, s
 		var schemaIDs []string
 		for _, schema := range needAddSchemas {
 			log.Infof("add new schema[%s/%s], operator: %s", serviceID, schema.SchemaId, remoteIP)
-			opts := schemaWithDatabaseOpera(registry.OpPut, domainProject, service.ServiceId, schema)
+			opts := schemaWithDatabaseOpera(client.OpPut, domainProject, service.ServiceId, schema)
 			pluginOps = append(pluginOps, opts...)
 			schemaIDs = append(schemaIDs, schema.SchemaId)
 		}
 
 		for _, schema := range needUpdateSchemas {
 			log.Infof("update schema[%s/%s], operator: %s", serviceID, schema.SchemaId, remoteIP)
-			opts := schemaWithDatabaseOpera(registry.OpPut, domainProject, serviceID, schema)
+			opts := schemaWithDatabaseOpera(client.OpPut, domainProject, serviceID, schema)
 			pluginOps = append(pluginOps, opts...)
 			schemaIDs = append(schemaIDs, schema.SchemaId)
 		}
 
 		for _, schema := range needDeleteSchemas {
 			log.Infof("delete non-existent schema[%s/%s], operator: %s", serviceID, schema.SchemaId, remoteIP)
-			opts := schemaWithDatabaseOpera(registry.OpDel, domainProject, serviceID, schema)
+			opts := schemaWithDatabaseOpera(client.OpDel, domainProject, serviceID, schema)
 			pluginOps = append(pluginOps, opts...)
 		}
 
@@ -2140,10 +2148,10 @@ func (ds *DataSource) modifySchemas(ctx context.Context, domainProject string, s
 	}
 
 	if len(pluginOps) != 0 {
-		resp, err := backend.BatchCommitWithCmp(ctx, pluginOps,
-			[]registry.CompareOp{registry.OpCmp(
-				registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, serviceID))),
-				registry.CmpNotEqual, 0)},
+		resp, err := client.BatchCommitWithCmp(ctx, pluginOps,
+			[]client.CompareOp{client.OpCmp(
+				client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, serviceID))),
+				client.CmpNotEqual, 0)},
 			nil)
 		if err != nil {
 			return scerr.NewError(scerr.ErrUnavailableBackend, err.Error())
@@ -2176,7 +2184,7 @@ func (ds *DataSource) modifySchema(ctx context.Context, serviceID string, schema
 		return scerr.NewError(scerr.ErrServiceNotExists, "Service does not exist")
 	}
 
-	var pluginOps []registry.PluginOp
+	var pluginOps []client.PluginOp
 	isExist := isExistSchemaID(microService, []*pb.Schema{schema})
 
 	if !ds.isSchemaEditable(microService) {
@@ -2185,7 +2193,7 @@ func (ds *DataSource) modifySchema(ctx context.Context, serviceID string, schema
 		}
 
 		key := apt.GenerateServiceSchemaKey(domainProject, serviceID, schemaID)
-		respSchema, err := backend.Store().Schema().Search(ctx, registry.WithStrKey(key), registry.WithCountOnly())
+		respSchema, err := kv.Store().Schema().Search(ctx, client.WithStrKey(key), client.WithCountOnly())
 		if err != nil {
 			log.Errorf(err, "modify schema[%s/%s] failed, get schema summary failed, operator: %s",
 				serviceID, schemaID, remoteIP)
@@ -2239,10 +2247,10 @@ func (ds *DataSource) modifySchema(ctx context.Context, serviceID string, schema
 	opts := commitSchemaInfo(domainProject, serviceID, schema)
 	pluginOps = append(pluginOps, opts...)
 
-	resp, err := backend.Registry().TxnWithCmp(ctx, pluginOps,
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, serviceID))),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.Instance().TxnWithCmp(ctx, pluginOps,
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(apt.GenerateServiceKey(domainProject, serviceID))),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		return scerr.NewError(scerr.ErrUnavailableBackend, err.Error())
@@ -2297,10 +2305,10 @@ func (ds *DataSource) DeleteServicePri(ctx context.Context, serviceID string, fo
 		}
 
 		instancesKey := apt.GenerateInstanceKey(domainProject, serviceID, "")
-		rsp, err := backend.Store().Instance().Search(ctx,
-			registry.WithStrKey(instancesKey),
-			registry.WithPrefix(),
-			registry.WithCountOnly())
+		rsp, err := kv.Store().Instance().Search(ctx,
+			client.WithStrKey(instancesKey),
+			client.WithPrefix(),
+			client.WithCountOnly())
 		if err != nil {
 			log.Errorf(err, "delete micro-service[%s] failed, get instances failed, operator: %s",
 				serviceID, remoteIP)
@@ -2323,10 +2331,10 @@ func (ds *DataSource) DeleteServicePri(ctx context.Context, serviceID string, fo
 		Version:     microservice.Version,
 		Alias:       microservice.Alias,
 	}
-	opts := []registry.PluginOp{
-		registry.OpDel(registry.WithStrKey(apt.GenerateServiceIndexKey(serviceKey))),
-		registry.OpDel(registry.WithStrKey(apt.GenerateServiceAliasKey(serviceKey))),
-		registry.OpDel(registry.WithStrKey(serviceIDKey)),
+	opts := []client.PluginOp{
+		client.OpDel(client.WithStrKey(apt.GenerateServiceIndexKey(serviceKey))),
+		client.OpDel(client.WithStrKey(apt.GenerateServiceAliasKey(serviceKey))),
+		client.OpDel(client.WithStrKey(serviceIDKey)),
 	}
 
 	//删除依赖规则
@@ -2339,32 +2347,32 @@ func (ds *DataSource) DeleteServicePri(ctx context.Context, serviceID string, fo
 	opts = append(opts, optDeleteDep)
 
 	//删除黑白名单
-	opts = append(opts, registry.OpDel(
-		registry.WithStrKey(apt.GenerateServiceRuleKey(domainProject, serviceID, "")),
-		registry.WithPrefix()))
-	opts = append(opts, registry.OpDel(registry.WithStrKey(
+	opts = append(opts, client.OpDel(
+		client.WithStrKey(apt.GenerateServiceRuleKey(domainProject, serviceID, "")),
+		client.WithPrefix()))
+	opts = append(opts, client.OpDel(client.WithStrKey(
 		util.StringJoin([]string{apt.GetServiceRuleIndexRootKey(domainProject), serviceID, ""}, "/")),
-		registry.WithPrefix()))
+		client.WithPrefix()))
 
 	//删除schemas
-	opts = append(opts, registry.OpDel(
-		registry.WithStrKey(apt.GenerateServiceSchemaKey(domainProject, serviceID, "")),
-		registry.WithPrefix()))
-	opts = append(opts, registry.OpDel(
-		registry.WithStrKey(apt.GenerateServiceSchemaSummaryKey(domainProject, serviceID, "")),
-		registry.WithPrefix()))
+	opts = append(opts, client.OpDel(
+		client.WithStrKey(apt.GenerateServiceSchemaKey(domainProject, serviceID, "")),
+		client.WithPrefix()))
+	opts = append(opts, client.OpDel(
+		client.WithStrKey(apt.GenerateServiceSchemaSummaryKey(domainProject, serviceID, "")),
+		client.WithPrefix()))
 
 	//删除tags
-	opts = append(opts, registry.OpDel(
-		registry.WithStrKey(apt.GenerateServiceTagKey(domainProject, serviceID))))
+	opts = append(opts, client.OpDel(
+		client.WithStrKey(apt.GenerateServiceTagKey(domainProject, serviceID))))
 
 	//删除instances
-	opts = append(opts, registry.OpDel(
-		registry.WithStrKey(apt.GenerateInstanceKey(domainProject, serviceID, "")),
-		registry.WithPrefix()))
-	opts = append(opts, registry.OpDel(
-		registry.WithStrKey(apt.GenerateInstanceLeaseKey(domainProject, serviceID, "")),
-		registry.WithPrefix()))
+	opts = append(opts, client.OpDel(
+		client.WithStrKey(apt.GenerateInstanceKey(domainProject, serviceID, "")),
+		client.WithPrefix()))
+	opts = append(opts, client.OpDel(
+		client.WithStrKey(apt.GenerateInstanceLeaseKey(domainProject, serviceID, "")),
+		client.WithPrefix()))
 
 	//删除实例
 	err = serviceUtil.DeleteServiceAllInstances(ctx, serviceID)
@@ -2374,10 +2382,10 @@ func (ds *DataSource) DeleteServicePri(ctx context.Context, serviceID string, fo
 		return proto.CreateResponse(scerr.ErrUnavailableBackend, err.Error()), err
 	}
 
-	resp, err := backend.Registry().TxnWithCmp(ctx, opts,
-		[]registry.CompareOp{registry.OpCmp(
-			registry.CmpVer(util.StringToBytesWithNoCopy(serviceIDKey)),
-			registry.CmpNotEqual, 0)},
+	resp, err := client.Instance().TxnWithCmp(ctx, opts,
+		[]client.CompareOp{client.OpCmp(
+			client.CmpVer(util.StringToBytesWithNoCopy(serviceIDKey)),
+			client.CmpNotEqual, 0)},
 		nil)
 	if err != nil {
 		log.Errorf(err, "%s micro-service[%s] failed, operator: %s", title, serviceID, remoteIP)
@@ -2392,7 +2400,7 @@ func (ds *DataSource) DeleteServicePri(ctx context.Context, serviceID string, fo
 	serviceUtil.RemandServiceQuota(ctx)
 
 	log.Infof("%s micro-service[%s] successfully, operator: %s", title, serviceID, remoteIP)
-	return proto.CreateResponse(proto.Response_SUCCESS, "Unregister service successfully."), nil
+	return proto.CreateResponse(proto.ResponseSuccess, "Unregister service successfully."), nil
 }
 
 func (ds *DataSource) GetDeleteServiceFunc(ctx context.Context, serviceID string, force bool,
@@ -2405,7 +2413,7 @@ func (ds *DataSource) GetDeleteServiceFunc(ctx context.Context, serviceID string
 		resp, err := ds.DeleteServicePri(ctx, serviceID, force)
 		if err != nil {
 			serviceRst.ErrMessage = err.Error()
-		} else if resp.GetCode() != proto.Response_SUCCESS {
+		} else if resp.GetCode() != proto.ResponseSuccess {
 			serviceRst.ErrMessage = resp.GetMessage()
 		}
 
diff --git a/datasource/etcd/ms_test.go b/datasource/etcd/ms_test.go
index 97b9886..b9ad2a3 100644
--- a/datasource/etcd/ms_test.go
+++ b/datasource/etcd/ms_test.go
@@ -15,10 +15,11 @@
  * limitations under the License.
  */
 
-package etcd
+package etcd_test
 
 import (
 	"github.com/apache/servicecomb-service-center/datasource"
+	"github.com/apache/servicecomb-service-center/datasource/etcd"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	pb "github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
@@ -43,16 +44,6 @@ func TestInit(t *testing.T) {
 
 func TestService_Register(t *testing.T) {
 	t.Run("Register service after init & install, should pass", func(t *testing.T) {
-		datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-			return NewDataSource(opts), nil
-		})
-
-		err := datasource.Init(datasource.Options{
-			Endpoint:       "",
-			PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-		})
-		assert.NoError(t, err)
-
 		size := quota.DefaultSchemaQuota + 1
 		paths := make([]*pb.ServicePath, 0, size)
 		properties := make(map[string]string, size)
@@ -84,19 +75,10 @@ func TestService_Register(t *testing.T) {
 		resp, err := datasource.Instance().RegisterService(getContext(), request)
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("register service with same key", func(t *testing.T) {
-		datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-			return NewDataSource(opts), nil
-		})
-		err := datasource.Init(datasource.Options{
-			Endpoint:       "",
-			PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-		})
-		assert.NoError(t, err)
-
 		// serviceName: some-relay-ms-service-name
 		// alias: sr-ms-service-name
 		resp, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -114,7 +96,7 @@ func TestService_Register(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		sameId := resp.ServiceId
 
 		// serviceName: some-relay-ms-service-name
@@ -174,7 +156,7 @@ func TestService_Register(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		// serviceName: some-relay-ms-service-name
 		// alias: sr1-ms-service-name
@@ -195,7 +177,7 @@ func TestService_Register(t *testing.T) {
 		})
 		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		// serviceName: some-relay-ms-service-name
 		// alias: sr1-ms-service-name
@@ -242,15 +224,6 @@ func TestService_Register(t *testing.T) {
 
 	t.Run("same serviceId,different service, can not register again,error is same as the service register twice",
 		func(t *testing.T) {
-			datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-				return NewDataSource(opts), nil
-			})
-			err := datasource.Init(datasource.Options{
-				Endpoint:       "",
-				PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-			})
-			assert.NoError(t, err)
-
 			resp, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 				Service: &pb.MicroService{
 					ServiceId:   "same-serviceId-service-ms",
@@ -267,7 +240,7 @@ func TestService_Register(t *testing.T) {
 
 			assert.NotNil(t, resp)
 			assert.NoError(t, err)
-			assert.Equal(t, resp.Response.GetCode(), proto.Response_SUCCESS)
+			assert.Equal(t, resp.Response.GetCode(), proto.ResponseSuccess)
 
 			// same serviceId with different service name
 			resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -292,29 +265,12 @@ func TestService_Register(t *testing.T) {
 func TestService_Get(t *testing.T) {
 	// get service test
 	t.Run("query all services, should pass", func(t *testing.T) {
-		datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-			return NewDataSource(opts), nil
-		})
-		err := datasource.Init(datasource.Options{
-			Endpoint:       "",
-			PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-		})
-		assert.NoError(t, err)
 		resp, err := datasource.Instance().GetServices(getContext(), &pb.GetServicesRequest{})
 		assert.NoError(t, err)
 		assert.Greater(t, len(resp.Services), 0)
 	})
 
 	t.Run("get a exist service, should pass", func(t *testing.T) {
-		datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-			return NewDataSource(opts), nil
-		})
-		err := datasource.Init(datasource.Options{
-			Endpoint:       "",
-			PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-		})
-		assert.NoError(t, err)
-
 		request := &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
 				ServiceId:   "ms-service-query-id",
@@ -328,26 +284,17 @@ func TestService_Get(t *testing.T) {
 
 		resp, err := datasource.Instance().RegisterService(getContext(), request)
 		assert.NoError(t, err)
-		assert.Equal(t, resp.Response.GetCode(), proto.Response_SUCCESS)
+		assert.Equal(t, resp.Response.GetCode(), proto.ResponseSuccess)
 
 		// search service by serviceID
 		queryResp, err := datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: "ms-service-query-id",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, queryResp.Response.GetCode(), proto.Response_SUCCESS)
+		assert.Equal(t, queryResp.Response.GetCode(), proto.ResponseSuccess)
 	})
 
 	t.Run("query a service by a not existed serviceId, should not pass", func(t *testing.T) {
-		datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-			return NewDataSource(opts), nil
-		})
-		err := datasource.Init(datasource.Options{
-			Endpoint:       "",
-			PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-		})
-		assert.NoError(t, err)
-
 		// not exist service
 		resp, err := datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: "no-exist-service",
@@ -362,17 +309,6 @@ func TestService_Exist(t *testing.T) {
 		serviceId1 string
 		serviceId2 string
 	)
-
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	t.Run("create service", func(t *testing.T) {
 		svc := &pb.MicroService{
 			Alias:       "es_service_ms",
@@ -530,16 +466,6 @@ func TestService_Exist(t *testing.T) {
 }
 
 func TestService_Update(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var serviceId string
 
 	t.Run("create service", func(t *testing.T) {
@@ -555,7 +481,7 @@ func TestService_Update(t *testing.T) {
 		})
 		assert.NoError(t, err)
 		assert.NotNil(t, resp)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.NotEqual(t, "", resp.ServiceId)
 		serviceId = resp.ServiceId
 	})
@@ -574,11 +500,11 @@ func TestService_Update(t *testing.T) {
 		request2.Properties["k"] = "v"
 		resp, err := datasource.Instance().UpdateService(getContext(), request)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().UpdateService(getContext(), request2)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		respGetService, err := datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceId,
@@ -597,7 +523,7 @@ func TestService_Update(t *testing.T) {
 		}
 		resp, err := datasource.Instance().UpdateService(getContext(), r)
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("update service by removing the properties", func(t *testing.T) {
@@ -608,7 +534,7 @@ func TestService_Update(t *testing.T) {
 		}
 		resp, err := datasource.Instance().UpdateService(getContext(), r)
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("remove properties for service with empty serviceId")
 		r = &pb.UpdateServicePropsRequest{
@@ -617,21 +543,11 @@ func TestService_Update(t *testing.T) {
 		}
 		resp, err = datasource.Instance().UpdateService(getContext(), r)
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestService_Delete(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceContainInstId string
 		serviceNoInstId      string
@@ -648,7 +564,7 @@ func TestService_Delete(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreate.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreate.Response.GetCode())
 		serviceContainInstId = respCreate.ServiceId
 
 		log.Info("attach instance")
@@ -664,7 +580,7 @@ func TestService_Delete(t *testing.T) {
 			Instance: instance,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateIns.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateIns.Response.GetCode())
 
 		log.Info("create service without instance")
 		provider := &pb.MicroService{
@@ -678,7 +594,7 @@ func TestService_Delete(t *testing.T) {
 			Service: provider,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreate.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreate.Response.GetCode())
 		serviceNoInstId = respCreate.ServiceId
 
 		respCreate, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -691,7 +607,7 @@ func TestService_Delete(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreate.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreate.Response.GetCode())
 	})
 
 	t.Run("delete a service which contains instances with no force flag", func(t *testing.T) {
@@ -701,7 +617,7 @@ func TestService_Delete(t *testing.T) {
 			Force:     false,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("delete a service which contains instances with force flag", func(t *testing.T) {
@@ -711,7 +627,7 @@ func TestService_Delete(t *testing.T) {
 			Force:     true,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	// todo: add delete service depended by consumer after finishing dependency management
@@ -723,7 +639,7 @@ func TestService_Delete(t *testing.T) {
 			Force:     true,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("delete a service with no force flag", func(t *testing.T) {
@@ -733,67 +649,47 @@ func TestService_Delete(t *testing.T) {
 			Force:     false,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestService_Info(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	t.Run("get all services", func(t *testing.T) {
 		log.Info("should be passed")
 		resp, err := datasource.Instance().GetServicesInfo(getContext(), &pb.GetServicesInfoRequest{
 			Options: []string{"all"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().GetServicesInfo(getContext(), &pb.GetServicesInfoRequest{
 			Options: []string{""},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().GetServicesInfo(getContext(), &pb.GetServicesInfoRequest{
 			Options: []string{"tags", "rules", "instances", "schemas", "statistics"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().GetServicesInfo(getContext(), &pb.GetServicesInfoRequest{
 			Options: []string{"statistics"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().GetServicesInfo(getContext(), &pb.GetServicesInfoRequest{
 			Options:   []string{"instances"},
 			CountOnly: true,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestService_Detail(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId string
 	)
@@ -810,7 +706,7 @@ func TestService_Detail(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		serviceId = resp.ServiceId
 
 		datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -819,7 +715,7 @@ func TestService_Detail(t *testing.T) {
 			Schema:    "detail",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
 			Instance: &pb.MicroServiceInstance{
@@ -832,73 +728,53 @@ func TestService_Detail(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("when get invalid service detail, should be failed")
 		respD, err := datasource.Instance().GetServiceDetail(getContext(), &pb.GetServiceRequest{
 			ServiceId: "",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respD.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respD.Response.GetCode())
 
 		log.Info("when get a service detail, should be passed")
 		respGetServiceDetail, err := datasource.Instance().GetServiceDetail(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceId,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respGetServiceDetail.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respGetServiceDetail.Response.GetCode())
 
 		respDelete, err := datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
 			ServiceId: serviceId,
 			Force:     true,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respDelete.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respDelete.Response.GetCode())
 
 		respGetServiceDetail, err = datasource.Instance().GetServiceDetail(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceId,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respGetServiceDetail.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respGetServiceDetail.Response.GetCode())
 	})
 }
 
 func TestApplication_Get(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	t.Run("execute 'get apps' operation", func(t *testing.T) {
 		log.Info("when request is valid, should be passed")
 		resp, err := datasource.Instance().GetApplications(getContext(), &pb.GetAppsRequest{})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().GetApplications(getContext(), &pb.GetAppsRequest{
 			Environment: pb.ENV_ACCEPT,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestInstance_Create(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var serviceId string
 
 	t.Run("create service", func(t *testing.T) {
@@ -913,7 +789,7 @@ func TestInstance_Create(t *testing.T) {
 		})
 
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 	})
 
@@ -929,7 +805,7 @@ func TestInstance_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInst.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInst.Response.GetCode())
 		assert.NotEqual(t, "", respCreateInst.InstanceId)
 
 		respCreateInst, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -944,7 +820,7 @@ func TestInstance_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInst.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInst.Response.GetCode())
 		assert.Equal(t, "customId_ms", respCreateInst.InstanceId)
 	})
 
@@ -961,27 +837,18 @@ func TestInstance_Create(t *testing.T) {
 			Instance: instance,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
 			Instance: instance,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.Equal(t, instance.InstanceId, resp.InstanceId)
 	})
 }
 
 func TestInstance_HeartBeat(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId   string
 		instanceId1 string
@@ -1000,7 +867,7 @@ func TestInstance_HeartBeat(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		respCreateInstance, err := datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1014,7 +881,7 @@ func TestInstance_HeartBeat(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId1 = respCreateInstance.InstanceId
 
 		respCreateInstance, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1028,7 +895,7 @@ func TestInstance_HeartBeat(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId2 = respCreateInstance.InstanceId
 	})
 
@@ -1039,7 +906,7 @@ func TestInstance_HeartBeat(t *testing.T) {
 			InstanceId: instanceId1,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("serviceId does not exist")
 		resp, err = datasource.Instance().Heartbeat(getContext(), &pb.HeartbeatRequest{
@@ -1047,7 +914,7 @@ func TestInstance_HeartBeat(t *testing.T) {
 			InstanceId: instanceId1,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("instance does not exist")
 		resp, err = datasource.Instance().Heartbeat(getContext(), &pb.HeartbeatRequest{
@@ -1055,7 +922,7 @@ func TestInstance_HeartBeat(t *testing.T) {
 			InstanceId: "not-exist-ins",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("batch update lease", func(t *testing.T) {
@@ -1073,20 +940,11 @@ func TestInstance_HeartBeat(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestInstance_Update(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId  string
 		instanceId string
@@ -1104,7 +962,7 @@ func TestInstance_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		log.Info("create instance")
@@ -1120,7 +978,7 @@ func TestInstance_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId = respCreateInstance.InstanceId
 	})
 
@@ -1132,7 +990,7 @@ func TestInstance_Update(t *testing.T) {
 			Status:     pb.MSI_DOWN,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateStatus.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateStatus.Response.GetCode())
 
 		log.Info("update instance status to OUTOFSERVICE")
 		respUpdateStatus, err = datasource.Instance().UpdateInstanceStatus(getContext(), &pb.UpdateInstanceStatusRequest{
@@ -1141,7 +999,7 @@ func TestInstance_Update(t *testing.T) {
 			Status:     pb.MSI_OUTOFSERVICE,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateStatus.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateStatus.Response.GetCode())
 
 		log.Info("update instance status to STARTING")
 		respUpdateStatus, err = datasource.Instance().UpdateInstanceStatus(getContext(), &pb.UpdateInstanceStatusRequest{
@@ -1150,7 +1008,7 @@ func TestInstance_Update(t *testing.T) {
 			Status:     pb.MSI_STARTING,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateStatus.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateStatus.Response.GetCode())
 
 		log.Info("update instance status to TESTING")
 		respUpdateStatus, err = datasource.Instance().UpdateInstanceStatus(getContext(), &pb.UpdateInstanceStatusRequest{
@@ -1159,7 +1017,7 @@ func TestInstance_Update(t *testing.T) {
 			Status:     pb.MSI_TESTING,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateStatus.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateStatus.Response.GetCode())
 
 		log.Info("update instance status to UP")
 		respUpdateStatus, err = datasource.Instance().UpdateInstanceStatus(getContext(), &pb.UpdateInstanceStatusRequest{
@@ -1168,7 +1026,7 @@ func TestInstance_Update(t *testing.T) {
 			Status:     pb.MSI_UP,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateStatus.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateStatus.Response.GetCode())
 
 		log.Info("update instance status with a not exist instance")
 		respUpdateStatus, err = datasource.Instance().UpdateInstanceStatus(getContext(), &pb.UpdateInstanceStatusRequest{
@@ -1177,7 +1035,7 @@ func TestInstance_Update(t *testing.T) {
 			Status:     pb.MSI_STARTING,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respUpdateStatus.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respUpdateStatus.Response.GetCode())
 	})
 
 	t.Run("update instance properties", func(t *testing.T) {
@@ -1191,7 +1049,7 @@ func TestInstance_Update(t *testing.T) {
 				},
 			})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateProperties.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateProperties.Response.GetCode())
 
 		log.Info("all max properties updated")
 		size := 1000
@@ -1207,7 +1065,7 @@ func TestInstance_Update(t *testing.T) {
 				Properties: properties,
 			})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateProperties.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateProperties.Response.GetCode())
 
 		log.Info("update instance that does not exist")
 		respUpdateProperties, err = datasource.Instance().UpdateInstanceProperties(getContext(),
@@ -1219,7 +1077,7 @@ func TestInstance_Update(t *testing.T) {
 				},
 			})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respUpdateProperties.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respUpdateProperties.Response.GetCode())
 
 		log.Info("remove properties")
 		respUpdateProperties, err = datasource.Instance().UpdateInstanceProperties(getContext(),
@@ -1228,7 +1086,7 @@ func TestInstance_Update(t *testing.T) {
 				InstanceId: instanceId,
 			})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respUpdateProperties.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respUpdateProperties.Response.GetCode())
 
 		log.Info("update service that does not exist")
 		respUpdateProperties, err = datasource.Instance().UpdateInstanceProperties(getContext(),
@@ -1240,20 +1098,11 @@ func TestInstance_Update(t *testing.T) {
 				},
 			})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respUpdateProperties.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respUpdateProperties.Response.GetCode())
 	})
 }
 
 func TestInstance_Query(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId1  string
 		serviceId2  string
@@ -1283,7 +1132,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId1 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1296,7 +1145,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId2 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1309,7 +1158,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId3 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1323,7 +1172,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId4 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1335,12 +1184,12 @@ func TestInstance_Query(t *testing.T) {
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 				Properties: map[string]string{
-					proto.PROP_ALLOW_CROSS_APP: "true",
+					proto.PropAllowCrossApp: "true",
 				},
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId5 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(
@@ -1355,7 +1204,7 @@ func TestInstance_Query(t *testing.T) {
 				},
 			})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId6 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1368,7 +1217,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId7 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1381,7 +1230,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId8 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1394,7 +1243,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId9 = respCreateService.ServiceId
 
 		respCreateInstance, err := datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1408,7 +1257,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId1 = respCreateInstance.InstanceId
 
 		respCreateInstance, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1422,7 +1271,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId2 = respCreateInstance.InstanceId
 
 		respCreateInstance, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1436,7 +1285,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId4 = respCreateInstance.InstanceId
 
 		respCreateInstance, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1450,7 +1299,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId5 = respCreateInstance.InstanceId
 
 		respCreateInstance, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1464,7 +1313,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId8 = respCreateInstance.InstanceId
 
 		respCreateInstance, err = datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1478,7 +1327,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId9 = respCreateInstance.InstanceId
 	})
 
@@ -1491,7 +1340,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule:       "latest",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, instanceId2, respFind.Instances[0].InstanceId)
 
 		respFind, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
@@ -1502,7 +1351,7 @@ func TestInstance_Query(t *testing.T) {
 			Tags:              []string{},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, instanceId2, respFind.Instances[0].InstanceId)
 
 		respFind, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
@@ -1512,7 +1361,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule:       "1.0.0",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, instanceId1, respFind.Instances[0].InstanceId)
 
 		respFind, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
@@ -1532,7 +1381,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule:       "1.0.0",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Instances))
 		assert.Equal(t, instanceId4, respFind.Instances[0].InstanceId)
 
@@ -1543,7 +1392,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule: "1.0.0",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Instances))
 		assert.Equal(t, instanceId4, respFind.Instances[0].InstanceId)
 
@@ -1556,7 +1405,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule:       "1.0.0",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		rev, _ := ctx.Value(util.CtxResponseRevision).(string)
 		assert.Equal(t, instanceId8, respFind.Instances[0].InstanceId)
 		assert.NotEqual(t, 0, len(rev))
@@ -1569,7 +1418,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule:       "1.0.0",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, instanceId8, respFind.Instances[0].InstanceId)
 		assert.Equal(t, ctx.Value(util.CtxResponseRevision), rev)
 
@@ -1581,7 +1430,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule:       "1.0.5",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 0, len(respFind.Instances))
 
 		log.Info("provider tag does not exist")
@@ -1593,7 +1442,7 @@ func TestInstance_Query(t *testing.T) {
 			Tags:              []string{"not_exist_tag"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 0, len(respFind.Instances))
 
 		log.Info("shared service discovery")
@@ -1611,7 +1460,7 @@ func TestInstance_Query(t *testing.T) {
 				VersionRule:       "1.0.0",
 			})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Instances))
 		assert.Equal(t, instanceId5, respFind.Instances[0].InstanceId)
 
@@ -1622,7 +1471,7 @@ func TestInstance_Query(t *testing.T) {
 			VersionRule:       "1.0.0",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Instances))
 		assert.Equal(t, instanceId5, respFind.Instances[0].InstanceId)
 
@@ -1661,7 +1510,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, int64(0), respFind.Services.Updated[0].Index)
 		assert.Equal(t, instanceId2, respFind.Services.Updated[0].Instances[0].InstanceId)
 		assert.Equal(t, int64(1), respFind.Services.Updated[1].Index)
@@ -1683,7 +1532,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Services.Updated[0].Instances))
 		assert.Equal(t, instanceId4, respFind.Services.Updated[0].Instances[0].InstanceId)
 
@@ -1723,7 +1572,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		rev := respFind.Services.Updated[0].Rev
 		assert.Equal(t, int64(0), respFind.Services.Updated[0].Index)
 		assert.Equal(t, int64(1), respFind.Services.Updated[1].Index)
@@ -1760,7 +1609,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, instanceId8, respFind.Services.Updated[0].Instances[0].InstanceId)
 		assert.Equal(t, respFind.Services.Updated[0].Rev, rev)
 		assert.Equal(t, instanceId9, respFind.Instances.Updated[0].Instances[0].InstanceId)
@@ -1789,7 +1638,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, int64(0), respFind.Services.NotModified[0])
 		assert.Equal(t, int64(0), respFind.Instances.NotModified[0])
 
@@ -1807,7 +1656,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 0, len(respFind.Services.Updated[0].Instances))
 
 		log.Info("shared service discovery")
@@ -1831,7 +1680,7 @@ func TestInstance_Query(t *testing.T) {
 				},
 			})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Services.Updated[0].Instances))
 		assert.Equal(t, instanceId5, respFind.Services.Updated[0].Instances[0].InstanceId)
 
@@ -1848,7 +1697,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Services.Updated[0].Instances))
 		assert.Equal(t, instanceId5, respFind.Services.Updated[0].Instances[0].InstanceId)
 
@@ -1867,7 +1716,7 @@ func TestInstance_Query(t *testing.T) {
 				},
 			})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, scerr.ErrServiceNotExists, respFind.Instances.Failed[0].Error.Code)
 
 		respFind, err = datasource.Instance().BatchFind(getContext(), &pb.BatchFindInstancesRequest{
@@ -1882,7 +1731,7 @@ func TestInstance_Query(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 1, len(respFind.Instances.Updated[0].Instances))
 		assert.Equal(t, instanceId5, respFind.Instances.Updated[0].Instances[0].InstanceId)
 
@@ -1902,7 +1751,7 @@ func TestInstance_Query(t *testing.T) {
 
 		UTFunc(serviceId3, scerr.ErrServiceNotExists)
 
-		UTFunc(serviceId1, proto.Response_SUCCESS)
+		UTFunc(serviceId1, proto.ResponseSuccess)
 
 		log.Info("diff env")
 		respFind, err := datasource.Instance().GetInstances(getContext(), &pb.GetInstancesRequest{
@@ -1910,20 +1759,11 @@ func TestInstance_Query(t *testing.T) {
 			ProviderServiceId: serviceId2,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respFind.Response.GetCode())
 	})
 }
 
 func TestInstance_GetOne(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId1  string
 		serviceId2  string
@@ -1942,7 +1782,7 @@ func TestInstance_GetOne(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId1 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1955,7 +1795,7 @@ func TestInstance_GetOne(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId2 = respCreateService.ServiceId
 
 		respCreateInstance, err := datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -1969,7 +1809,7 @@ func TestInstance_GetOne(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		instanceId2 = respCreateInstance.InstanceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -1982,7 +1822,7 @@ func TestInstance_GetOne(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId3 = respCreateService.ServiceId
 	})
 
@@ -1994,7 +1834,7 @@ func TestInstance_GetOne(t *testing.T) {
 			ProviderInstanceId: instanceId2,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("consumer does not exist")
 		resp, err = datasource.Instance().GetInstance(getContext(), &pb.GetOneInstanceRequest{
@@ -2003,7 +1843,7 @@ func TestInstance_GetOne(t *testing.T) {
 			ProviderInstanceId: instanceId2,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("get between diff apps", func(t *testing.T) {
@@ -2020,7 +1860,7 @@ func TestInstance_GetOne(t *testing.T) {
 			ProviderServiceId: serviceId2,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respAll.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respAll.Response.GetCode())
 	})
 
 	t.Run("get instances when request is invalid", func(t *testing.T) {
@@ -2030,7 +1870,7 @@ func TestInstance_GetOne(t *testing.T) {
 			ProviderServiceId: serviceId2,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("consumer does not exist")
 		resp, err = datasource.Instance().GetInstances(getContext(), &pb.GetInstancesRequest{
@@ -2038,20 +1878,11 @@ func TestInstance_GetOne(t *testing.T) {
 			ProviderServiceId: serviceId2,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestInstance_Unregister(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId  string
 		instanceId string
@@ -2071,7 +1902,7 @@ func TestInstance_Unregister(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		respCreateInstance, err := datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -2085,7 +1916,7 @@ func TestInstance_Unregister(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateInstance.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateInstance.Response.GetCode())
 		instanceId = respCreateInstance.InstanceId
 	})
 
@@ -2095,7 +1926,7 @@ func TestInstance_Unregister(t *testing.T) {
 			InstanceId: instanceId,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("unregister instance when request is invalid", func(t *testing.T) {
@@ -2105,7 +1936,7 @@ func TestInstance_Unregister(t *testing.T) {
 			InstanceId: instanceId,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("instance id does not exist")
 		resp, err = datasource.Instance().UnregisterInstance(getContext(), &pb.UnregisterInstanceRequest{
@@ -2113,20 +1944,11 @@ func TestInstance_Unregister(t *testing.T) {
 			InstanceId: "not-exist-id-ms",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestSchema_Create(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceIdDev string
 	)
@@ -2145,7 +1967,7 @@ func TestSchema_Create(t *testing.T) {
 		})
 		assert.NoError(t, err)
 		assert.NotEqual(t, "", resp.ServiceId)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		serviceIdDev = resp.ServiceId
 
 		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -2160,7 +1982,7 @@ func TestSchema_Create(t *testing.T) {
 		})
 		assert.NoError(t, err)
 		assert.NotEqual(t, "", resp.ServiceId)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("create schemas out of gauge", func(t *testing.T) {
@@ -2193,7 +2015,7 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas[:quota.DefaultSchemaQuota],
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("should be failed in production env")
 		resp, err = datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
@@ -2222,7 +2044,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		serviceIdDev1 = resp.ServiceId
 
 		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -2239,7 +2061,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		serviceIdDev2 = resp.ServiceId
 
 		log.Info("create schemas with service schemaId set is empty")
@@ -2260,7 +2082,7 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateSchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateSchema.Response.GetCode())
 
 		// todo: test GetAllSchemaInfo interface refers to schema_test line 342
 
@@ -2290,14 +2112,14 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateSchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateSchema.Response.GetCode())
 
 		log.Info("query service by serviceID to obtain schema info")
 		respGetService, err := datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceIdDev1,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respGetService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respGetService.Response.GetCode())
 		assert.Equal(t, []string{"second_schemaId_service_ms"}, respGetService.Service.Schemas)
 
 		log.Info("add new schemaId not exist in service's schemaId list")
@@ -2313,13 +2135,13 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateSchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateSchema.Response.GetCode())
 
 		respGetService, err = datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceIdDev2,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respGetService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respGetService.Response.GetCode())
 		assert.Equal(t, []string{"second_schemaId_service_ms"}, respGetService.Service.Schemas)
 	})
 
@@ -2341,7 +2163,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro1 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -2359,7 +2181,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro2 = respCreateService.ServiceId
 
 		log.Info("add schemas to service whose schemaId set is empty")
@@ -2380,12 +2202,12 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchemas.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchemas.Response.GetCode())
 		respGetService, err := datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceIdPro1,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respGetService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respGetService.Response.GetCode())
 		assert.Equal(t, []string{"first_schemaId_service_ms"}, respGetService.Service.Schemas)
 
 		// todo: finish ut after implementing GetAllSchemaInfo, refer to schema_test.go line. 496
@@ -2396,7 +2218,7 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchemas.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchemas.Response.GetCode())
 
 		log.Info("add schemas, non-exist schemaId")
 		schemas = []*pb.Schema{
@@ -2420,7 +2242,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "first_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("add schemas when summary in database is empty")
 		schemas = []*pb.Schema{
@@ -2435,7 +2257,7 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchemas.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchemas.Response.GetCode())
 		respExist, err := datasource.Instance().ExistSchema(getContext(), &pb.GetExistenceRequest{
 			Type:      service.ExistTypeSchema,
 			ServiceId: serviceIdPro2,
@@ -2449,7 +2271,7 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchemas.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchemas.Response.GetCode())
 	})
 
 	t.Run("create a schema in dev env", func(t *testing.T) {
@@ -2470,7 +2292,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdDev1 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -2487,7 +2309,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdDev2 = respCreateService.ServiceId
 
 		log.Info("create a schema for service whose schemaID is empty")
@@ -2497,7 +2319,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "first_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("create schema for the service whose schemaId already exist")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2506,7 +2328,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "first_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("create schema for the service whose schema summary is empty")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2516,7 +2338,7 @@ func TestSchema_Create(t *testing.T) {
 			Summary:   "first0summary1change_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("create schema for the service whose schema summary already exist")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2526,7 +2348,7 @@ func TestSchema_Create(t *testing.T) {
 			Summary:   "first0summary_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("add schema")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2535,7 +2357,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "second_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 	})
 
@@ -2557,7 +2379,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro1 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -2575,7 +2397,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro2 = respCreateService.ServiceId
 
 		log.Info("create a schema for service whose schemaID is empty")
@@ -2585,7 +2407,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "first_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("modify schema for the service whose schema summary is empty")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2595,7 +2417,7 @@ func TestSchema_Create(t *testing.T) {
 			Summary:   "first0summary1change_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("modify schema for the service whose schema summary already exist")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2605,7 +2427,7 @@ func TestSchema_Create(t *testing.T) {
 			Summary:   "first0summary_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("add schema")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2614,7 +2436,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "second_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("modify schema for the service whose schemaId already exist")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2623,7 +2445,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "first_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 	})
 
@@ -2644,7 +2466,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro1 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -2661,7 +2483,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro2 = respCreateService.ServiceId
 
 		log.Info("create a schema for service whose schemaID is empty")
@@ -2671,7 +2493,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "first_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("modify schema for the service whose schema summary is empty")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2681,7 +2503,7 @@ func TestSchema_Create(t *testing.T) {
 			Summary:   "first0summary1change_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("modify schema for the service whose schema summary already exist")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2691,7 +2513,7 @@ func TestSchema_Create(t *testing.T) {
 			Summary:   "first0summary_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("add schema")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2700,7 +2522,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "second_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 
 		log.Info("modify schema for the service whose schemaId already exist")
 		respModifySchema, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2709,7 +2531,7 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    "first_schema_service_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 	})
 
 	t.Run("add a schemaId in production env while schema editable is set", func(t *testing.T) {
@@ -2728,7 +2550,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro1 = respCreateService.ServiceId
 
 		log.Info("add a schema with new schemaId, should pass")
@@ -2744,13 +2566,13 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchemas.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchemas.Response.GetCode())
 
 		respService, err := datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceIdPro1,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respService.Response.GetCode())
 		assert.Equal(t, []string{"first_schemaId_ms"}, respService.Service.Schemas)
 
 		schemas = []*pb.Schema{
@@ -2762,7 +2584,7 @@ func TestSchema_Create(t *testing.T) {
 		}
 		log.Info("schema edit not allowed, add a schema with new schemaId should fail")
 
-		localMicroServiceDs := &DataSource{SchemaEditable: false}
+		localMicroServiceDs := &etcd.DataSource{SchemaEditable: false}
 		respModifySchemas, err = localMicroServiceDs.ModifySchemas(getContext(), &pb.ModifySchemasRequest{
 			ServiceId: serviceIdPro1,
 			Schemas:   schemas,
@@ -2771,13 +2593,13 @@ func TestSchema_Create(t *testing.T) {
 		assert.Equal(t, scerr.ErrUndefinedSchemaID, respModifySchemas.Response.GetCode())
 
 		log.Info("schema edit allowed, add a schema with new schemaId, should pass")
-		localMicroServiceDs = &DataSource{SchemaEditable: true}
+		localMicroServiceDs = &etcd.DataSource{SchemaEditable: true}
 		respModifySchemas, err = localMicroServiceDs.ModifySchemas(getContext(), &pb.ModifySchemasRequest{
 			ServiceId: serviceIdPro1,
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchemas.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchemas.Response.GetCode())
 	})
 
 	t.Run("modify a schema in production env while schema editable is set", func(t *testing.T) {
@@ -2796,7 +2618,7 @@ func TestSchema_Create(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceIdPro1 = respCreateService.ServiceId
 
 		log.Info("add schemas, should pass")
@@ -2812,7 +2634,7 @@ func TestSchema_Create(t *testing.T) {
 			Schemas:   schemas,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchemas.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchemas.Response.GetCode())
 
 		respService, err := datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
 			ServiceId: serviceIdPro1,
@@ -2821,7 +2643,7 @@ func TestSchema_Create(t *testing.T) {
 		assert.Equal(t, []string{"first_schemaId_ms"}, respService.Service.Schemas)
 
 		log.Info("schema edit not allowed, modify schema should fail")
-		localMicroServiceDs := &DataSource{SchemaEditable: false}
+		localMicroServiceDs := &etcd.DataSource{SchemaEditable: false}
 		respModifySchema, err := localMicroServiceDs.ModifySchema(getContext(), &pb.ModifySchemaRequest{
 			ServiceId: serviceIdPro1,
 			SchemaId:  schemas[0].SchemaId,
@@ -2832,7 +2654,7 @@ func TestSchema_Create(t *testing.T) {
 		assert.Equal(t, scerr.ErrModifySchemaNotAllow, respModifySchema.Response.GetCode())
 
 		log.Info("schema edit allowed, add a schema with new schemaId, should pass")
-		localMicroServiceDs = &DataSource{SchemaEditable: true}
+		localMicroServiceDs = &etcd.DataSource{SchemaEditable: true}
 		respModifySchema, err = localMicroServiceDs.ModifySchema(getContext(), &pb.ModifySchemaRequest{
 			ServiceId: serviceIdPro1,
 			SchemaId:  schemas[0].SchemaId,
@@ -2840,20 +2662,11 @@ func TestSchema_Create(t *testing.T) {
 			Schema:    schemas[0].SchemaId,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respModifySchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respModifySchema.Response.GetCode())
 	})
 }
 
 func TestSchema_Exist(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId string
 	)
@@ -2871,7 +2684,7 @@ func TestSchema_Exist(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		log.Info("add schemas, should pass")
@@ -2882,7 +2695,7 @@ func TestSchema_Exist(t *testing.T) {
 			Summary:   "summary_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
 			ServiceId: serviceId,
@@ -2890,7 +2703,7 @@ func TestSchema_Exist(t *testing.T) {
 			Schema:    "query schema ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("check exists", func(t *testing.T) {
@@ -2901,7 +2714,7 @@ func TestSchema_Exist(t *testing.T) {
 			SchemaId:  "com.huawei.test.ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.Equal(t, "summary_ms", resp.Summary)
 
 		resp, err = datasource.Instance().ExistSchema(getContext(), &pb.GetExistenceRequest{
@@ -2913,7 +2726,7 @@ func TestSchema_Exist(t *testing.T) {
 			Version:     "()",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().ExistSchema(getContext(), &pb.GetExistenceRequest{
 			Type:      service.ExistTypeSchema,
@@ -2921,22 +2734,13 @@ func TestSchema_Exist(t *testing.T) {
 			SchemaId:  "com.huawei.test.no.summary.ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.Equal(t, "com.huawei.test.no.summary.ms", resp.SchemaId)
 		assert.Equal(t, "", resp.Summary)
 	})
 }
 
 func TestSchema_Get(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId  string
 		serviceId1 string
@@ -2965,7 +2769,7 @@ func TestSchema_Get(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		respCreateSchema, err := datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -2975,7 +2779,7 @@ func TestSchema_Get(t *testing.T) {
 			Summary:   "schema0summary1ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateSchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateSchema.Response.GetCode())
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
@@ -2992,7 +2796,7 @@ func TestSchema_Get(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId1 = respCreateService.ServiceId
 
 		respPutData, err := datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -3001,7 +2805,7 @@ func TestSchema_Get(t *testing.T) {
 			Schema:    schemaContent,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respPutData.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respPutData.Response.GetCode())
 
 		respPutData, err = datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
 			ServiceId: serviceId1,
@@ -3010,14 +2814,14 @@ func TestSchema_Get(t *testing.T) {
 			Summary:   summary,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respPutData.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respPutData.Response.GetCode())
 
 		respGetAllSchema, err := datasource.Instance().GetAllSchemas(getContext(), &pb.GetAllSchemaRequest{
 			ServiceId:  serviceId1,
 			WithSchema: false,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respGetAllSchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respGetAllSchema.Response.GetCode())
 		schemas := respGetAllSchema.Schemas
 		for _, schema := range schemas {
 			if schema.SchemaId == schemaId1 && schema.SchemaId == schemaId2 {
@@ -3035,7 +2839,7 @@ func TestSchema_Get(t *testing.T) {
 			WithSchema: true,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respGetAllSchema.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respGetAllSchema.Response.GetCode())
 		schemas = respGetAllSchema.Schemas
 		for _, schema := range schemas {
 			switch schema.SchemaId {
@@ -3082,7 +2886,7 @@ func TestSchema_Get(t *testing.T) {
 			SchemaId:  "com.huawei.test.ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.Equal(t, "get schema ms", resp.Schema)
 		assert.Equal(t, "schema0summary1ms", resp.SchemaSummary)
 
@@ -3090,15 +2894,6 @@ func TestSchema_Get(t *testing.T) {
 }
 
 func TestSchema_Delete(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId string
 	)
@@ -3114,7 +2909,7 @@ func TestSchema_Delete(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		resp, err := datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
@@ -3124,7 +2919,7 @@ func TestSchema_Delete(t *testing.T) {
 			Summary:   "summary_ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("test delete when request is invalid", func(t *testing.T) {
@@ -3134,7 +2929,7 @@ func TestSchema_Delete(t *testing.T) {
 			SchemaId:  "none_exist_schema",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("service id does not exist")
 		resp, err = datasource.Instance().DeleteSchema(getContext(), &pb.DeleteSchemaRequest{
@@ -3142,7 +2937,7 @@ func TestSchema_Delete(t *testing.T) {
 			SchemaId:  "com.huawei.test.ms",
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("test delete when request is valid", func(t *testing.T) {
@@ -3151,7 +2946,7 @@ func TestSchema_Delete(t *testing.T) {
 			SchemaId:  "com.huawei.test.ms",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		respGet, err := datasource.Instance().GetSchema(getContext(), &pb.GetSchemaRequest{
 			ServiceId: serviceId,
@@ -3171,15 +2966,6 @@ func TestSchema_Delete(t *testing.T) {
 }
 
 func TestRule_Add(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId1 string
 		serviceId2 string
@@ -3196,7 +2982,7 @@ func TestRule_Add(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId1 = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -3209,7 +2995,7 @@ func TestRule_Add(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId2 = respCreateService.ServiceId
 	})
 
@@ -3227,7 +3013,7 @@ func TestRule_Add(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respAddRule)
+		assert.NotEqual(t, proto.ResponseSuccess, respAddRule)
 	})
 
 	t.Run("request is valid", func(t *testing.T) {
@@ -3244,7 +3030,7 @@ func TestRule_Add(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 		ruleId := respAddRule.RuleIds[0]
 		assert.NotEqual(t, "", ruleId)
 
@@ -3261,7 +3047,7 @@ func TestRule_Add(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 		assert.Equal(t, 0, len(respAddRule.RuleIds))
 
 		log.Info("create a new white list when black list already exists")
@@ -3277,7 +3063,7 @@ func TestRule_Add(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 	})
 
 	t.Run("create rule out of gaugue", func(t *testing.T) {
@@ -3297,7 +3083,7 @@ func TestRule_Add(t *testing.T) {
 			Rules:     rules[:size-1],
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		resp, err = datasource.Instance().AddRule(getContext(), &pb.AddServiceRulesRequest{
 			ServiceId: serviceId2,
@@ -3309,15 +3095,6 @@ func TestRule_Add(t *testing.T) {
 }
 
 func TestRule_Get(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId string
 		ruleId    string
@@ -3334,7 +3111,7 @@ func TestRule_Get(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		respAddRule, err := datasource.Instance().AddRule(getContext(), &pb.AddServiceRulesRequest{
@@ -3349,7 +3126,7 @@ func TestRule_Get(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 		ruleId = respAddRule.RuleIds[0]
 		assert.NotEqual(t, "", ruleId)
 	})
@@ -3368,21 +3145,12 @@ func TestRule_Get(t *testing.T) {
 			ServiceId: serviceId,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respGetRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respGetRule.Response.GetCode())
 		assert.Equal(t, ruleId, respGetRule.Rules[0].RuleId)
 	})
 }
 
 func TestRule_Update(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId string
 		ruleId    string
@@ -3399,7 +3167,7 @@ func TestRule_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		respAddRule, err := datasource.Instance().AddRule(getContext(), &pb.AddServiceRulesRequest{
@@ -3414,7 +3182,7 @@ func TestRule_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 		ruleId = respAddRule.RuleIds[0]
 		assert.NotEqual(t, "", ruleId)
 	})
@@ -3433,7 +3201,7 @@ func TestRule_Update(t *testing.T) {
 			Rule:      rule,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("rule not exists")
 		resp, err = datasource.Instance().UpdateRule(getContext(), &pb.UpdateServiceRuleRequest{
@@ -3442,7 +3210,7 @@ func TestRule_Update(t *testing.T) {
 			Rule:      rule,
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("change rule type")
 		resp, err = datasource.Instance().UpdateRule(getContext(), &pb.UpdateServiceRuleRequest{
@@ -3456,7 +3224,7 @@ func TestRule_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.NotEqual(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.NotEqual(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("update when request is valid", func(t *testing.T) {
@@ -3471,20 +3239,11 @@ func TestRule_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
 func TestRule_Delete(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		serviceId string
 		ruleId    string
@@ -3500,7 +3259,7 @@ func TestRule_Delete(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		serviceId = respCreateService.ServiceId
 
 		respAddRule, err := datasource.Instance().AddRule(getContext(), &pb.AddServiceRulesRequest{
@@ -3515,7 +3274,7 @@ func TestRule_Delete(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 		ruleId = respAddRule.RuleIds[0]
 		assert.NotEqual(t, "", ruleId)
 	})
@@ -3544,27 +3303,18 @@ func TestRule_Delete(t *testing.T) {
 			RuleIds:   []string{ruleId},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		respGetRule, err := datasource.Instance().GetRule(getContext(), &pb.GetServiceRulesRequest{
 			ServiceId: serviceId,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.Equal(t, 0, len(respGetRule.Rules))
 	})
 }
 
 func TestRule_Permission(t *testing.T) {
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	var (
 		consumerVersion string
 		consumerTag     string
@@ -3582,7 +3332,7 @@ func TestRule_Permission(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		consumerVersion = respCreateService.ServiceId
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
@@ -3595,7 +3345,7 @@ func TestRule_Permission(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		providerBlack = respCreateService.ServiceId
 
 		respAddRule, err := datasource.Instance().AddRule(getContext(), &pb.AddServiceRulesRequest{
@@ -3614,7 +3364,7 @@ func TestRule_Permission(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
@@ -3626,7 +3376,7 @@ func TestRule_Permission(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		providerWhite = respCreateService.ServiceId
 
 		respAddRule, err = datasource.Instance().AddRule(getContext(), &pb.AddServiceRulesRequest{
@@ -3645,7 +3395,7 @@ func TestRule_Permission(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddRule.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddRule.Response.GetCode())
 
 		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
@@ -3657,7 +3407,7 @@ func TestRule_Permission(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respCreateService.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respCreateService.Response.GetCode())
 		consumerTag = respCreateService.ServiceId
 
 		respAddTag, err := datasource.Instance().AddTags(getContext(), &pb.AddServiceTagsRequest{
@@ -3665,7 +3415,7 @@ func TestRule_Permission(t *testing.T) {
 			Tags:      map[string]string{"a": "b"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddTag.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddTag.Response.GetCode())
 	})
 
 	t.Run("when query instances", func(t *testing.T) {
@@ -3693,7 +3443,7 @@ func TestRule_Permission(t *testing.T) {
 			VersionRule:       "0+",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 0, len(respFind.Instances))
 
 		respFind, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
@@ -3703,7 +3453,7 @@ func TestRule_Permission(t *testing.T) {
 			VersionRule:       "0+",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respFind.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respFind.Response.GetCode())
 		assert.Equal(t, 0, len(respFind.Instances))
 
 		log.Info("consumer not in black list")
@@ -3712,7 +3462,7 @@ func TestRule_Permission(t *testing.T) {
 			ProviderServiceId: providerBlack,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("consumer not in white list")
 		resp, err = datasource.Instance().GetInstances(getContext(), &pb.GetInstancesRequest{
@@ -3728,7 +3478,7 @@ func TestRule_Permission(t *testing.T) {
 			ProviderServiceId: providerWhite,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		log.Info("consumer tag in white list")
 		resp, err = datasource.Instance().GetInstances(getContext(), &pb.GetInstancesRequest{
@@ -3736,7 +3486,7 @@ func TestRule_Permission(t *testing.T) {
 			ProviderServiceId: providerWhite,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 }
 
@@ -3746,16 +3496,6 @@ func TestTags_Add(t *testing.T) {
 		serviceId2 string
 	)
 
-	// init
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	// create service
 	t.Run("create service", func(t *testing.T) {
 		svc1 := &pb.MicroService{
@@ -3812,7 +3552,7 @@ func TestTags_Add(t *testing.T) {
 			Tags:      tags,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("tag's quota exceeded", func(t *testing.T) {
@@ -3828,7 +3568,7 @@ func TestTags_Add(t *testing.T) {
 			Tags:      tags,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		tags["out"] = "range"
 		resp, _ = datasource.Instance().AddTags(getContext(), &pb.AddServiceTagsRequest{
@@ -3842,15 +3582,6 @@ func TestTags_Add(t *testing.T) {
 
 func TestTags_Get(t *testing.T) {
 	var serviceId string
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	t.Run("create service and add tags", func(t *testing.T) {
 		svc := &pb.MicroService{
 			AppId:       "get_tag_group_ms",
@@ -3863,7 +3594,7 @@ func TestTags_Get(t *testing.T) {
 			Service: svc,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		serviceId = resp.ServiceId
 
 		log.Info("add tags should be passed")
@@ -3875,7 +3606,7 @@ func TestTags_Get(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddTags.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddTags.Response.GetCode())
 	})
 
 	t.Run("the request is invalid", func(t *testing.T) {
@@ -3905,22 +3636,13 @@ func TestTags_Get(t *testing.T) {
 			ServiceId: serviceId,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.Equal(t, "test", resp.Tags["a"])
 	})
 }
 
 func TestTag_Update(t *testing.T) {
 	var serviceId string
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	t.Run("add service and add tags", func(t *testing.T) {
 		svc := &pb.MicroService{
 			AppId:       "update_tag_group_ms",
@@ -3933,7 +3655,7 @@ func TestTag_Update(t *testing.T) {
 			Service: svc,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		serviceId = resp.ServiceId
 
 		log.Info("add tags")
@@ -3945,7 +3667,7 @@ func TestTag_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddTags.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddTags.Response.GetCode())
 	})
 
 	t.Run("the request is invalid", func(t *testing.T) {
@@ -3985,7 +3707,7 @@ func TestTag_Update(t *testing.T) {
 			Value:     "update",
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 	})
 
 	t.Run("find instance, contain tag", func(t *testing.T) {
@@ -4000,7 +3722,7 @@ func TestTag_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		consumerId := resp.ServiceId
 
 		log.Info("create provider")
@@ -4014,7 +3736,7 @@ func TestTag_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		providerId := resp.ServiceId
 
 		log.Info("tag the provider")
@@ -4023,7 +3745,7 @@ func TestTag_Update(t *testing.T) {
 			Tags:      map[string]string{"filter_tag": "filter"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, addTagsResp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, addTagsResp.Response.GetCode())
 
 		log.Info("add instance to provider")
 		instanceResp, err := datasource.Instance().RegisterInstance(getContext(), &pb.RegisterInstanceRequest{
@@ -4037,7 +3759,7 @@ func TestTag_Update(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, instanceResp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, instanceResp.Response.GetCode())
 
 		log.Info("find instance")
 		findResp, err := datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
@@ -4048,7 +3770,7 @@ func TestTag_Update(t *testing.T) {
 			Tags:              []string{"not-exist-tag"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, findResp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, findResp.Response.GetCode())
 		assert.Equal(t, 0, len(findResp.Instances))
 
 		findResp, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
@@ -4059,7 +3781,7 @@ func TestTag_Update(t *testing.T) {
 			Tags:              []string{"filter_tag"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, findResp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, findResp.Response.GetCode())
 		assert.Equal(t, instanceResp.InstanceId, findResp.Instances[0].InstanceId)
 
 		// no add rules
@@ -4070,7 +3792,7 @@ func TestTag_Update(t *testing.T) {
 			Tags:      map[string]string{"consumer_tag": "filter"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, addTagsResp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, addTagsResp.Response.GetCode())
 
 		findResp, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
 			ConsumerServiceId: consumerId,
@@ -4080,21 +3802,12 @@ func TestTag_Update(t *testing.T) {
 			Tags:              []string{"filter_tag"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, findResp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, findResp.Response.GetCode())
 	})
 }
 
 func TestTags_Delete(t *testing.T) {
 	var serviceId string
-	datasource.Install("etcd", func(opts datasource.Options) (datasource.DataSource, error) {
-		return NewDataSource(opts), nil
-	})
-	err := datasource.Init(datasource.Options{
-		Endpoint:       "",
-		PluginImplName: datasource.ImplName(archaius.GetString("servicecomb.datasource.name", "etcd")),
-	})
-	assert.NoError(t, err)
-
 	t.Run("create service and add tags", func(t *testing.T) {
 		resp, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
@@ -4106,7 +3819,7 @@ func TestTags_Delete(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		serviceId = resp.ServiceId
 
 		respAddTages, err := datasource.Instance().AddTags(getContext(), &pb.AddServiceTagsRequest{
@@ -4117,7 +3830,7 @@ func TestTags_Delete(t *testing.T) {
 			},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, respAddTages.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, respAddTages.Response.GetCode())
 	})
 
 	t.Run("the request is invalid", func(t *testing.T) {
@@ -4144,13 +3857,13 @@ func TestTags_Delete(t *testing.T) {
 			Keys:      []string{"a", "b"},
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 
 		respGetTags, err := datasource.Instance().GetTags(getContext(), &pb.GetServiceTagsRequest{
 			ServiceId: serviceId,
 		})
 		assert.NoError(t, err)
-		assert.Equal(t, proto.Response_SUCCESS, resp.Response.GetCode())
+		assert.Equal(t, proto.ResponseSuccess, resp.Response.GetCode())
 		assert.Equal(t, "", respGetTags.Tags["a"])
 	})
 }
diff --git a/server/mux/mux.go b/datasource/etcd/mux/mux.go
similarity index 100%
rename from server/mux/mux.go
rename to datasource/etcd/mux/mux.go
diff --git a/server/plugin/discovery/aggregate/adaptor.go b/datasource/etcd/sd/aggregate/adaptor.go
similarity index 75%
rename from server/plugin/discovery/aggregate/adaptor.go
rename to datasource/etcd/sd/aggregate/adaptor.go
index 956a0fa..65e1e5f 100644
--- a/server/plugin/discovery/aggregate/adaptor.go
+++ b/datasource/etcd/sd/aggregate/adaptor.go
@@ -16,25 +16,24 @@
 package aggregate
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd/kv"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/server/core"
-	"github.com/apache/servicecomb-service-center/server/core/backend"
-	mgr "github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 )
 
-// Aggregator implements discovery.Adaptor.
+// Aggregator implements sd.Adaptor.
 // Aggregator is an aggregator of multi Adaptors, and it aggregates all the
 // Adaptors' data as it's result.
 type Aggregator struct {
 	// Indexer searches data from all the adapters
-	discovery.Indexer
-	Type     discovery.Type
-	Adaptors []discovery.Adaptor
+	sd.Indexer
+	Type     sd.Type
+	Adaptors []sd.Adaptor
 }
 
 // Cache gets all the adapters' cache
-func (as *Aggregator) Cache() discovery.CacheReader {
+func (as *Aggregator) Cache() sd.CacheReader {
 	var cache Cache
 	for _, a := range as.Adaptors {
 		cache = append(cache, a.Cache())
@@ -61,10 +60,10 @@ func (as *Aggregator) Ready() <-chan struct{} {
 	return closedCh
 }
 
-func getLogConflictFunc(t discovery.Type) func(origin, conflict *discovery.KeyValue) {
+func getLogConflictFunc(t sd.Type) func(origin, conflict *sd.KeyValue) {
 	switch t {
-	case backend.ServiceIndex:
-		return func(origin, conflict *discovery.KeyValue) {
+	case kv.ServiceIndex:
+		return func(origin, conflict *sd.KeyValue) {
 			if serviceID, conflictID := origin.Value.(string), conflict.Value.(string); conflictID != serviceID {
 				key := core.GetInfoFromSvcIndexKV(conflict.Key)
 				log.Warnf("conflict! can not merge microservice index[%s][%s][%s/%s/%s/%s], found one[%s] in cluster[%s]",
@@ -72,8 +71,8 @@ func getLogConflictFunc(t discovery.Type) func(origin, conflict *discovery.KeyVa
 					serviceID, origin.ClusterName)
 			}
 		}
-	case backend.ServiceAlias:
-		return func(origin, conflict *discovery.KeyValue) {
+	case kv.ServiceAlias:
+		return func(origin, conflict *sd.KeyValue) {
 			if serviceID, conflictID := origin.Value.(string), conflict.Value.(string); conflictID != serviceID {
 				key := core.GetInfoFromSvcAliasKV(conflict.Key)
 				log.Warnf("conflict! can not merge microservice alias[%s][%s][%s/%s/%s/%s], found one[%s] in cluster[%s]",
@@ -85,16 +84,21 @@ func getLogConflictFunc(t discovery.Type) func(origin, conflict *discovery.KeyVa
 	return nil
 }
 
-func NewAggregator(t discovery.Type, cfg *discovery.Config) *Aggregator {
+func NewAggregator(t sd.Type, cfg *sd.Config) *Aggregator {
 	as := &Aggregator{Type: t}
 	for _, name := range repos {
-		repo := mgr.Plugins().Get(mgr.DISCOVERY, mgr.ImplName(name)).New().(discovery.AdaptorRepository)
+		// create and get all plugin instances
+		repo, err := sd.New(sd.Options{PluginImplName: sd.ImplName(name)})
+		if err != nil {
+			log.Errorf(err, "failed to new plugin instance[%s]", name)
+			continue
+		}
 		as.Adaptors = append(as.Adaptors, repo.New(t, cfg))
 	}
 	as.Indexer = NewAggregatorIndexer(as)
 
 	switch t {
-	case backend.ServiceIndex, backend.ServiceAlias:
+	case kv.ServiceIndex, kv.ServiceAlias:
 		NewConflictChecker(as.Cache(), getLogConflictFunc(t))
 	}
 	return as
diff --git a/server/plugin/discovery/aggregate/cache.go b/datasource/etcd/sd/aggregate/cache.go
similarity index 69%
rename from server/plugin/discovery/aggregate/cache.go
rename to datasource/etcd/sd/aggregate/cache.go
index d7a935a..7fbf6e7 100644
--- a/server/plugin/discovery/aggregate/cache.go
+++ b/datasource/etcd/sd/aggregate/cache.go
@@ -16,13 +16,13 @@
 package aggregate
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 )
 
-// Cache implements CacheReader.
+// Cache implements sd.CacheReader.
 // Cache is a multi-CacheReader, it reads cache from all CacheReaders.
-type Cache []discovery.CacheReader
+type Cache []sd.CacheReader
 
 func (c Cache) Name() string {
 	if len(c) == 0 {
@@ -37,7 +37,7 @@ func (c Cache) Size() (s int) {
 	}
 	return s
 }
-func (c Cache) Get(k string) (kv *discovery.KeyValue) {
+func (c Cache) Get(k string) (kv *sd.KeyValue) {
 	for _, cache := range c {
 		if kv = cache.Get(k); kv != nil {
 			return
@@ -45,22 +45,22 @@ func (c Cache) Get(k string) (kv *discovery.KeyValue) {
 	}
 	return
 }
-func (c Cache) GetAll(arr *[]*discovery.KeyValue) (s int) {
+func (c Cache) GetAll(arr *[]*sd.KeyValue) (s int) {
 	exists := make(map[string]struct{})
-	for _, cache := range c {
-		var tmp []*discovery.KeyValue
-		if l := cache.GetAll(&tmp); l == 0 {
+	for _, item := range c {
+		var tmp []*sd.KeyValue
+		if l := item.GetAll(&tmp); l == 0 {
 			continue
 		}
 		s += c.append(tmp, arr, exists)
 	}
 	return
 }
-func (c Cache) GetPrefix(prefix string, arr *[]*discovery.KeyValue) (s int) {
+func (c Cache) GetPrefix(prefix string, arr *[]*sd.KeyValue) (s int) {
 	exists := make(map[string]struct{})
-	for _, cache := range c {
-		var tmp []*discovery.KeyValue
-		if l := cache.GetPrefix(prefix, &tmp); l == 0 {
+	for _, item := range c {
+		var tmp []*sd.KeyValue
+		if l := item.GetPrefix(prefix, &tmp); l == 0 {
 			continue
 		}
 		s += c.append(tmp, arr, exists)
@@ -68,7 +68,7 @@ func (c Cache) GetPrefix(prefix string, arr *[]*discovery.KeyValue) (s int) {
 	return
 }
 
-func (c Cache) append(tmp []*discovery.KeyValue, arr *[]*discovery.KeyValue,
+func (c Cache) append(tmp []*sd.KeyValue, arr *[]*sd.KeyValue,
 	exists map[string]struct{}) (s int) {
 	for _, kv := range tmp {
 		key := util.BytesToStringWithNoCopy(kv.Key)
@@ -84,10 +84,10 @@ func (c Cache) append(tmp []*discovery.KeyValue, arr *[]*discovery.KeyValue,
 	return
 }
 
-func (c Cache) ForEach(iter func(k string, v *discovery.KeyValue) (next bool)) {
+func (c Cache) ForEach(iter func(k string, v *sd.KeyValue) (next bool)) {
 	exists := make(map[string]struct{})
-	for _, cache := range c {
-		cache.ForEach(func(k string, v *discovery.KeyValue) bool {
+	for _, item := range c {
+		item.ForEach(func(k string, v *sd.KeyValue) bool {
 			if _, ok := exists[k]; ok {
 				return true
 			}
diff --git a/server/plugin/discovery/aggregate/common.go b/datasource/etcd/sd/aggregate/common.go
similarity index 100%
rename from server/plugin/discovery/aggregate/common.go
rename to datasource/etcd/sd/aggregate/common.go
diff --git a/server/plugin/discovery/aggregate/conflict_checker.go b/datasource/etcd/sd/aggregate/conflict_checker.go
similarity index 74%
rename from server/plugin/discovery/aggregate/conflict_checker.go
rename to datasource/etcd/sd/aggregate/conflict_checker.go
index 2596d2b..fb6399b 100644
--- a/server/plugin/discovery/aggregate/conflict_checker.go
+++ b/datasource/etcd/sd/aggregate/conflict_checker.go
@@ -17,20 +17,20 @@ package aggregate
 
 import (
 	"context"
+	"github.com/apache/servicecomb-service-center/datasource/etcd"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 	"time"
 )
 
 type ConflictChecker struct {
-	Cache              discovery.CacheReader
-	ConflictHandleFunc func(origin, conflict *discovery.KeyValue)
+	Cache              sd.CacheReader
+	ConflictHandleFunc func(origin, conflict *sd.KeyValue)
 }
 
 func (c *ConflictChecker) Run(ctx context.Context) {
-	d := registry.Configuration().AutoSyncInterval
+	d := etcd.Configuration().AutoSyncInterval
 	if d == 0 || c.Cache == nil {
 		return
 	}
@@ -50,12 +50,12 @@ func (c *ConflictChecker) Check() {
 		return
 	}
 
-	var arr []*discovery.KeyValue
-	for _, cache := range caches {
-		cache.GetAll(&arr)
+	var arr []*sd.KeyValue
+	for _, item := range caches {
+		item.GetAll(&arr)
 	}
 
-	exists := make(map[string]*discovery.KeyValue)
+	exists := make(map[string]*sd.KeyValue)
 	for _, v := range arr {
 		key := util.BytesToStringWithNoCopy(v.Key)
 		if kv, ok := exists[key]; ok {
@@ -66,7 +66,7 @@ func (c *ConflictChecker) Check() {
 	}
 }
 
-func NewConflictChecker(cache discovery.CacheReader, f func(origin, conflict *discovery.KeyValue)) *ConflictChecker {
+func NewConflictChecker(cache sd.CacheReader, f func(origin, conflict *sd.KeyValue)) *ConflictChecker {
 	checker := &ConflictChecker{Cache: cache, ConflictHandleFunc: f}
 	gopool.Go(checker.Run)
 	return checker
diff --git a/server/plugin/discovery/aggregate/indexer.go b/datasource/etcd/sd/aggregate/indexer.go
similarity index 75%
rename from server/plugin/discovery/aggregate/indexer.go
rename to datasource/etcd/sd/aggregate/indexer.go
index 3d7a72f..756e85b 100644
--- a/server/plugin/discovery/aggregate/indexer.go
+++ b/datasource/etcd/sd/aggregate/indexer.go
@@ -16,28 +16,28 @@
 package aggregate
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 
 	"context"
 )
 
-// AdaptorsIndexer implements discovery.Indexer.
+// AdaptorsIndexer implements sd.Indexer.
 // AdaptorsIndexer is an aggregator of multi Indexers, and it aggregates all the
 // Indexers' data as it's result.
 type AdaptorsIndexer struct {
-	Adaptors []discovery.Adaptor
+	Adaptors []sd.Adaptor
 }
 
-// Search implements discovery.Indexer.Search.
+// Search implements sd.Indexer#Search.
 // AdaptorsIndexer ignores the errors during search to ensure availability, so
 // it always searches successfully, no matter how many Adaptors are abnormal.
 // But at the cost of that, AdaptorsIndexer doesn't guarantee the correctness
 // of the search results.
-func (i *AdaptorsIndexer) Search(ctx context.Context, opts ...registry.PluginOpOption) (*discovery.Response, error) {
+func (i *AdaptorsIndexer) Search(ctx context.Context, opts ...client.PluginOpOption) (*sd.Response, error) {
 	var (
-		response discovery.Response
+		response sd.Response
 		exists   = make(map[string]struct{})
 	)
 	for _, a := range i.Adaptors {
@@ -57,7 +57,7 @@ func (i *AdaptorsIndexer) Search(ctx context.Context, opts ...registry.PluginOpO
 	return &response, nil
 }
 
-// Creditable implements discovery.Indexer.Creditable.
+// Creditable implements sd.Indexer#Creditable.
 // AdaptorsIndexer's search result's are not creditable as it ignores the
 // errors. In other words, AdaptorsIndexer makes the best efforts to search
 // data, but it does not ensure the correctness.
@@ -65,25 +65,25 @@ func (i *AdaptorsIndexer) Creditable() bool {
 	return false
 }
 
-func NewAdaptorsIndexer(as []discovery.Adaptor) *AdaptorsIndexer {
+func NewAdaptorsIndexer(as []sd.Adaptor) *AdaptorsIndexer {
 	return &AdaptorsIndexer{Adaptors: as}
 }
 
-// AggregatorIndexer implements discovery.Indexer.
+// AggregatorIndexer implements sd.Indexer.
 // AggregatorIndexer consists of multi Indexers and it decides which Indexer to
 // use based on it's mechanism.
 type AggregatorIndexer struct {
 	// CacheIndexer searches data from all the adaptors's cache.
-	*discovery.CacheIndexer
+	*sd.CacheIndexer
 	// AdaptorsIndexer searches data from all the adaptors.
-	AdaptorsIndexer discovery.Indexer
+	AdaptorsIndexer sd.Indexer
 	// LocalIndexer data from local adaptor.
-	LocalIndexer discovery.Indexer
+	LocalIndexer sd.Indexer
 }
 
-// Search implements discovery.Indexer.Search.
-func (i *AggregatorIndexer) Search(ctx context.Context, opts ...registry.PluginOpOption) (resp *discovery.Response, err error) {
-	op := registry.OpGet(opts...)
+// Search implements sd.Indexer#Search.
+func (i *AggregatorIndexer) Search(ctx context.Context, opts ...client.PluginOpOption) (resp *sd.Response, err error) {
+	op := client.OpGet(opts...)
 
 	if op.NoCache() || !op.Global {
 		return i.search(ctx, opts...)
@@ -101,8 +101,8 @@ func (i *AggregatorIndexer) Search(ctx context.Context, opts ...registry.PluginO
 	return i.search(ctx, opts...)
 }
 
-func (i *AggregatorIndexer) search(ctx context.Context, opts ...registry.PluginOpOption) (*discovery.Response, error) {
-	op := registry.OptionsToOp(opts...)
+func (i *AggregatorIndexer) search(ctx context.Context, opts ...client.PluginOpOption) (*sd.Response, error) {
+	op := client.OptionsToOp(opts...)
 	if !op.Global {
 		return i.LocalIndexer.Search(ctx, opts...)
 	}
@@ -110,7 +110,7 @@ func (i *AggregatorIndexer) search(ctx context.Context, opts ...registry.PluginO
 	return i.AdaptorsIndexer.Search(ctx, opts...)
 }
 
-// Creditable implements discovery.Indexer.Creditable.
+// Creditable implements sd.Indexer#Creditable.
 func (i *AggregatorIndexer) Creditable() bool {
 	return i.AdaptorsIndexer.Creditable() &&
 		i.LocalIndexer.Creditable() &&
@@ -120,7 +120,7 @@ func (i *AggregatorIndexer) Creditable() bool {
 func NewAggregatorIndexer(as *Aggregator) *AggregatorIndexer {
 	indexer := NewAdaptorsIndexer(as.Adaptors)
 	ai := &AggregatorIndexer{
-		CacheIndexer:    discovery.NewCacheIndexer(as.Cache()),
+		CacheIndexer:    sd.NewCacheIndexer(as.Cache()),
 		AdaptorsIndexer: indexer,
 		LocalIndexer:    indexer,
 	}
diff --git a/server/plugin/discovery/aggregate/repo.go b/datasource/etcd/sd/aggregate/repo.go
similarity index 66%
rename from server/plugin/discovery/aggregate/repo.go
rename to datasource/etcd/sd/aggregate/repo.go
index 6b69d6f..1234f38 100644
--- a/server/plugin/discovery/aggregate/repo.go
+++ b/datasource/etcd/sd/aggregate/repo.go
@@ -16,29 +16,27 @@
 package aggregate
 
 import (
-	mgr "github.com/apache/servicecomb-service-center/server/plugin"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
+	"github.com/apache/servicecomb-service-center/server/core"
 )
 
 func init() {
-	mgr.RegisterPlugin(mgr.Plugin{PName: mgr.DISCOVERY, Name: Aggregate, New: NewRepository})
+	sd.Install(Aggregate, NewRepository)
 }
 
 type Repository struct {
 }
 
-func (r *Repository) New(t discovery.Type, cfg *discovery.Config) discovery.Adaptor {
+func (r *Repository) New(t sd.Type, cfg *sd.Config) sd.Adaptor {
 	return NewAggregator(t, cfg)
 }
 
-func NewRepository() mgr.Instance {
+func NewRepository(opts sd.Options) sd.AdaptorRepository {
 	InitConfigs()
 	return &Repository{}
 }
 
 func InitConfigs() {
-	mgr.DISCOVERY.ActiveConfigs().
-		Set("config", registry.Configuration()).
+	core.ServerInfo.Config.Plugins.Object("discovery").
 		Set("aggregateMode", repos)
 }
diff --git a/server/plugin/discovery/cache.go b/datasource/etcd/sd/cache.go
similarity index 99%
rename from server/plugin/discovery/cache.go
rename to datasource/etcd/sd/cache.go
index 1dc6268..f5424b7 100644
--- a/server/plugin/discovery/cache.go
+++ b/datasource/etcd/sd/cache.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 // Cacher manages cache of some data source, e.g. etcd, kubernetes.
 // An user can do nothing but read the managed cache.
diff --git a/server/plugin/discovery/cache_kv.go b/datasource/etcd/sd/cache_kv.go
similarity index 99%
rename from server/plugin/discovery/cache_kv.go
rename to datasource/etcd/sd/cache_kv.go
index d8b1955..72160c8 100644
--- a/server/plugin/discovery/cache_kv.go
+++ b/datasource/etcd/sd/cache_kv.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 import (
 	"github.com/apache/servicecomb-service-center/pkg/util"
diff --git a/server/plugin/discovery/cache_null.go b/datasource/etcd/sd/cache_null.go
similarity index 99%
rename from server/plugin/discovery/cache_null.go
rename to datasource/etcd/sd/cache_null.go
index 1f12041..f2f13bd 100644
--- a/server/plugin/discovery/cache_null.go
+++ b/datasource/etcd/sd/cache_null.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 var (
 	NullCache  = &nullCache{}
diff --git a/server/plugin/discovery/cache_test.go b/datasource/etcd/sd/cache_test.go
similarity index 99%
rename from server/plugin/discovery/cache_test.go
rename to datasource/etcd/sd/cache_test.go
index 2ff7015..2e6c823 100644
--- a/server/plugin/discovery/cache_test.go
+++ b/datasource/etcd/sd/cache_test.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 import (
 	"testing"
diff --git a/server/plugin/discovery/cacher.go b/datasource/etcd/sd/cacher.go
similarity index 61%
rename from server/plugin/discovery/cacher.go
rename to datasource/etcd/sd/cacher.go
index 5590c47..f99c8b6 100644
--- a/server/plugin/discovery/cacher.go
+++ b/datasource/etcd/sd/cacher.go
@@ -1,19 +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.
+/*
+ * 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 discovery
+package sd
 
 import (
 	"github.com/apache/servicecomb-service-center/pkg/log"
@@ -22,7 +24,7 @@ import (
 	"github.com/apache/servicecomb-service-center/pkg/util"
 )
 
-// CommonCacher implements discovery.Cacher.
+// CommonCacher implements sd.Cacher.
 // CommonCacher is universal to manage cache of any registry.
 // Use Cfg to set it's behavior.
 type CommonCacher struct {
diff --git a/server/plugin/discovery/cacher_test.go b/datasource/etcd/sd/cacher_test.go
similarity index 61%
rename from server/plugin/discovery/cacher_test.go
rename to datasource/etcd/sd/cacher_test.go
index 97426d9..bc3a808 100644
--- a/server/plugin/discovery/cacher_test.go
+++ b/datasource/etcd/sd/cacher_test.go
@@ -1,19 +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.
+/*
+ * 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 discovery
+package sd
 
 import (
 	"github.com/apache/servicecomb-service-center/pkg/registry"
diff --git a/server/plugin/discovery/common.go b/datasource/etcd/sd/common.go
similarity index 98%
rename from server/plugin/discovery/common.go
rename to datasource/etcd/sd/common.go
index 39232aa..46d2c6b 100644
--- a/server/plugin/discovery/common.go
+++ b/datasource/etcd/sd/common.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 import (
 	"time"
diff --git a/server/plugin/discovery/config.go b/datasource/etcd/sd/config.go
similarity index 99%
rename from server/plugin/discovery/config.go
rename to datasource/etcd/sd/config.go
index b14cbab..4f394b6 100644
--- a/server/plugin/discovery/config.go
+++ b/datasource/etcd/sd/config.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 import (
 	"fmt"
diff --git a/server/plugin/discovery/config_test.go b/datasource/etcd/sd/config_test.go
similarity index 65%
rename from server/plugin/discovery/config_test.go
rename to datasource/etcd/sd/config_test.go
index d1ecc53..2df9ef9 100644
--- a/server/plugin/discovery/config_test.go
+++ b/datasource/etcd/sd/config_test.go
@@ -1,19 +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.
+/*
+ * 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 discovery
+package sd
 
 import (
 	"github.com/apache/servicecomb-service-center/server/core/proto"
diff --git a/server/plugin/discovery/defer.go b/datasource/etcd/sd/defer.go
similarity index 98%
rename from server/plugin/discovery/defer.go
rename to datasource/etcd/sd/defer.go
index 10e6de2..32812f6 100644
--- a/server/plugin/discovery/defer.go
+++ b/datasource/etcd/sd/defer.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 type DeferHandler interface {
 	OnCondition(CacheReader, []KvEvent) bool
diff --git a/server/plugin/discovery/discovery.go b/datasource/etcd/sd/discovery.go
similarity index 92%
rename from server/plugin/discovery/discovery.go
rename to datasource/etcd/sd/discovery.go
index a41f6af..f55e8c4 100644
--- a/server/plugin/discovery/discovery.go
+++ b/datasource/etcd/sd/discovery.go
@@ -14,14 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package discovery
+
+package sd
 
 // Adaptor is used to do service discovery.
 // To improve the performance, Adaptor may use cache firstly in
-// service discovery.
+// service pkg.
 type Adaptor interface {
 	Runnable
-	// Indexer is used to search data from the registry.
+	// Indexer is used to search data from the cache.
 	Indexer
 	// Cacher is used to manage the registry's cache.
 	Cacher
diff --git a/server/plugin/discovery/etcd/adaptor.go b/datasource/etcd/sd/etcd/adaptor.go
similarity index 71%
rename from server/plugin/discovery/etcd/adaptor.go
rename to datasource/etcd/sd/etcd/adaptor.go
index fcc5302..acf74c0 100644
--- a/server/plugin/discovery/etcd/adaptor.go
+++ b/datasource/etcd/sd/etcd/adaptor.go
@@ -14,52 +14,53 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package etcd
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/server/core"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 )
 
-// Adaptor implements discovery.Adaptor.
-// Adaptor does service discovery with etcd as it's registry.
+// Adaptor implements sd.Adaptor.
+// Adaptor does service pkg with etcd as it's cache.
 type Adaptor struct {
-	discovery.Cacher
-	discovery.Indexer
+	sd.Cacher
+	sd.Indexer
 }
 
 func (se *Adaptor) Run() {
-	if r, ok := se.Cacher.(discovery.Runnable); ok {
+	if r, ok := se.Cacher.(sd.Runnable); ok {
 		r.Run()
 	}
 }
 
 func (se *Adaptor) Stop() {
-	if r, ok := se.Cacher.(discovery.Runnable); ok {
+	if r, ok := se.Cacher.(sd.Runnable); ok {
 		r.Stop()
 	}
 }
 
 func (se *Adaptor) Ready() <-chan struct{} {
-	if r, ok := se.Cacher.(discovery.Runnable); ok {
+	if r, ok := se.Cacher.(sd.Runnable); ok {
 		return r.Ready()
 	}
 	return closedCh
 }
 
-func NewEtcdAdaptor(name string, cfg *discovery.Config) *Adaptor {
+func NewEtcdAdaptor(name string, cfg *sd.Config) *Adaptor {
 	var adaptor Adaptor
 	switch {
 	case core.ServerInfo.Config.EnableCache && cfg.InitSize > 0:
-		cache := discovery.NewKvCache(name, cfg)
-		adaptor.Cacher = NewKvCacher(cfg, cache)
-		adaptor.Indexer = NewCacheIndexer(cfg, cache)
+		kvCache := sd.NewKvCache(name, cfg)
+		adaptor.Cacher = NewKvCacher(cfg, kvCache)
+		adaptor.Indexer = NewCacheIndexer(cfg, kvCache)
 	default:
 		log.Infof(
 			"core will not cache '%s' and ignore all events of it, cache enabled: %v, init size: %d",
 			name, core.ServerInfo.Config.EnableCache, cfg.InitSize)
-		adaptor.Cacher = discovery.NullCacher
+		adaptor.Cacher = sd.NullCacher
 		adaptor.Indexer = NewEtcdIndexer(cfg.Key, cfg.Parser)
 	}
 	return &adaptor
diff --git a/server/plugin/discovery/etcd/adaptor_test.go b/datasource/etcd/sd/etcd/adaptor_test.go
similarity index 82%
rename from server/plugin/discovery/etcd/adaptor_test.go
rename to datasource/etcd/sd/etcd/adaptor_test.go
index da04c07..7005401 100644
--- a/server/plugin/discovery/etcd/adaptor_test.go
+++ b/datasource/etcd/sd/etcd/adaptor_test.go
@@ -14,17 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package etcd
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/server/core"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 	"testing"
 )
 
 func TestNewKvEntity(t *testing.T) {
 	core.ServerInfo.Config.EnableCache = false
-	i := NewEtcdAdaptor("a", discovery.Configure().WithInitSize(1))
+	i := NewEtcdAdaptor("a", sd.Configure().WithInitSize(1))
 	if _, ok := i.Indexer.(*Indexer); !ok {
 		t.Fatalf("TestNewIndexer failed")
 	}
@@ -34,12 +35,12 @@ func TestNewKvEntity(t *testing.T) {
 	<-i.Ready()
 	i.Stop()
 
-	i = NewEtcdAdaptor("a", discovery.Configure().WithInitSize(0))
+	i = NewEtcdAdaptor("a", sd.Configure().WithInitSize(0))
 	if _, ok := i.Indexer.(*Indexer); !ok {
 		t.Fatalf("TestNewIndexer failed")
 	}
 
-	i = NewEtcdAdaptor("a", discovery.Configure())
+	i = NewEtcdAdaptor("a", sd.Configure())
 	if _, ok := i.Indexer.(*CacheIndexer); !ok {
 		t.Fatalf("TestNewIndexer failed")
 	}
@@ -49,8 +50,8 @@ func TestNewKvEntity(t *testing.T) {
 }
 
 func TestNewRepository(t *testing.T) {
-	repo := NewRepository()
-	i := repo.(*Repository).New(0, discovery.Configure())
+	repo := NewRepository(sd.Options{})
+	i := repo.(*Repository).New(0, sd.Configure())
 	if _, ok := i.(*Adaptor); !ok {
 		t.Fatalf("TestNewIndexer failed")
 	}
diff --git a/server/plugin/discovery/etcd/cacher_kv.go b/datasource/etcd/sd/etcd/cacher_kv.go
similarity index 82%
rename from server/plugin/discovery/etcd/cacher_kv.go
rename to datasource/etcd/sd/etcd/cacher_kv.go
index eaa302b..c052ff7 100644
--- a/server/plugin/discovery/etcd/cacher_kv.go
+++ b/datasource/etcd/sd/etcd/cacher_kv.go
@@ -14,34 +14,34 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package etcd
 
 import (
 	"context"
 	"errors"
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/backoff"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	rmodel "github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/core"
-	"github.com/apache/servicecomb-service-center/server/core/backend"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 	"github.com/coreos/etcd/mvcc/mvccpb"
 	"sync"
 	"time"
 )
 
-// KvCacher implements discovery.Cacher.
+// KvCacher implements sd.Cacher.
 // KvCacher manages etcd cache.
 // To update cache, KvCacher watch etcd event and pull data periodly from etcd.
 // When the cache data changes, KvCacher creates events and notifies it's
 // subscribers.
 // Use Cfg to set it's behaviors.
 type KvCacher struct {
-	Cfg *discovery.Config
+	Cfg *sd.Config
 
 	reListCount int
 
@@ -49,11 +49,11 @@ type KvCacher struct {
 	lw        ListWatch
 	mux       sync.Mutex
 	once      sync.Once
-	cache     discovery.Cache
+	cache     sd.Cache
 	goroutine *gopool.Pool
 }
 
-func (c *KvCacher) Config() *discovery.Config {
+func (c *KvCacher) Config() *sd.Config {
 	return c.Cfg
 }
 
@@ -161,15 +161,15 @@ func (c *KvCacher) handleWatcher(watcher Watcher) error {
 
 		start := time.Now()
 		rev := resp.Revision
-		evts := make([]discovery.KvEvent, 0, len(resp.Kvs))
+		evts := make([]sd.KvEvent, 0, len(resp.Kvs))
 		for _, kv := range resp.Kvs {
-			evt := discovery.NewKvEvent(rmodel.EVT_CREATE, nil, kv.ModRevision)
+			evt := sd.NewKvEvent(rmodel.EVT_CREATE, nil, kv.ModRevision)
 			switch {
-			case resp.Action == registry.Put && kv.Version == 1:
+			case resp.Action == client.ActionPut && kv.Version == 1:
 				evt.Type, evt.KV = rmodel.EVT_CREATE, c.doParse(kv)
-			case resp.Action == registry.Put:
+			case resp.Action == client.ActionPut:
 				evt.Type, evt.KV = rmodel.EVT_UPDATE, c.doParse(kv)
-			case resp.Action == registry.Delete:
+			case resp.Action == client.ActionDelete:
 				evt.Type = rmodel.EVT_DELETE
 				if kv.Value == nil {
 					// it will happen in embed mode, and then need to get the cache value not unmarshal
@@ -194,7 +194,7 @@ func (c *KvCacher) handleWatcher(watcher Watcher) error {
 	return nil
 }
 
-func (c *KvCacher) needDeferHandle(evts []discovery.KvEvent) bool {
+func (c *KvCacher) needDeferHandle(evts []sd.KvEvent) bool {
 	if c.Cfg.DeferHandler == nil || !c.IsReady() {
 		return false
 	}
@@ -228,7 +228,7 @@ func (c *KvCacher) refresh(ctx context.Context) {
 }
 
 // keep the evts valid when call sync
-func (c *KvCacher) sync(evts []discovery.KvEvent) {
+func (c *KvCacher) sync(evts []sd.KvEvent) {
 	if len(evts) == 0 {
 		return
 	}
@@ -240,20 +240,20 @@ func (c *KvCacher) sync(evts []discovery.KvEvent) {
 	c.onEvents(evts)
 }
 
-func (c *KvCacher) filter(rev int64, items []*mvccpb.KeyValue) []discovery.KvEvent {
+func (c *KvCacher) filter(rev int64, items []*mvccpb.KeyValue) []sd.KvEvent {
 	nc := len(items)
 	newStore := make(map[string]*mvccpb.KeyValue, nc)
 	for _, kv := range items {
 		newStore[util.BytesToStringWithNoCopy(kv.Key)] = kv
 	}
 	filterStopCh := make(chan struct{})
-	eventsCh := make(chan [eventBlockSize]discovery.KvEvent, 2)
+	eventsCh := make(chan [eventBlockSize]sd.KvEvent, 2)
 
 	go c.filterDelete(newStore, rev, eventsCh, filterStopCh)
 
 	go c.filterCreateOrUpdate(newStore, rev, eventsCh, filterStopCh)
 
-	evts := make([]discovery.KvEvent, 0, nc)
+	evts := make([]sd.KvEvent, 0, nc)
 	for block := range eventsCh {
 		for _, e := range block {
 			if e.KV == nil {
@@ -266,11 +266,11 @@ func (c *KvCacher) filter(rev int64, items []*mvccpb.KeyValue) []discovery.KvEve
 }
 
 func (c *KvCacher) filterDelete(newStore map[string]*mvccpb.KeyValue,
-	rev int64, eventsCh chan [eventBlockSize]discovery.KvEvent, filterStopCh chan struct{}) {
-	var block [eventBlockSize]discovery.KvEvent
+	rev int64, eventsCh chan [eventBlockSize]sd.KvEvent, filterStopCh chan struct{}) {
+	var block [eventBlockSize]sd.KvEvent
 	i := 0
 
-	c.cache.ForEach(func(k string, v *discovery.KeyValue) (next bool) {
+	c.cache.ForEach(func(k string, v *sd.KeyValue) (next bool) {
 		next = true
 
 		_, ok := newStore[k]
@@ -280,11 +280,11 @@ func (c *KvCacher) filterDelete(newStore map[string]*mvccpb.KeyValue,
 
 		if i >= eventBlockSize {
 			eventsCh <- block
-			block = [eventBlockSize]discovery.KvEvent{}
+			block = [eventBlockSize]sd.KvEvent{}
 			i = 0
 		}
 
-		block[i] = discovery.NewKvEvent(rmodel.EVT_DELETE, v, rev)
+		block[i] = sd.NewKvEvent(rmodel.EVT_DELETE, v, rev)
 		i++
 		return
 	})
@@ -297,8 +297,8 @@ func (c *KvCacher) filterDelete(newStore map[string]*mvccpb.KeyValue,
 }
 
 func (c *KvCacher) filterCreateOrUpdate(newStore map[string]*mvccpb.KeyValue,
-	rev int64, eventsCh chan [eventBlockSize]discovery.KvEvent, filterStopCh chan struct{}) {
-	var block [eventBlockSize]discovery.KvEvent
+	rev int64, eventsCh chan [eventBlockSize]sd.KvEvent, filterStopCh chan struct{}) {
+	var block [eventBlockSize]sd.KvEvent
 	i := 0
 
 	for k, v := range newStore {
@@ -306,12 +306,12 @@ func (c *KvCacher) filterCreateOrUpdate(newStore map[string]*mvccpb.KeyValue,
 		if ov == nil {
 			if i >= eventBlockSize {
 				eventsCh <- block
-				block = [eventBlockSize]discovery.KvEvent{}
+				block = [eventBlockSize]sd.KvEvent{}
 				i = 0
 			}
 
 			if kv := c.doParse(v); kv != nil {
-				block[i] = discovery.NewKvEvent(rmodel.EVT_CREATE, kv, rev)
+				block[i] = sd.NewKvEvent(rmodel.EVT_CREATE, kv, rev)
 				i++
 			}
 			continue
@@ -323,12 +323,12 @@ func (c *KvCacher) filterCreateOrUpdate(newStore map[string]*mvccpb.KeyValue,
 
 		if i >= eventBlockSize {
 			eventsCh <- block
-			block = [eventBlockSize]discovery.KvEvent{}
+			block = [eventBlockSize]sd.KvEvent{}
 			i = 0
 		}
 
 		if kv := c.doParse(v); kv != nil {
-			block[i] = discovery.NewKvEvent(rmodel.EVT_UPDATE, kv, rev)
+			block[i] = sd.NewKvEvent(rmodel.EVT_UPDATE, kv, rev)
 			i++
 		}
 	}
@@ -359,7 +359,7 @@ func (c *KvCacher) deferHandle(ctx context.Context) {
 func (c *KvCacher) handleDeferEvents(ctx context.Context) {
 	defer log.Recover()
 	var (
-		evts = make([]discovery.KvEvent, eventBlockSize)
+		evts = make([]sd.KvEvent, eventBlockSize)
 		i    int
 	)
 	interval := 300 * time.Millisecond
@@ -376,7 +376,7 @@ func (c *KvCacher) handleDeferEvents(ctx context.Context) {
 
 			if i >= eventBlockSize {
 				c.onEvents(evts[:i])
-				evts = make([]discovery.KvEvent, eventBlockSize)
+				evts = make([]sd.KvEvent, eventBlockSize)
 				i = 0
 			}
 
@@ -392,18 +392,18 @@ func (c *KvCacher) handleDeferEvents(ctx context.Context) {
 			}
 
 			c.onEvents(evts[:i])
-			evts = make([]discovery.KvEvent, eventBlockSize)
+			evts = make([]sd.KvEvent, eventBlockSize)
 			i = 0
 		}
 	}
 }
 
-func (c *KvCacher) onEvents(evts []discovery.KvEvent) {
+func (c *KvCacher) onEvents(evts []sd.KvEvent) {
 	c.buildCache(evts)
 	c.notify(evts)
 }
 
-func (c *KvCacher) buildCache(evts []discovery.KvEvent) {
+func (c *KvCacher) buildCache(evts []sd.KvEvent) {
 	init := !c.IsReady()
 	for i, evt := range evts {
 		key := util.BytesToStringWithNoCopy(evt.KV.Key)
@@ -438,10 +438,10 @@ func (c *KvCacher) buildCache(evts []discovery.KvEvent) {
 			evts[i] = evt
 		}
 	}
-	discovery.ReportProcessEventCompleted(c.Cfg.Key, evts)
+	sd.ReportProcessEventCompleted(c.Cfg.Key, evts)
 }
 
-func (c *KvCacher) notify(evts []discovery.KvEvent) {
+func (c *KvCacher) notify(evts []sd.KvEvent) {
 	if c.Cfg.OnEvent == nil {
 		return
 	}
@@ -452,8 +452,8 @@ func (c *KvCacher) notify(evts []discovery.KvEvent) {
 	}
 }
 
-func (c *KvCacher) doParse(src *mvccpb.KeyValue) (kv *discovery.KeyValue) {
-	kv = discovery.NewKeyValue()
+func (c *KvCacher) doParse(src *mvccpb.KeyValue) (kv *sd.KeyValue) {
+	kv = sd.NewKeyValue()
 	if err := FromEtcdKeyValue(kv, src, c.Cfg.Parser); err != nil {
 		log.Errorf(err, "parse %s value failed", util.BytesToStringWithNoCopy(src.Key))
 		return nil
@@ -461,7 +461,7 @@ func (c *KvCacher) doParse(src *mvccpb.KeyValue) (kv *discovery.KeyValue) {
 	return
 }
 
-func (c *KvCacher) Cache() discovery.CacheReader {
+func (c *KvCacher) Cache() sd.CacheReader {
 	return c.cache
 }
 
@@ -509,13 +509,13 @@ func (c *KvCacher) reportMetrics(ctx context.Context) {
 	}
 }
 
-func NewKvCacher(cfg *discovery.Config, cache discovery.Cache) *KvCacher {
+func NewKvCacher(cfg *sd.Config, cache sd.Cache) *KvCacher {
 	return &KvCacher{
 		Cfg:   cfg,
 		cache: cache,
 		ready: make(chan struct{}),
 		lw: &innerListWatch{
-			Client: backend.Registry(),
+			Client: client.Instance(),
 			Prefix: cfg.Key,
 		},
 		goroutine: gopool.New(context.Background()),
diff --git a/server/plugin/discovery/etcd/cacher_kv_test.go b/datasource/etcd/sd/etcd/cacher_kv_test.go
similarity index 88%
rename from server/plugin/discovery/etcd/cacher_kv_test.go
rename to datasource/etcd/sd/etcd/cacher_kv_test.go
index 4819a30..100c84d 100644
--- a/server/plugin/discovery/etcd/cacher_kv_test.go
+++ b/datasource/etcd/sd/etcd/cacher_kv_test.go
@@ -14,18 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package etcd
 
 import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	pb "github.com/apache/servicecomb-service-center/pkg/registry"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/core/proto"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 	"github.com/coreos/etcd/mvcc/mvccpb"
 	"math/rand"
 	"strconv"
@@ -34,19 +35,19 @@ import (
 
 type mockCache struct {
 	Key string
-	KV  *discovery.KeyValue
+	KV  *sd.KeyValue
 }
 
-func (n *mockCache) Name() string                          { return "NULL" }
-func (n *mockCache) Size() int                             { return 0 }
-func (n *mockCache) GetAll(arr *[]*discovery.KeyValue) int { return 0 }
-func (n *mockCache) Get(k string) *discovery.KeyValue {
+func (n *mockCache) Name() string                   { return "NULL" }
+func (n *mockCache) Size() int                      { return 0 }
+func (n *mockCache) GetAll(arr *[]*sd.KeyValue) int { return 0 }
+func (n *mockCache) Get(k string) *sd.KeyValue {
 	if k == n.Key {
 		return n.KV
 	}
 	return nil
 }
-func (n *mockCache) GetPrefix(prefix string, arr *[]*discovery.KeyValue) int {
+func (n *mockCache) GetPrefix(prefix string, arr *[]*sd.KeyValue) int {
 	if prefix == n.Key {
 		if arr != nil {
 			*arr = append(*arr, n.KV)
@@ -55,10 +56,10 @@ func (n *mockCache) GetPrefix(prefix string, arr *[]*discovery.KeyValue) int {
 	}
 	return 0
 }
-func (n *mockCache) ForEach(iter func(k string, v *discovery.KeyValue) (next bool)) {
+func (n *mockCache) ForEach(iter func(k string, v *sd.KeyValue) (next bool)) {
 	iter(n.Key, n.KV)
 }
-func (n *mockCache) Put(k string, v *discovery.KeyValue) {
+func (n *mockCache) Put(k string, v *sd.KeyValue) {
 	n.Key = k
 	n.KV = v
 }
@@ -75,12 +76,12 @@ func (n *mockCache) Clear()      {}
 func TestNewKvCacher(t *testing.T) {
 	w := &mockWatcher{}
 	lw := &mockListWatch{
-		Bus: make(chan *registry.PluginResponse, 100),
+		Bus: make(chan *client.PluginResponse, 100),
 	}
 	w.lw = lw
 
 	cr := &KvCacher{
-		Cfg:       discovery.Configure(),
+		Cfg:       sd.Configure(),
 		ready:     make(chan struct{}),
 		lw:        lw,
 		goroutine: gopool.New(context.Background()),
@@ -97,10 +98,10 @@ func TestNewKvCacher(t *testing.T) {
 	}
 
 	// prepare data
-	var evt discovery.KvEvent
+	var evt sd.KvEvent
 	cr = &KvCacher{
-		Cfg: discovery.Configure().
-			WithEventFunc(func(e discovery.KvEvent) {
+		Cfg: sd.Configure().
+			WithEventFunc(func(e sd.KvEvent) {
 				evt = e
 			}),
 		ready:     make(chan struct{}),
@@ -111,8 +112,8 @@ func TestNewKvCacher(t *testing.T) {
 
 	lw.Watcher = w
 	data := &mvccpb.KeyValue{Key: []byte("ka"), Value: []byte("va"), Version: 1, ModRevision: 2}
-	test := &registry.PluginResponse{
-		Action:   registry.Put,
+	test := &client.PluginResponse{
+		Action:   client.ActionPut,
 		Revision: 3,
 		Kvs:      []*mvccpb.KeyValue{data}}
 
@@ -170,7 +171,7 @@ func TestNewKvCacher(t *testing.T) {
 		t.Fatalf("TestNewKvCacher failed")
 	}
 
-	lw.ListResponse = &registry.PluginResponse{Revision: 5}
+	lw.ListResponse = &client.PluginResponse{Revision: 5}
 	for i := 0; i < DefaultForceListInterval; i++ {
 		lw.Bus <- nil
 	}
@@ -223,7 +224,7 @@ func TestNewKvCacher(t *testing.T) {
 	}
 
 	test.Revision = 8
-	test.Action = registry.Delete
+	test.Action = client.ActionDelete
 	data.Version = 0
 	data.ModRevision = 6
 	lw.Bus <- test
@@ -261,7 +262,7 @@ func TestNewKvCacher(t *testing.T) {
 
 	// case: caught delete event but value is nil
 	test.Revision = 10
-	test.Action = registry.Delete
+	test.Action = client.ActionDelete
 	data.Version = 0
 	data.ModRevision = 1
 	data.Value = nil
@@ -317,7 +318,7 @@ func TestNewKvCacher(t *testing.T) {
 	}
 
 	// case: list result is too large
-	var evts = make(map[string]discovery.KvEvent)
+	var evts = make(map[string]sd.KvEvent)
 	lw.Rev = 0
 	test.Revision = 3
 	test.Kvs = nil
@@ -335,7 +336,7 @@ func TestNewKvCacher(t *testing.T) {
 	lw.Bus <- nil
 	evt.KV = nil
 	old = *cr.Cfg
-	cr.Cfg.WithEventFunc(func(evt discovery.KvEvent) {
+	cr.Cfg.WithEventFunc(func(evt sd.KvEvent) {
 		evts[string(evt.KV.Key)] = evt
 	})
 	cr.refresh(ctx)
@@ -362,7 +363,7 @@ func TestNewKvCacher(t *testing.T) {
 	lw.ListResponse = nil // the next list
 	lw.Bus <- test
 	old = *cr.Cfg
-	cr.Cfg.WithEventFunc(func(evt discovery.KvEvent) {
+	cr.Cfg.WithEventFunc(func(evt sd.KvEvent) {
 		t.Fatalf("TestNewKvCacher failed, %v", evt)
 	})
 	cr.refresh(ctx)
@@ -379,10 +380,10 @@ func BenchmarkFilter(b *testing.B) {
 	}
 	v, _ := json.Marshal(inst)
 
-	cfg := discovery.Configure().WithParser(proto.InstanceParser)
+	cfg := sd.Configure().WithParser(proto.InstanceParser)
 
 	n := 300 * 1000 // 30w
-	cache := discovery.NewKvCache("test", cfg)
+	cache := sd.NewKvCache("test", cfg)
 	items := make([]*mvccpb.KeyValue, 0, n)
 	for ; n > 0; n-- {
 		k := fmt.Sprintf("/%d", n)
@@ -395,7 +396,7 @@ func BenchmarkFilter(b *testing.B) {
 			})
 		} else if n > 100*1000 && n <= 20*1000 {
 			// update
-			cache.Put(k, &discovery.KeyValue{
+			cache.Put(k, &sd.KeyValue{
 				Key:         util.StringToBytesWithNoCopy(k),
 				Value:       inst,
 				ModRevision: 1,
@@ -407,7 +408,7 @@ func BenchmarkFilter(b *testing.B) {
 			})
 		} else {
 			// delete
-			cache.Put(k, &discovery.KeyValue{
+			cache.Put(k, &sd.KeyValue{
 				Key:         util.StringToBytesWithNoCopy(k),
 				Value:       inst,
 				ModRevision: 1,
diff --git a/server/plugin/discovery/etcd/common.go b/datasource/etcd/sd/etcd/common.go
similarity index 83%
rename from server/plugin/discovery/etcd/common.go
rename to datasource/etcd/sd/etcd/common.go
index b0c1a04..06367c3 100644
--- a/server/plugin/discovery/etcd/common.go
+++ b/datasource/etcd/sd/etcd/common.go
@@ -16,8 +16,9 @@
 package etcd
 
 import (
+	"github.com/apache/servicecomb-service-center/datasource/etcd"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/server/core/proto"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
 	"github.com/coreos/etcd/mvcc/mvccpb"
 	"time"
 )
@@ -38,7 +39,8 @@ func init() {
 	close(closedCh)
 }
 
-func FromEtcdKeyValue(dist *discovery.KeyValue, src *mvccpb.KeyValue, parser proto.Parser) (err error) {
+func FromEtcdKeyValue(dist *sd.KeyValue, src *mvccpb.KeyValue, parser proto.Parser) (err error) {
+	dist.ClusterName = etcd.Configuration().ClusterName
 	dist.Key = src.Key
 	dist.Version = src.Version
 	dist.CreateRevision = src.CreateRevision
diff --git a/server/plugin/discovery/etcd/indexer_cache.go b/datasource/etcd/sd/etcd/indexer_cache.go
similarity index 74%
rename from server/plugin/discovery/etcd/indexer_cache.go
rename to datasource/etcd/sd/etcd/indexer_cache.go
index 4afa847..8594084 100644
--- a/server/plugin/discovery/etcd/indexer_cache.go
+++ b/datasource/etcd/sd/etcd/indexer_cache.go
@@ -14,28 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package etcd
 
 import (
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 
 	"context"
 )
 
-// CacheIndexer implements discovery.Indexer.
+// CacheIndexer implements sd.Indexer.
 // CacheIndexer searches data from etcd cache(firstly) and
 // etcd server(secondly).
 type CacheIndexer struct {
 	*Indexer
-	*discovery.CacheIndexer
+	*sd.CacheIndexer
 }
 
-func (i *CacheIndexer) Search(ctx context.Context, opts ...registry.PluginOpOption) (*discovery.Response, error) {
-	op := registry.OpGet(opts...)
+func (i *CacheIndexer) Search(ctx context.Context, opts ...client.PluginOpOption) (*sd.Response, error) {
+	op := client.OpGet(opts...)
 	key := util.BytesToStringWithNoCopy(op.Key)
 
 	if op.NoCache() {
@@ -57,14 +58,14 @@ func (i *CacheIndexer) Search(ctx context.Context, opts ...registry.PluginOpOpti
 	return i.Indexer.Search(ctx, opts...)
 }
 
-// Creditable implements discovery.Indexer.Creditable.
+// Creditable implements sd.Indexer#Creditable.
 func (i *CacheIndexer) Creditable() bool {
 	return i.Indexer.Creditable()
 }
 
-func NewCacheIndexer(cfg *discovery.Config, cache discovery.Cache) *CacheIndexer {
+func NewCacheIndexer(cfg *sd.Config, c sd.Cache) *CacheIndexer {
 	return &CacheIndexer{
 		Indexer:      NewEtcdIndexer(cfg.Key, cfg.Parser),
-		CacheIndexer: discovery.NewCacheIndexer(cache),
+		CacheIndexer: sd.NewCacheIndexer(c),
 	}
 }
diff --git a/server/plugin/discovery/etcd/indexer_etcd.go b/datasource/etcd/sd/etcd/indexer_etcd.go
similarity index 75%
rename from server/plugin/discovery/etcd/indexer_etcd.go
rename to datasource/etcd/sd/etcd/indexer_etcd.go
index 3f5c8ff..3b1b832 100644
--- a/server/plugin/discovery/etcd/indexer_etcd.go
+++ b/datasource/etcd/sd/etcd/indexer_etcd.go
@@ -14,26 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package etcd
 
 import (
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
 	"github.com/apache/servicecomb-service-center/server/core/proto"
 	"strings"
 
+	"github.com/apache/servicecomb-service-center/datasource/etcd/client"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/core/backend"
-	"github.com/apache/servicecomb-service-center/server/plugin/discovery"
-	"github.com/apache/servicecomb-service-center/server/plugin/registry"
 
 	"context"
 )
 
-// Indexer implements discovery.Indexer.
+// Indexer implements sd.Indexer.
 // Indexer searches data from etcd server.
 type Indexer struct {
-	Client registry.Registry
+	Client client.Registry
 	Parser proto.Parser
 	Root   string
 }
@@ -45,8 +45,8 @@ func (i *Indexer) CheckPrefix(key string) error {
 	return nil
 }
 
-func (i *Indexer) Search(ctx context.Context, opts ...registry.PluginOpOption) (r *discovery.Response, err error) {
-	op := registry.OpGet(opts...)
+func (i *Indexer) Search(ctx context.Context, opts ...client.PluginOpOption) (r *sd.Response, err error) {
+	op := client.OpGet(opts...)
 	key := util.BytesToStringWithNoCopy(op.Key)
 
 	log.Debugf("search '%s' match special options, request etcd server, opts: %s", key, op)
@@ -60,7 +60,7 @@ func (i *Indexer) Search(ctx context.Context, opts ...registry.PluginOpOption) (
 		return nil, err
 	}
 
-	r = new(discovery.Response)
+	r = new(sd.Response)
 	r.Count = resp.Count
 	if len(resp.Kvs) == 0 || op.CountOnly {
 		return
@@ -71,9 +71,9 @@ func (i *Indexer) Search(ctx context.Context, opts ...registry.PluginOpOption) (
 		p = nil
 	}
 
-	kvs := make([]*discovery.KeyValue, 0, len(resp.Kvs))
+	kvs := make([]*sd.KeyValue, 0, len(resp.Kvs))
 	for _, src := range resp.Kvs {
-		kv := discovery.NewKeyValue()
+		kv := sd.NewKeyValue()
 		if err = FromEtcdKeyValue(kv, src, p); err != nil {
 			continue
 		}
@@ -83,11 +83,11 @@ func (i *Indexer) Search(ctx context.Context, opts ...registry.PluginOpOption) (
 	return
 }
 
-// Creditable implements discovery.Indexer.Creditable.
+// Creditable implements sd.Indexer#Creditable.
 func (i *Indexer) Creditable() bool {
 	return true
 }
 
 func NewEtcdIndexer(root string, p proto.Parser) (indexer *Indexer) {
-	return &Indexer{Client: backend.Registry(), Parser: p, Root: root}
+	return &Indexer{Client: client.Instance(), Parser: p, Root: root}
 }
... 19972 lines suppressed ...