You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by la...@apache.org on 2021/08/01 04:27:41 UTC

[dubbo-go] branch Fix/config-enhancement updated: Config refactor (#1358)

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

laurence pushed a commit to branch Fix/config-enhancement
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/Fix/config-enhancement by this push:
     new 1ecc7eb  Config refactor (#1358)
1ecc7eb is described below

commit 1ecc7eb34a933879e97ede50b73282dc553e2717
Author: Laurence <45...@users.noreply.github.com>
AuthorDate: Sun Aug 1 12:27:34 2021 +0800

    Config refactor (#1358)
    
    * config file enhance
    
    * set Koanf
    
    * add:registry config
    
    * add:config center config
    
    * up:default config name
    
    * up:调整结构
    
    * up:set config
    
    * add validate
    
    * add check genre
    
    * 修改配置目录
    
    * add registry config
    
    * add protocol
    
    * add provider config
    
    * add comments
    
    * up:service config
    
    * 修改解析tag
    
    * registries:
    
    * 配置中心配置
    
    * 添加registry
    
    * fix: make new config struct runnable
    
    Co-authored-by: zhaoyunxing92 <23...@qq.com>
---
 cluster/router/chain/chain.go                      |    2 +-
 .../judger/attachment_match_judger_test.go         |    2 +-
 .../router/v3router/judger/bool_match_judger.go    |    4 +-
 .../v3router/judger/bool_match_judger_test.go      |    5 +-
 .../v3router/judger/double_match_judger_test.go    |    5 +-
 .../judger/double_range_match_judger_test.go       |    5 +-
 .../judger/list_double_match_judger_test.go        |    5 +-
 .../judger/list_string_match_judger_test.go        |    5 +-
 .../v3router/judger/method_match_judger_test.go    |    2 +-
 .../router/v3router/judger/string_match_judger.go  |    5 +-
 .../v3router/judger/string_match_judger_test.go    |    5 +-
 .../v3router/k8s_api/listener_handler_impl.go      |    2 +-
 cluster/router/v3router/router_chain.go            |    2 +-
 cluster/router/v3router/router_chain_test.go       |    2 +-
 cluster/router/v3router/uniform_rule.go            |    2 +-
 common/constant/key.go                             |   28 +-
 common/rpc_service.go                              |    5 +-
 config/application_config.go                       |   45 +-
 config/base_config.go                              |  312 ------
 config/base_config_test.go                         |  303 -----
 config/config_api.go                               | 1091 +++++++++---------
 config/config_api_test.go                          |  283 +++--
 config/config_center_config.go                     |  207 ++--
 config/config_center_config_test.go                |   75 --
 config/config_loader.go                            |  910 ++++++++-------
 config/config_loader_options.go                    |  322 ++++--
 config/config_loader_options_test.go               |   61 ++
 config/config_loader_test.go                       | 1153 ++++++++++----------
 config/config_utils.go                             |   42 +
 config/consumer_config.go                          |  275 +++--
 config/{ => generic}/generic_service.go            |    2 +-
 config/graceful_shutdown.go                        |  241 ++--
 config/graceful_shutdown_config.go                 |    6 +-
 config/graceful_shutdown_test.go                   |  184 ++--
 config/metadata_report_config.go                   |   94 +-
 config/metadata_report_config_test.go              |   52 -
 config/metric_config_test.go                       |    8 +-
 config/protocol_config.go                          |   32 +-
 config/provider_config.go                          |  168 ++-
 config/provider_config_test.go                     |   64 +-
 config/reference_config.go                         |  136 ++-
 config/reference_config_test.go                    |  777 ++++++-------
 config/registry_config.go                          |  100 +-
 config/registry_config_test.go                     |   38 +-
 config/root_config.go                              |  255 +++++
 config/service.go                                  |    5 +
 config/service_config.go                           |  262 ++++-
 config/service_config_test.go                      |  215 ----
 config/service_discovery_config.go                 |    2 +-
 config/testdata/application.yaml                   |   35 +
 config/testdata/config/app/application.yaml        |    6 +
 .../testdata/config/center/conf-application.yaml   |   13 +
 config/testdata/config/protocol/application.yaml   |    6 +
 .../config/protocol/empty_application.yaml         |    2 +
 config/testdata/config/provider/application.yaml   |   12 +
 .../provider/empty_registry_application.yaml       |    8 +
 .../config/provider/registry_application.yaml      |   10 +
 config/testdata/config/registry/application.yaml   |   10 +
 .../config/registry/empty_application.yaml         |    2 +
 config/testdata/config/service/hello_service.go    |   18 +
 config/testdata/config/service/order_service.go    |   18 +
 config_center/apollo/impl.go                       |    2 +-
 config_center/apollo/impl_test.go                  |    6 +-
 filter/hystrix/filter.go                           |    6 +-
 go.mod                                             |    2 +
 go.sum                                             |   38 +-
 metadata/mapping/dynamic/service_name_mapping.go   |    2 +-
 .../mapping/dynamic/service_name_mapping_test.go   |    2 +-
 metadata/mapping/memory/service_name_mapping.go    |    2 +-
 metadata/service/exporter/configurable/exporter.go |    8 +-
 .../service/exporter/configurable/exporter_test.go |   91 +-
 metadata/service/local/service.go                  |    2 +-
 protocol/dubbo3/common_test.go                     |    2 +-
 protocol/dubbo3/dubbo3_protocol.go                 |    2 +-
 protocol/dubbo3/internal/client.go                 |    5 +-
 protocol/grpc/client.go                            |    6 +-
 protocol/grpc/grpc_protocol_test.go                |   52 +-
 protocol/grpc/internal/helloworld/client.go        |    5 +-
 protocol/grpc/internal/routeguide/client.go        |    5 +-
 protocol/grpc/server.go                            |    2 +-
 protocol/jsonrpc/jsonrpc_protocol_test.go          |    2 +-
 protocol/rest/config/reader/rest_config_reader.go  |   10 +-
 protocol/rest/rest_invoker_test.go                 |    2 +-
 protocol/rest/rest_protocol_test.go                |    2 +-
 registry/directory/directory.go                    |    5 +-
 registry/directory/directory_test.go               |    8 +-
 registry/etcdv3/service_discovery.go               |    4 +-
 registry/etcdv3/service_discovery_test.go          |    8 +-
 .../event_publishing_service_deiscovery_test.go    |    2 +-
 registry/event/service_config_exported_event.go    |    2 +-
 registry/file/service_discovery.go                 |    2 +-
 registry/file/service_discovery_test.go            |    2 +-
 registry/nacos/service_discovery.go                |    4 +-
 registry/nacos/service_discovery_test.go           |   10 +-
 registry/protocol/protocol.go                      |    7 +-
 registry/protocol/protocol_test.go                 |   15 +-
 .../servicediscovery/service_discovery_registry.go |    2 +-
 .../service_discovery_registry_test.go             |    3 +-
 registry/zookeeper/service_discovery.go            |    4 +-
 registry/zookeeper/service_discovery_test.go       |    8 +-
 remoting/getty/config.go                           |    5 +-
 remoting/getty/getty_client.go                     |    2 +-
 samples                                            |    1 -
 test/integrate/dubbo/go-client/client.go           |    2 +-
 test/integrate/dubbo/go-client/user.go             |    2 +-
 test/integrate/dubbo/go-server/server.go           |    2 +-
 test/integrate/dubbo/go-server/user.go             |    2 +-
 107 files changed, 4277 insertions(+), 4027 deletions(-)

diff --git a/cluster/router/chain/chain.go b/cluster/router/chain/chain.go
index 616909a..81839f7 100644
--- a/cluster/router/chain/chain.go
+++ b/cluster/router/chain/chain.go
@@ -122,7 +122,7 @@ func NewRouterChain(url *common.URL) (*RouterChain, error) {
 
 	for key, routerFactory := range routerFactories {
 		if virtualServiceConfigByte == nil || destinationRuleConfigByte == nil {
-			logger.Warnf("virtual Service Config or destinationRule Confi Byte may be empty, pls check your CONF_VIRTUAL_SERVICE_FILE_PATH and CONF_DEST_RULE_FILE_PATH env is correctly point to your yaml file\n")
+			logger.Warnf("virtual Service ProtocolConfig or destinationRule Confi Byte may be empty, pls check your CONF_VIRTUAL_SERVICE_FILE_PATH and CONF_DEST_RULE_FILE_PATH env is correctly point to your yaml file\n")
 		}
 		r, err := routerFactory().NewPriorityRouter(virtualServiceConfigByte, destinationRuleConfigByte)
 		if r == nil || err != nil {
diff --git a/cluster/router/v3router/judger/attachment_match_judger_test.go b/cluster/router/v3router/judger/attachment_match_judger_test.go
index 26a8d5e..eabc312 100644
--- a/cluster/router/v3router/judger/attachment_match_judger_test.go
+++ b/cluster/router/v3router/judger/attachment_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -26,7 +27,6 @@ import (
 )
 
 import (
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/protocol/invocation"
 )
 
diff --git a/cluster/router/v3router/judger/bool_match_judger.go b/cluster/router/v3router/judger/bool_match_judger.go
index 4dcf200..5c4bb46 100644
--- a/cluster/router/v3router/judger/bool_match_judger.go
+++ b/cluster/router/v3router/judger/bool_match_judger.go
@@ -17,7 +17,9 @@
 
 package judger
 
-import "dubbo.apache.org/dubbo-go/v3/config"
+import (
+	"dubbo.apache.org/dubbo-go/v3/config"
+)
 
 // nolint
 type BoolMatchJudger struct {
diff --git a/cluster/router/v3router/judger/bool_match_judger_test.go b/cluster/router/v3router/judger/bool_match_judger_test.go
index a86651e..fb7fc20 100644
--- a/cluster/router/v3router/judger/bool_match_judger_test.go
+++ b/cluster/router/v3router/judger/bool_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -25,10 +26,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 func TestBoolMatchJudger(t *testing.T) {
 	assert.True(t, newBoolMatchJudger(&config.BoolMatch{
 		Exact: true,
diff --git a/cluster/router/v3router/judger/double_match_judger_test.go b/cluster/router/v3router/judger/double_match_judger_test.go
index a2ba18b..f15f604 100644
--- a/cluster/router/v3router/judger/double_match_judger_test.go
+++ b/cluster/router/v3router/judger/double_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -25,10 +26,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 func TestDoubleMatchJudger(t *testing.T) {
 	assert.True(t, newDoubleMatchJudger(&config.DoubleMatch{
 		Exact: 3.14159,
diff --git a/cluster/router/v3router/judger/double_range_match_judger_test.go b/cluster/router/v3router/judger/double_range_match_judger_test.go
index 9487e40..e8c6b6f 100644
--- a/cluster/router/v3router/judger/double_range_match_judger_test.go
+++ b/cluster/router/v3router/judger/double_range_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -25,10 +26,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 func TestDoubleRangeMatchJudger(t *testing.T) {
 	assert.True(t, newDoubleRangeMatchJudger(&config.DoubleRangeMatch{
 		Start: 1.0,
diff --git a/cluster/router/v3router/judger/list_double_match_judger_test.go b/cluster/router/v3router/judger/list_double_match_judger_test.go
index bc84c78..696be6b 100644
--- a/cluster/router/v3router/judger/list_double_match_judger_test.go
+++ b/cluster/router/v3router/judger/list_double_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -25,10 +26,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 func TestListDoubleMatchJudger_Judge(t *testing.T) {
 	assert.True(t, newListDoubleMatchJudger(&config.ListDoubleMatch{
 		Oneof: []*config.DoubleMatch{
diff --git a/cluster/router/v3router/judger/list_string_match_judger_test.go b/cluster/router/v3router/judger/list_string_match_judger_test.go
index 1816b95..169ee57 100644
--- a/cluster/router/v3router/judger/list_string_match_judger_test.go
+++ b/cluster/router/v3router/judger/list_string_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -25,10 +26,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 func TestListStringMatchJudger(t *testing.T) {
 	assert.True(t, newListStringMatchJudger(&config.ListStringMatch{
 		Oneof: []*config.StringMatch{{Exact: "abd"}},
diff --git a/cluster/router/v3router/judger/method_match_judger_test.go b/cluster/router/v3router/judger/method_match_judger_test.go
index 71e90aa..d0f5023 100644
--- a/cluster/router/v3router/judger/method_match_judger_test.go
+++ b/cluster/router/v3router/judger/method_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"reflect"
 	"testing"
 )
@@ -27,7 +28,6 @@ import (
 )
 
 import (
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/protocol/invocation"
 )
 
diff --git a/cluster/router/v3router/judger/string_match_judger.go b/cluster/router/v3router/judger/string_match_judger.go
index fae5278..a502cc3 100644
--- a/cluster/router/v3router/judger/string_match_judger.go
+++ b/cluster/router/v3router/judger/string_match_judger.go
@@ -18,14 +18,11 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"regexp"
 	"strings"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 // nolint
 type StringMatchJudger struct {
 	config.StringMatch
diff --git a/cluster/router/v3router/judger/string_match_judger_test.go b/cluster/router/v3router/judger/string_match_judger_test.go
index 968eda9..c9da665 100644
--- a/cluster/router/v3router/judger/string_match_judger_test.go
+++ b/cluster/router/v3router/judger/string_match_judger_test.go
@@ -18,6 +18,7 @@
 package judger
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -25,10 +26,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 func TestNewStringMatchJudger(t *testing.T) {
 	assert.True(t, NewStringMatchJudger(&config.StringMatch{
 		Exact: "abc",
diff --git a/cluster/router/v3router/k8s_api/listener_handler_impl.go b/cluster/router/v3router/k8s_api/listener_handler_impl.go
index 64a8cf3..e6f660c 100644
--- a/cluster/router/v3router/k8s_api/listener_handler_impl.go
+++ b/cluster/router/v3router/k8s_api/listener_handler_impl.go
@@ -18,6 +18,7 @@
 package k8s_api
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	metav "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/watch"
@@ -27,7 +28,6 @@ import (
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/cluster/router/v3router/k8s_crd"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 	"dubbo.apache.org/dubbo-go/v3/remoting"
 )
diff --git a/cluster/router/v3router/router_chain.go b/cluster/router/v3router/router_chain.go
index ce82694..b677d8f 100644
--- a/cluster/router/v3router/router_chain.go
+++ b/cluster/router/v3router/router_chain.go
@@ -18,6 +18,7 @@
 package v3router
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"encoding/json"
 	"io"
 	"strings"
@@ -32,7 +33,6 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/cluster/router/v3router/k8s_api"
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 	"dubbo.apache.org/dubbo-go/v3/remoting"
diff --git a/cluster/router/v3router/router_chain_test.go b/cluster/router/v3router/router_chain_test.go
index 9e12da1..e1af532 100644
--- a/cluster/router/v3router/router_chain_test.go
+++ b/cluster/router/v3router/router_chain_test.go
@@ -18,6 +18,7 @@
 package v3router
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"fmt"
 	"testing"
 )
@@ -28,7 +29,6 @@ import (
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/cluster/router/v3router/k8s_api"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 )
 
diff --git a/cluster/router/v3router/uniform_rule.go b/cluster/router/v3router/uniform_rule.go
index 3b552b8..ef4b16c 100644
--- a/cluster/router/v3router/uniform_rule.go
+++ b/cluster/router/v3router/uniform_rule.go
@@ -18,6 +18,7 @@
 package v3router
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"math/rand"
 	"time"
 )
@@ -30,7 +31,6 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/cluster/router/v3router/judger"
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 )
 
diff --git a/common/constant/key.go b/common/constant/key.go
index 4d258bb..b1ec48e 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -53,6 +53,7 @@ const (
 	SSL_ENABLED_KEY = "ssl-enabled"
 	// PARAMS_TYPE_Key key used in pass through invoker factory, to define param type
 	PARAMS_TYPE_Key = "parameter-type-names"
+	DEFAULT_Key     = "default"
 )
 
 const (
@@ -169,19 +170,20 @@ const (
 )
 
 const (
-	RegistryConfigPrefix       = "dubbo.registries."
-	SingleRegistryConfigPrefix = "dubbo.registry."
-	ReferenceConfigPrefix      = "dubbo.reference."
-	ServiceConfigPrefix        = "dubbo.service."
-	ConfigBasePrefix           = "dubbo.base."
-	RemotePrefix               = "dubbo.remote."
-	ServiceDiscPrefix          = "dubbo.service-discovery."
-	ProtocolConfigPrefix       = "dubbo.protocols."
-	ProviderConfigPrefix       = "dubbo.provider."
-	ConsumerConfigPrefix       = "dubbo.consumer."
-	ShutdownConfigPrefix       = "dubbo.shutdown."
-	MetadataReportPrefix       = "dubbo.metadata-report."
-	RouterConfigPrefix         = "dubbo.router."
+	RegistryConfigPrefix       = "dubbo.registries"
+	ConfigCenterPrefix         = "dubbo.config-center"
+	SingleRegistryConfigPrefix = "dubbo.registry"
+	ReferenceConfigPrefix      = "dubbo.reference"
+	ServiceConfigPrefix        = "dubbo.service"
+	ConfigBasePrefix           = "dubbo.base"
+	RemotePrefix               = "dubbo.remote"
+	ServiceDiscPrefix          = "dubbo.service-discovery"
+	ProtocolConfigPrefix       = "dubbo.protocols"
+	ProviderConfigPrefix       = "dubbo.provider"
+	ConsumerConfigPrefix       = "dubbo.consumer"
+	ShutdownConfigPrefix       = "dubbo.shutdown"
+	MetadataReportPrefix       = "dubbo.metadata-report"
+	RouterConfigPrefix         = "dubbo.router"
 )
 
 const (
diff --git a/common/rpc_service.go b/common/rpc_service.go
index 57c8f1c..1bca7d9 100644
--- a/common/rpc_service.go
+++ b/common/rpc_service.go
@@ -37,8 +37,9 @@ import (
 // RPCService
 // rpc service interface
 type RPCService interface {
-	// Reference:
-	// rpc service id or reference id
+	//// Name rpc service id
+	//Name() string
+	// Reference  rpc service reference
 	Reference() string
 }
 
diff --git a/config/application_config.go b/config/application_config.go
index 1b4291d..55981a4 100644
--- a/config/application_config.go
+++ b/config/application_config.go
@@ -18,35 +18,38 @@
 package config
 
 import (
-	"github.com/creasty/defaults"
-)
-
-import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
+	"github.com/creasty/defaults"
 )
 
-// ApplicationConfig is a configuration for current application, whether the application is a provider or a consumer
+// ApplicationConfig is a configuration for current applicationConfig, whether the applicationConfig is a provider or a consumer
 type ApplicationConfig struct {
-	Organization string `yaml:"organization" json:"organization,omitempty" property:"organization"`
-	Name         string `yaml:"name" json:"name,omitempty" property:"name"`
-	Module       string `yaml:"module" json:"module,omitempty" property:"module"`
-	Version      string `yaml:"version" json:"version,omitempty" property:"version"`
-	Owner        string `yaml:"owner" json:"owner,omitempty" property:"owner"`
-	Environment  string `yaml:"environment" json:"environment,omitempty" property:"environment"`
+	Organization string `default:"dubbo.io" yaml:"organization" json:"organization,omitempty" property:"organization"`
+	Name         string `default:"dubbo.io" yaml:"name" json:"name,omitempty" property:"name"`
+	Module       string `default:"sample" yaml:"module" json:"module,omitempty" property:"module"`
+	Version      string `default:"0.0.1" yaml:"version" json:"version,omitempty" property:"version"`
+	Owner        string `default:"dubbo-go" yaml:"owner" json:"owner,omitempty" property:"owner"`
+	Environment  string `default:"dev" yaml:"environment" json:"environment,omitempty" property:"environment"`
 	// the metadata type. remote or local
 	MetadataType string `default:"local" yaml:"metadataType" json:"metadataType,omitempty" property:"metadataType"`
 }
 
-// nolint
-func (*ApplicationConfig) Prefix() string {
-	return constant.DUBBO + ".application."
+func NewApplicationConfig() *ApplicationConfig {
+	return &ApplicationConfig{}
+}
+
+// Prefix dubbo.applicationConfig
+func (ApplicationConfig) Prefix() string {
+	return constant.DUBBO + ".applicationConfig"
+}
+
+func (a *ApplicationConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(a)
+	return verify(a)
 }
 
-// UnmarshalYAML unmarshals the ApplicationConfig by @unmarshal function
-func (c *ApplicationConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
-	if err := defaults.Set(c); err != nil {
-		return err
-	}
-	type plain ApplicationConfig
-	return unmarshal((*plain)(c))
+func (a *ApplicationConfig) Validate() {
+	defaults.MustSet(a)
+	// todo set default application
 }
diff --git a/config/base_config.go b/config/base_config.go
deleted file mode 100644
index 0259549..0000000
--- a/config/base_config.go
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * 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 config
-
-import (
-	"bytes"
-	"reflect"
-	"strconv"
-	"strings"
-)
-
-import (
-	perrors "github.com/pkg/errors"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common/config"
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/common/yaml"
-)
-
-// BaseConfig is the common configuration for provider and consumer
-type BaseConfig struct {
-	ConfigCenterConfig *ConfigCenterConfig `yaml:"config_center" json:"config_center,omitempty"`
-
-	// since 1.5.0 version
-	Remotes              map[string]*RemoteConfig           `yaml:"remote" json:"remote,omitempty" property:"remote"`
-	ServiceDiscoveries   map[string]*ServiceDiscoveryConfig `yaml:"service_discovery" json:"service_discovery,omitempty" property:"service_discovery"`
-	MetadataReportConfig *MetadataReportConfig              `yaml:"metadata_report" json:"metadata_report,omitempty" property:"metadata_report"`
-
-	// application config
-	ApplicationConfig *ApplicationConfig `yaml:"application" json:"application,omitempty" property:"application"`
-
-	// prefix              string
-	fatherConfig        interface{}
-	EventDispatcherType string        `default:"direct" yaml:"event_dispatcher_type" json:"event_dispatcher_type,omitempty"`
-	MetricConfig        *MetricConfig `yaml:"metrics" json:"metrics,omitempty"`
-	fileStream          *bytes.Buffer
-
-	// cache file used to store the current used configurations.
-	CacheFile string `yaml:"cache_file" json:"cache_file,omitempty" property:"cache_file"`
-}
-
-func (c *BaseConfig) Prefix() string {
-	return constant.ConfigBasePrefix
-}
-
-func BaseInit(confBaseFile string) error {
-	if confBaseFile == "" {
-		return perrors.Errorf("application configure(base) file name is nil")
-	}
-	baseConfig = &BaseConfig{}
-	fileStream, err := yaml.UnmarshalYMLConfig(confBaseFile, baseConfig)
-	if err != nil {
-		return perrors.Errorf("unmarshalYmlConfig error %v", perrors.WithStack(err))
-	}
-	baseConfig.fileStream = bytes.NewBuffer(fileStream)
-	return nil
-}
-
-// nolint
-func (c *BaseConfig) GetServiceDiscoveries(name string) (config *ServiceDiscoveryConfig, ok bool) {
-	config, ok = c.ServiceDiscoveries[name]
-	return
-}
-
-// GetRemoteConfig will return the remote's config with the name if found
-func (c *BaseConfig) GetRemoteConfig(name string) (config *RemoteConfig, ok bool) {
-	config, ok = c.Remotes[name]
-	return
-}
-
-func getKeyPrefix(val reflect.Value) []string {
-	var prefix string
-	configPrefixMethod := "Prefix"
-	if val.CanAddr() {
-		prefix = val.Addr().MethodByName(configPrefixMethod).Call(nil)[0].String()
-	} else {
-		prefix = val.MethodByName(configPrefixMethod).Call(nil)[0].String()
-	}
-
-	return strings.Split(prefix, "|")
-}
-
-func getPtrElement(v reflect.Value) reflect.Value {
-	if v.Kind() == reflect.Ptr {
-		v = v.Elem()
-		if v.Kind() == reflect.Ptr {
-			return getPtrElement(v)
-		}
-	}
-	return v
-}
-
-func setFieldValue(val reflect.Value, id reflect.Value, config *config.InmemoryConfiguration) {
-	for i := 0; i < val.NumField(); i++ {
-		if key := val.Type().Field(i).Tag.Get("property"); key != "-" && key != "" {
-			f := val.Field(i)
-			if f.IsValid() {
-				setBaseValue := func(f reflect.Value) {
-					var (
-						ok    bool
-						value string
-						idStr string
-					)
-
-					prefixes := getKeyPrefix(val)
-
-					if id.Kind() == reflect.String {
-						idStr = id.Interface().(string)
-					}
-
-					for _, pfx := range prefixes {
-
-						if len(pfx) > 0 {
-							if len(idStr) > 0 {
-								ok, value = config.GetProperty(pfx + idStr + "." + key)
-							}
-							if len(value) == 0 || !ok {
-								ok, value = config.GetProperty(pfx + key)
-							}
-
-						} else {
-							ok, value = config.GetProperty(key)
-						}
-
-						if ok {
-							break
-						}
-
-					}
-					if ok {
-						errMsg := func(structName string, fieldName string, errorDetails error) {
-							logger.Errorf("Dynamic change the configuration in struct {%v} field {%v} error ,error message is {%v}",
-								structName, fieldName, errorDetails)
-						}
-						switch f.Kind() {
-						case reflect.Int64:
-							x, err := strconv.Atoi(value)
-							if err != nil {
-								errMsg(val.Type().Name(), val.Type().Field(i).Name, err)
-							} else {
-								if !f.OverflowInt(int64(x)) {
-									f.SetInt(int64(x))
-								} else {
-									errMsg(val.Type().Name(), val.Type().Field(i).Name, perrors.Errorf("the int64 value {%v} from config center is  overflow", int64(x)))
-								}
-							}
-						case reflect.String:
-							f.SetString(value)
-						case reflect.Bool:
-							x, err := strconv.ParseBool(value)
-							if err != nil {
-								errMsg(val.Type().Name(), val.Type().Field(i).Name, err)
-							}
-							f.SetBool(x)
-						case reflect.Float64:
-							x, err := strconv.ParseFloat(value, 64)
-							if err != nil {
-								errMsg(val.Type().Name(), val.Type().Field(i).Name, err)
-							} else {
-								if !f.OverflowFloat(x) {
-									f.SetFloat(x)
-								} else {
-									errMsg(val.Type().Name(), val.Type().Field(i).Name, perrors.Errorf("the float64 value {%v} from config center is  overflow", x))
-								}
-							}
-						default:
-							logger.Warnf("The kind of field {%v} is not supported ", f.Kind().String())
-						}
-
-					}
-				}
-
-				if f.Kind() == reflect.Ptr {
-					f = getPtrElement(f)
-					if f.Kind() == reflect.Struct {
-						setFieldValue(f, reflect.Value{}, config)
-					} else {
-						setBaseValue(f)
-					}
-				}
-
-				if f.Kind() == reflect.Struct {
-					setFieldValue(f, reflect.Value{}, config)
-				}
-				if f.Kind() == reflect.Slice {
-					for i := 0; i < f.Len(); i++ {
-						e := f.Index(i)
-						if e.Kind() == reflect.Ptr {
-							e = getPtrElement(e)
-							if e.Kind() == reflect.Struct {
-								setFieldValue(e, reflect.Value{}, config)
-							} else {
-								setBaseValue(e)
-							}
-						}
-
-					}
-				}
-				if f.Kind() == reflect.Map {
-
-					if f.Type().Elem().Kind() == reflect.Ptr {
-						// initiate config
-						s := reflect.New(f.Type().Elem().Elem())
-						prefix := s.MethodByName("Prefix").Call(nil)[0].String()
-						for _, pfx := range strings.Split(prefix, "|") {
-							m := config.GetSubProperty(pfx)
-							for k := range m {
-								f.SetMapIndex(reflect.ValueOf(k), reflect.New(f.Type().Elem().Elem()))
-							}
-						}
-
-					}
-
-					for _, k := range f.MapKeys() {
-						v := f.MapIndex(k)
-						switch v.Kind() {
-						case reflect.Ptr:
-							v = getPtrElement(v)
-							if v.Kind() == reflect.Struct {
-								setFieldValue(v, k, config)
-							} else {
-								setBaseValue(v)
-							}
-						case reflect.Int64, reflect.String, reflect.Bool, reflect.Float64:
-							setBaseValue(v)
-						default:
-							logger.Warnf("The kind of field {%v} is not supported ", v.Kind().String())
-						}
-					}
-				}
-				setBaseValue(f)
-			}
-		}
-	}
-}
-
-func (c *BaseConfig) fresh() {
-	configList := config.GetEnvInstance().Configuration()
-	for element := configList.Back(); element != nil; element = element.Prev() {
-		cfg := element.Value.(*config.InmemoryConfiguration)
-		c.freshInternalConfig(cfg)
-	}
-}
-
-func (c *BaseConfig) freshInternalConfig(config *config.InmemoryConfiguration) {
-	// reflect to init struct
-	tp := reflect.ValueOf(c.fatherConfig).Elem().Type()
-	initializeStruct(tp, reflect.ValueOf(c.fatherConfig).Elem())
-
-	val := reflect.Indirect(reflect.ValueOf(c.fatherConfig))
-	setFieldValue(val, reflect.Value{}, config)
-}
-
-// SetFatherConfig sets father config by @fatherConfig
-func (c *BaseConfig) SetFatherConfig(fatherConfig interface{}) {
-	c.fatherConfig = fatherConfig
-}
-
-func initializeStruct(t reflect.Type, v reflect.Value) {
-	if v.Kind() != reflect.Struct {
-		return
-	}
-	for i := 0; i < v.NumField(); i++ {
-		f := v.Field(i)
-		ft := t.Field(i)
-
-		if ft.Tag.Get("property") == "" {
-			continue
-		}
-		switch ft.Type.Kind() {
-		case reflect.Map:
-			if f.IsNil() {
-				f.Set(reflect.MakeMap(ft.Type))
-			}
-		case reflect.Slice:
-			if f.IsNil() {
-				f.Set(reflect.MakeSlice(ft.Type, 0, 0))
-			}
-		case reflect.Chan:
-			if f.IsNil() {
-				f.Set(reflect.MakeChan(ft.Type, 0))
-			}
-		case reflect.Struct:
-			initializeStruct(ft.Type, f)
-		case reflect.Ptr:
-			if f.IsNil() {
-				fv := reflect.New(ft.Type.Elem())
-				initializeStruct(ft.Type.Elem(), fv.Elem())
-				f.Set(fv)
-			}
-		default:
-		}
-	}
-}
diff --git a/config/base_config_test.go b/config/base_config_test.go
deleted file mode 100644
index 7d5fa55..0000000
--- a/config/base_config_test.go
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * 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 config
-
-import (
-	"reflect"
-	"testing"
-)
-
-import (
-	"github.com/stretchr/testify/assert"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common/config"
-)
-
-func getMockMap() map[string]string {
-	baseMockMap := map[string]string{
-		"dubbo.registries.shanghai_reg1.protocol":             "mock100",
-		"dubbo.reference.com.MockService.MockService.retries": "10",
-		"dubbo.com.MockService.MockService.GetUser.retries":   "10",
-		"dubbo.consumer.check":                                "false",
-		"dubbo.application.name":                              "dubbo",
-	}
-	return baseMockMap
-}
-
-var baseAppConfig = &ApplicationConfig{
-	Organization: "dubbo_org",
-	Name:         "dubbo",
-	Module:       "module",
-	Version:      "2.6.0",
-	Owner:        "dubbo",
-	Environment:  "test",
-}
-
-var baseRegistries = map[string]*RegistryConfig{
-	"shanghai_reg2": {
-		Protocol:   "mock",
-		TimeoutStr: "2s",
-		Group:      "shanghai_idc",
-		Address:    "127.0.0.2:2181",
-		Username:   "user1",
-		Password:   "pwd1",
-	},
-	"hangzhou_reg1": {
-		Protocol:   "mock",
-		TimeoutStr: "2s",
-		Group:      "hangzhou_idc",
-		Address:    "127.0.0.3:2181",
-		Username:   "user1",
-		Password:   "pwd1",
-	},
-	"hangzhou_reg2": {
-		Protocol:   "mock",
-		TimeoutStr: "2s",
-		Group:      "hangzhou_idc",
-		Address:    "127.0.0.4:2181",
-		Username:   "user1",
-		Password:   "pwd1",
-	},
-}
-
-var baseMockRef = map[string]*ReferenceConfig{
-	"MockService": {
-		InterfaceName: "com.MockService",
-		Protocol:      "mock",
-		Cluster:       "failover",
-		Loadbalance:   "random",
-		Retries:       "3",
-		Group:         "huadong_idc",
-		Version:       "1.0.0",
-		Methods: []*MethodConfig{
-			{
-				InterfaceId:   "MockService",
-				InterfaceName: "com.MockService",
-				Name:          "GetUser",
-				Retries:       "2",
-				LoadBalance:   "random",
-			},
-			{
-				InterfaceId:   "MockService",
-				InterfaceName: "com.MockService",
-				Name:          "GetUser1",
-				Retries:       "2",
-				LoadBalance:   "random",
-			},
-		},
-	},
-}
-
-func TestRefresh(t *testing.T) {
-	c := &BaseConfig{}
-	c.fileStream = nil
-	mockMap := getMockMap()
-	mockMap["dubbo.shutdown.timeout"] = "12s"
-
-	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
-	config.GetEnvInstance().UpdateAppExternalConfigMap(map[string]string{})
-
-	father := &ConsumerConfig{
-		Check: &[]bool{true}[0],
-		BaseConfig: BaseConfig{
-			ApplicationConfig: baseAppConfig,
-		},
-		Registries: baseRegistries,
-		References: baseMockRef,
-		ShutdownConfig: &ShutdownConfig{
-			Timeout:              "12s",
-			StepTimeout:          "2s",
-			RejectRequestHandler: "mock",
-			RejectRequest:        false,
-			RequestsFinished:     false,
-		},
-	}
-
-	c.SetFatherConfig(father)
-	c.fresh()
-	assert.Equal(t, "mock100", father.Registries["shanghai_reg1"].Protocol)
-	assert.Equal(t, "10", father.References["MockService"].Retries)
-
-	assert.Equal(t, "10", father.References["MockService"].Methods[0].Retries)
-	assert.Equal(t, &[]bool{false}[0], father.Check)
-	assert.Equal(t, "dubbo", father.ApplicationConfig.Name)
-}
-
-func TestAppExternalRefresh(t *testing.T) {
-	c := &BaseConfig{}
-	mockMap := getMockMap()
-	mockMap["dubbo.reference.com.MockService.retries"] = "5"
-
-	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
-	mockMap["dubbo.consumer.check"] = "true"
-	config.GetEnvInstance().UpdateAppExternalConfigMap(mockMap)
-
-	father := &ConsumerConfig{
-		Check: &[]bool{true}[0],
-		BaseConfig: BaseConfig{
-			ApplicationConfig: baseAppConfig,
-		},
-		Registries: baseRegistries,
-		References: baseMockRef,
-	}
-
-	c.SetFatherConfig(father)
-	c.fresh()
-	assert.Equal(t, "mock100", father.Registries["shanghai_reg1"].Protocol)
-	assert.Equal(t, "10", father.References["MockService"].Retries)
-
-	assert.Equal(t, "10", father.References["MockService"].Methods[0].Retries)
-	assert.Equal(t, &[]bool{true}[0], father.Check)
-	assert.Equal(t, "dubbo", father.ApplicationConfig.Name)
-}
-
-func TestAppExternalWithoutIDRefresh(t *testing.T) {
-	c := &BaseConfig{}
-	mockMap := getMockMap()
-	delete(mockMap, "dubbo.reference.com.MockService.MockService.retries")
-	mockMap["dubbo.reference.com.MockService.retries"] = "10"
-
-	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
-	mockMap["dubbo.consumer.check"] = "true"
-	config.GetEnvInstance().UpdateAppExternalConfigMap(mockMap)
-	father := &ConsumerConfig{
-		Check: &[]bool{true}[0],
-		BaseConfig: BaseConfig{
-			ApplicationConfig: baseAppConfig,
-		},
-		Registries: baseRegistries,
-		References: baseMockRef,
-	}
-
-	c.SetFatherConfig(father)
-	c.fresh()
-	assert.Equal(t, "mock100", father.Registries["shanghai_reg1"].Protocol)
-	assert.Equal(t, "10", father.References["MockService"].Retries)
-
-	assert.Equal(t, "10", father.References["MockService"].Methods[0].Retries)
-	assert.Equal(t, &[]bool{true}[0], father.Check)
-	assert.Equal(t, "dubbo", father.ApplicationConfig.Name)
-}
-
-func TestRefreshSingleRegistry(t *testing.T) {
-	c := &BaseConfig{}
-	mockMap := map[string]string{}
-	mockMap["dubbo.registry.address"] = "mock100://127.0.0.1:2181"
-	mockMap["dubbo.reference.com.MockService.MockService.retries"] = "10"
-	mockMap["dubbo.com.MockService.MockService.GetUser.retries"] = "10"
-	mockMap["dubbo.consumer.check"] = "false"
-	mockMap["dubbo.application.name"] = "dubbo"
-
-	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
-	config.GetEnvInstance().UpdateAppExternalConfigMap(map[string]string{})
-
-	father := &ConsumerConfig{
-		Check: &[]bool{true}[0],
-		BaseConfig: BaseConfig{
-			ApplicationConfig: baseAppConfig,
-		},
-		Registries: map[string]*RegistryConfig{},
-		Registry:   &RegistryConfig{},
-		References: baseMockRef,
-	}
-
-	c.SetFatherConfig(father)
-	c.fresh()
-	assert.Equal(t, "mock100://127.0.0.1:2181", father.Registry.Address)
-	assert.Equal(t, "10", father.References["MockService"].Retries)
-
-	assert.Equal(t, "10", father.References["MockService"].Methods[0].Retries)
-	assert.Equal(t, &[]bool{false}[0], father.Check)
-	assert.Equal(t, "dubbo", father.ApplicationConfig.Name)
-}
-
-func TestRefreshProvider(t *testing.T) {
-	c := &BaseConfig{}
-	mockMap := getMockMap()
-	delete(mockMap, "dubbo.reference.com.MockService.MockService.retries")
-	mockMap["dubbo.service.com.MockService.MockService.retries"] = "10"
-	mockMap["dubbo.protocols.jsonrpc1.name"] = "jsonrpc"
-	mockMap["dubbo.protocols.jsonrpc1.ip"] = "127.0.0.1"
-	mockMap["dubbo.protocols.jsonrpc1.port"] = "20001"
-
-	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
-	config.GetEnvInstance().UpdateAppExternalConfigMap(map[string]string{})
-
-	father := &ProviderConfig{
-		BaseConfig: BaseConfig{
-			ApplicationConfig: baseAppConfig,
-		},
-		Registries: baseRegistries,
-		Services: map[string]*ServiceConfig{
-			"MockService": {
-				InterfaceName: "com.MockService",
-				Protocol:      "mock",
-				Cluster:       "failover",
-				Loadbalance:   "random",
-				Retries:       "3",
-				Group:         "huadong_idc",
-				Version:       "1.0.0",
-				Methods: []*MethodConfig{
-					{
-						InterfaceId:   "MockService",
-						InterfaceName: "com.MockService",
-						Name:          "GetUser",
-						Retries:       "2",
-						LoadBalance:   "random",
-					},
-					{
-						InterfaceId:   "MockService",
-						InterfaceName: "com.MockService",
-						Name:          "GetUser1",
-						Retries:       "2",
-						LoadBalance:   "random",
-					},
-				},
-			},
-		},
-	}
-
-	c.SetFatherConfig(father)
-	c.fresh()
-	assert.Equal(t, "mock100", father.Registries["shanghai_reg1"].Protocol)
-	assert.Equal(t, "10", father.Services["MockService"].Retries)
-
-	assert.Equal(t, "10", father.Services["MockService"].Methods[0].Retries)
-	assert.Equal(t, "dubbo", father.ApplicationConfig.Name)
-	assert.Equal(t, "20001", father.Protocols["jsonrpc1"].Port)
-}
-
-func TestInitializeStruct(t *testing.T) {
-	testConsumerConfig := &ConsumerConfig{}
-	tp := reflect.TypeOf(ConsumerConfig{})
-	v := reflect.New(tp)
-	initializeStruct(tp, v.Elem())
-	t.Logf("testConsumerConfig type:%s", reflect.ValueOf(testConsumerConfig).Elem().Type().String())
-	reflect.ValueOf(testConsumerConfig).Elem().Set(v.Elem())
-
-	assert.Condition(t, func() (success bool) {
-		return testConsumerConfig.Registry != nil
-	})
-	assert.Condition(t, func() (success bool) {
-		return testConsumerConfig.Registries != nil
-	})
-	assert.Condition(t, func() (success bool) {
-		return testConsumerConfig.References != nil
-	})
-}
diff --git a/config/config_api.go b/config/config_api.go
index fc9ebdb..ebcabd4 100644
--- a/config/config_api.go
+++ b/config/config_api.go
@@ -1,545 +1,556 @@
 /*
- * 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 config
 
-import (
-	"time"
-)
-
-//////////////////////////////////// default registry config
-const (
-	// defaultZKAddr is the default registry address of zookeeper
-	defaultZKAddr = "127.0.0.1:2181"
-
-	// defaultNacosAddr is the default registry address of nacos
-	defaultNacosAddr = "127.0.0.1:8848"
-
-	// defaultRegistryTimeout is the default registry timeout
-	defaultRegistryTimeout = "3s"
-)
-
-// NewDefaultRegistryConfig New default registry config
-// the input @protocol can only be:
-// "zookeeper" with default addr "127.0.0.1:2181"
-// "nacos" with default addr "127.0.0.1:8848"
-func NewDefaultRegistryConfig(protocol string) *RegistryConfig {
-	switch protocol {
-	case "zookeeper":
-		return &RegistryConfig{
-			Protocol:   protocol,
-			Address:    defaultZKAddr,
-			TimeoutStr: defaultRegistryTimeout,
-		}
-	case "nacos":
-		return &RegistryConfig{
-			Protocol:   protocol,
-			Address:    defaultNacosAddr,
-			TimeoutStr: defaultRegistryTimeout,
-		}
-	default:
-		return &RegistryConfig{
-			Protocol: protocol,
-		}
-	}
-}
-
-///////////////////////////////////// registry config api
-type RegistryConfigOpt func(config *RegistryConfig) *RegistryConfig
-
-// NewRegistryConfig creates New RegistryConfig with @opts
-func NewRegistryConfig(opts ...RegistryConfigOpt) *RegistryConfig {
-	newRegistryConfig := NewDefaultRegistryConfig("")
-	for _, v := range opts {
-		newRegistryConfig = v(newRegistryConfig)
-	}
-	return newRegistryConfig
-}
-
-// WithRegistryProtocol returns RegistryConfigOpt with given @regProtocol name
-func WithRegistryProtocol(regProtocol string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Protocol = regProtocol
-		return config
-	}
-}
-
-// WithRegistryAddress returns RegistryConfigOpt with given @addr registry address
-func WithRegistryAddress(addr string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Address = addr
-		return config
-	}
-}
-
-// WithRegistryTimeOut returns RegistryConfigOpt with given @timeout registry config
-func WithRegistryTimeOut(timeout string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.TimeoutStr = timeout
-		return config
-	}
-}
-
-// WithRegistryGroup returns RegistryConfigOpt with given @group registry group
-func WithRegistryGroup(group string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Group = group
-		return config
-	}
-}
-
-// WithRegistryTTL returns RegistryConfigOpt with given @ttl registry ttl
-func WithRegistryTTL(ttl string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.TTL = ttl
-		return config
-	}
-}
-
-// WithRegistryUserName returns RegistryConfigOpt with given @userName registry userName
-func WithRegistryUserName(userName string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Username = userName
-		return config
-	}
-}
-
-// WithRegistryPassword returns RegistryConfigOpt with given @psw registry password
-func WithRegistryPassword(psw string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Password = psw
-		return config
-	}
-}
-
-// WithRegistrySimplified returns RegistryConfigOpt with given @simplified registry simplified flag
-func WithRegistrySimplified(simplified bool) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Simplified = simplified
-		return config
-	}
-}
-
-// WithRegistryPreferred returns RegistryConfig with given @preferred registry preferred flag
-func WithRegistryPreferred(preferred bool) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Preferred = preferred
-		return config
-	}
-}
-
-// WithRegistryWeight returns RegistryConfigOpt with given @weight registry weight flag
-func WithRegistryWeight(weight int64) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Weight = weight
-		return config
-	}
-}
-
-// WithRegistryParams returns RegistryConfigOpt with given registry @params
-func WithRegistryParams(params map[string]string) RegistryConfigOpt {
-	return func(config *RegistryConfig) *RegistryConfig {
-		config.Params = params
-		return config
-	}
-}
-
-///////////////////////////////////// consumer config api
-// ConsumerConfigOpt is the options to init ConsumerConfig
-type ConsumerConfigOpt func(config *ConsumerConfig) *ConsumerConfig
-
-// NewDefaultConsumerConfig returns default ConsumerConfig
-// with connection timeout = 3s, request timeout = 3s
-func NewDefaultConsumerConfig() *ConsumerConfig {
-	check := true
-	newConsumerConfig := &ConsumerConfig{
-		BaseConfig:     BaseConfig{},
-		Registries:     make(map[string]*RegistryConfig, 8),
-		References:     make(map[string]*ReferenceConfig, 8),
-		ConnectTimeout: 3 * time.Second,
-		RequestTimeout: 3 * time.Second,
-		Check:          &check,
-	}
-	return newConsumerConfig
-}
-
-// NewConsumerConfig returns ConsumerConfig with @opts
-func NewConsumerConfig(opts ...ConsumerConfigOpt) *ConsumerConfig {
-	newConfig := NewDefaultConsumerConfig()
-	for _, v := range opts {
-		v(newConfig)
-	}
-	return newConfig
-}
-
-// WithConsumerAppConfig returns ConsumerConfigOpt with given @appConfig
-func WithConsumerAppConfig(appConfig *ApplicationConfig) ConsumerConfigOpt {
-	return func(config *ConsumerConfig) *ConsumerConfig {
-		config.ApplicationConfig = appConfig
-		return config
-	}
-}
-
-// WithConsumerRegistryConfig returns ConsumerConfigOpt with given @registryKey and @regConfig
-func WithConsumerRegistryConfig(registryKey string, regConfig *RegistryConfig) ConsumerConfigOpt {
-	return func(config *ConsumerConfig) *ConsumerConfig {
-		config.Registries[registryKey] = regConfig
-		return config
-	}
-}
-
-// WithConsumerReferenceConfig returns ConsumerConfigOpt with
-func WithConsumerReferenceConfig(referenceKey string, refConfig *ReferenceConfig) ConsumerConfigOpt {
-	return func(config *ConsumerConfig) *ConsumerConfig {
-		config.References[referenceKey] = refConfig
-		return config
-	}
-}
-
-// WithConsumerConnTimeout returns ConsumerConfigOpt with given consumer conn @timeout
-func WithConsumerConnTimeout(timeout time.Duration) ConsumerConfigOpt {
-	return func(config *ConsumerConfig) *ConsumerConfig {
-		config.ConnectTimeout = timeout
-		return config
-	}
-}
-
-// WithConsumerRequestTimeout returns ConsumerConfigOpt with given consumer request @timeout
-func WithConsumerRequestTimeout(timeout time.Duration) ConsumerConfigOpt {
-	return func(config *ConsumerConfig) *ConsumerConfig {
-		config.RequestTimeout = timeout
-		return config
-	}
-}
-
-// WithConsumerConfigCenterConfig returns ConsumerConfigOpt with given @configCenterConfig
-func WithConsumerConfigCenterConfig(configCenterConfig *ConfigCenterConfig) ConsumerConfigOpt {
-	return func(config *ConsumerConfig) *ConsumerConfig {
-		config.ConfigCenterConfig = configCenterConfig
-		return config
-	}
-}
-
-// WithConsumerConfigCheck returns ConsumerConfigOpt with given @check flag
-func WithConsumerConfigCheck(check bool) ConsumerConfigOpt {
-	return func(config *ConsumerConfig) *ConsumerConfig {
-		*config.Check = check
-		return config
-	}
-}
-
-//////////////////////////////////// reference config api
-// ReferenceConfigOpt is consumer's reference config
-type ReferenceConfigOpt func(config *ReferenceConfig) *ReferenceConfig
-
-// NewDefaultReferenceConfig returns empty ReferenceConfig
-func NewDefaultReferenceConfig() *ReferenceConfig {
-	newReferenceConfig := NewReferenceConfig("")
-	newReferenceConfig.Methods = make([]*MethodConfig, 0, 8)
-	newReferenceConfig.Params = make(map[string]string, 8)
-	return newReferenceConfig
-}
-
-// NewReferenceConfigByAPI returns ReferenceConfig with given @opts
-func NewReferenceConfigByAPI(opts ...ReferenceConfigOpt) *ReferenceConfig {
-	newReferenceConfig := NewDefaultReferenceConfig()
-	for _, v := range opts {
-		v(newReferenceConfig)
-	}
-	return newReferenceConfig
-}
-
-// WithReferenceRegistry returns ReferenceConfigOpt with given registryKey: @registry
-func WithReferenceRegistry(registry string) ReferenceConfigOpt {
-	return func(config *ReferenceConfig) *ReferenceConfig {
-		config.Registry = registry
-		return config
-	}
-}
-
-// WithReferenceProtocol returns ReferenceConfigOpt with given protocolKey: @protocol
-func WithReferenceProtocol(protocol string) ReferenceConfigOpt {
-	return func(config *ReferenceConfig) *ReferenceConfig {
-		config.Protocol = protocol
-		return config
-	}
-}
-
-// WithReferenceInterface returns ReferenceConfigOpt with given @interfaceName
-func WithReferenceInterface(interfaceName string) ReferenceConfigOpt {
-	return func(config *ReferenceConfig) *ReferenceConfig {
-		config.InterfaceName = interfaceName
-		return config
-	}
-}
-
-// WithReferenceCluster returns ReferenceConfigOpt with given cluster name: @cluster
-func WithReferenceCluster(cluster string) ReferenceConfigOpt {
-	return func(config *ReferenceConfig) *ReferenceConfig {
-		config.Cluster = cluster
-		return config
-	}
-}
-
-// WithReferenceMethod returns ReferenceConfigOpt with given @method, @retries, and load balance: @lb
-func WithReferenceMethod(methodName, retries, lb string) ReferenceConfigOpt {
-	return func(config *ReferenceConfig) *ReferenceConfig {
-		config.Methods = append(config.Methods, &MethodConfig{
-			Name:        methodName,
-			Retries:     retries,
-			LoadBalance: lb,
-		})
-		return config
-	}
-}
-
-///////////////////////////////////// provider config api
-// ProviderConfigOpt is the
-type ProviderConfigOpt func(config *ProviderConfig) *ProviderConfig
-
-// NewDefaultProviderConfig returns ProviderConfig with default ApplicationConfig
-func NewDefaultProviderConfig() *ProviderConfig {
-	newConsumerConfig := &ProviderConfig{
-		BaseConfig: BaseConfig{
-			ApplicationConfig: &ApplicationConfig{
-				Name:         "dubbo",
-				Module:       "module",
-				Organization: "dubbo_org",
-				Owner:        "dubbo",
-			},
-		},
-		Services:   make(map[string]*ServiceConfig),
-		Registries: make(map[string]*RegistryConfig, 8),
-		Protocols:  make(map[string]*ProtocolConfig, 8),
-	}
-	return newConsumerConfig
-}
-
-// NewProviderConfig returns ProviderConfig with given @opts
-func NewProviderConfig(opts ...ProviderConfigOpt) *ProviderConfig {
-	newConfig := NewDefaultProviderConfig()
-	for _, v := range opts {
-		v(newConfig)
-	}
-	return newConfig
-}
-
-// WithProviderRegistryConfig returns ProviderConfigOpt with given registry config: @regConfig
-func WithProviderRegistryConfig(regConfig *RegistryConfig) ProviderConfigOpt {
-	return func(config *ProviderConfig) *ProviderConfig {
-		config.Registries[regConfig.Protocol] = regConfig
-		return config
-	}
-}
-
-// WithProviderAppConfig returns ProviderConfigOpt with given @appConfig
-func WithProviderAppConfig(appConfig *ApplicationConfig) ProviderConfigOpt {
-	return func(config *ProviderConfig) *ProviderConfig {
-		config.ApplicationConfig = appConfig
-		return config
-	}
-}
-
-// WithProviderServices returns ProviderConfig with given serviceNameKey @serviceName and @serviceConfig
-func WithProviderServices(serviceName string, serviceConfig *ServiceConfig) ProviderConfigOpt {
-	return func(config *ProviderConfig) *ProviderConfig {
-		config.Services[serviceName] = serviceConfig
-		return config
-	}
-}
-
-// WithProviderProtocol returns ProviderConfigOpt with given @protocolKey, protocolName @protocol and @port
-func WithProviderProtocol(protocolKey, protocol, port string) ProviderConfigOpt {
-	return func(config *ProviderConfig) *ProviderConfig {
-		config.Protocols[protocolKey] = &ProtocolConfig{
-			Name: protocol,
-			Port: port,
-		}
-		return config
-	}
-}
-
-// WithProviderRegistry returns ProviderConfigOpt with given @registryKey and registry @registryConfig
-func WithProviderRegistry(registryKey string, registryConfig *RegistryConfig) ProviderConfigOpt {
-	return func(config *ProviderConfig) *ProviderConfig {
-		config.Registries[registryKey] = registryConfig
-		return config
-	}
-}
-
-/////////////////////////////////////// service config api
-// ServiceConfigOpt is the option to init ServiceConfig
-type ServiceConfigOpt func(config *ServiceConfig) *ServiceConfig
-
-// NewDefaultServiceConfig returns default ServiceConfig
-func NewDefaultServiceConfig() *ServiceConfig {
-	newServiceConfig := NewServiceConfig("")
-	newServiceConfig.Params = make(map[string]string)
-	newServiceConfig.Methods = make([]*MethodConfig, 0, 8)
-	return newServiceConfig
-}
-
-// NewServiceConfigByAPI is named as api, because there is NewServiceConfig func already declared
-// NewServiceConfigByAPI returns ServiceConfig with given @opts
-func NewServiceConfigByAPI(opts ...ServiceConfigOpt) *ServiceConfig {
-	defaultServiceConfig := NewDefaultServiceConfig()
-	for _, v := range opts {
-		v(defaultServiceConfig)
-	}
-	return defaultServiceConfig
-}
-
-// WithServiceRegistry returns ServiceConfigOpt with given registryKey @registry
-func WithServiceRegistry(registry string) ServiceConfigOpt {
-	return func(config *ServiceConfig) *ServiceConfig {
-		config.Registry = registry
-		return config
-	}
-}
-
-// WithServiceProtocol returns ServiceConfigOpt with given protocolKey @protocol
-func WithServiceProtocol(protocol string) ServiceConfigOpt {
-	return func(config *ServiceConfig) *ServiceConfig {
-		config.Protocol = protocol
-		return config
-	}
-}
-
-// WithServiceInterface returns ServiceConfigOpt with given @interfaceName
-func WithServiceInterface(interfaceName string) ServiceConfigOpt {
-	return func(config *ServiceConfig) *ServiceConfig {
-		config.InterfaceName = interfaceName
-		return config
-	}
-}
-
-// WithServiceLoadBalance returns ServiceConfigOpt with given load balance @lb
-func WithServiceLoadBalance(lb string) ServiceConfigOpt {
-	return func(config *ServiceConfig) *ServiceConfig {
-		config.Loadbalance = lb
-		return config
-	}
-}
-
-// WithServiceWarmUpTime returns ServiceConfigOpt with given @warmUp time
-func WithServiceWarmUpTime(warmUp string) ServiceConfigOpt {
-	return func(config *ServiceConfig) *ServiceConfig {
-		config.Warmup = warmUp
-		return config
-	}
-}
-
-// WithServiceCluster returns ServiceConfigOpt with given cluster name @cluster
-func WithServiceCluster(cluster string) ServiceConfigOpt {
-	return func(config *ServiceConfig) *ServiceConfig {
-		config.Cluster = cluster
-		return config
-	}
-}
-
-// WithServiceMethod returns ServiceConfigOpt with given @name, @retries and load balance @lb
-func WithServiceMethod(name, retries, lb string) ServiceConfigOpt {
-	return func(config *ServiceConfig) *ServiceConfig {
-		config.Methods = append(config.Methods, &MethodConfig{
-			Name:        name,
-			Retries:     retries,
-			LoadBalance: lb,
-		})
-		return config
-	}
-}
-
-///////////////////////////////////////// Application config api
-// ApplicationConfigOpt is option to init ApplicationConfig
-type ApplicationConfigOpt func(config *ApplicationConfig) *ApplicationConfig
-
-// NewDefaultApplicationConfig returns ApplicationConfig with default
-// name: dubbo.io
-// module: sample
-// organization: dubbo.io
-// owner: dubbogo
-// version: 0.0.1
-// environment dev
-func NewDefaultApplicationConfig() *ApplicationConfig {
-	newAppConfig := &ApplicationConfig{
-		Name:         "dubbo.io",
-		Module:       "sample",
-		Organization: "dubbo.io",
-		Owner:        "dubbogo",
-		Version:      "0.0.1",
-		Environment:  "dev",
-	}
-	return newAppConfig
-}
-
-// NewApplicationConfig is named as api, because there is NewServiceConfig func already declared
-// NewApplicationConfig returns ApplicationConfig with default application config
-func NewApplicationConfig(opts ...ApplicationConfigOpt) *ApplicationConfig {
-	defaultServiceConfig := NewDefaultApplicationConfig()
-	for _, v := range opts {
-		v(defaultServiceConfig)
-	}
-	return defaultServiceConfig
-}
-
-// WithAppName returns ApplicationConfigOpt with given @name
-func WithAppName(name string) ApplicationConfigOpt {
-	return func(config *ApplicationConfig) *ApplicationConfig {
-		config.Name = name
-		return config
-	}
-}
-
-// WithAppModule returns ApplicationConfigOpt with given @module
-func WithAppModule(module string) ApplicationConfigOpt {
-	return func(config *ApplicationConfig) *ApplicationConfig {
-		config.Module = module
-		return config
-	}
-}
-
-// WithAppOrganization returns ApplicationConfigOpt wight given organization @org
-func WithAppOrganization(org string) ApplicationConfigOpt {
-	return func(config *ApplicationConfig) *ApplicationConfig {
-		config.Organization = org
-		return config
-	}
-}
-
-// WithAppOwner returns ApplicationConfigOpt with given @owner
-func WithAppOwner(owner string) ApplicationConfigOpt {
-	return func(config *ApplicationConfig) *ApplicationConfig {
-		config.Owner = owner
-		return config
-	}
-}
-
-// WithAppVersion returns ApplicationConfigOpt with given version @version
-func WithAppVersion(version string) ApplicationConfigOpt {
-	return func(config *ApplicationConfig) *ApplicationConfig {
-		config.Version = version
-		return config
-	}
-}
-
-// WithAppEnvironment returns ApplicationConfigOpt with given environment @env
-func WithAppEnvironment(env string) ApplicationConfigOpt {
-	return func(config *ApplicationConfig) *ApplicationConfig {
-		config.Environment = env
-		return config
-	}
-}
+//
+//import (
+//	"dubbo.apache.org/dubbo-go/v3/config/applicationConfig"
+//	"dubbo.apache.org/dubbo-go/v3/config/center"
+//	"dubbo.apache.org/dubbo-go/v3/config/consumer"
+//	"dubbo.apache.org/dubbo-go/v3/config/method"
+//	"dubbo.apache.org/dubbo-go/v3/config/protocol"
+//	"dubbo.apache.org/dubbo-go/v3/config/provider"
+//	"dubbo.apache.org/dubbo-go/v3/config/reference"
+//	"dubbo.apache.org/dubbo-go/v3/config/registry"
+//	"dubbo.apache.org/dubbo-go/v3/config/service"
+//	"google.golang.org/grpc/balancer/base"
+//	"time"
+//)
+//
+////////////////////////////////////// default registry config
+//const (
+//	// defaultZKAddr is the default registry address of zookeeper
+//	defaultZKAddr = "127.0.0.1:2181"
+//
+//	// defaultNacosAddr is the default registry address of nacos
+//	defaultNacosAddr = "127.0.0.1:8848"
+//
+//	// defaultRegistryTimeout is the default registry timeout
+//	defaultRegistryTimeout = "3s"
+//)
+//
+//// NewDefaultRegistryConfig New default registry config
+//// the input @protocol can only be:
+//// "zookeeper" with default addr "127.0.0.1:2181"
+//// "nacos" with default addr "127.0.0.1:8848"
+//func NewDefaultRegistryConfig(protocol string) *registry.RegistryConfig {
+//	switch protocol {
+//	case "zookeeper":
+//		return &registry.RegistryConfig{
+//			Protocol:   protocol,
+//			Address:    defaultZKAddr,
+//			TimeoutStr: defaultRegistryTimeout,
+//		}
+//	case "nacos":
+//		return &registry.RegistryConfig{
+//			Protocol:   protocol,
+//			Address:    defaultNacosAddr,
+//			TimeoutStr: defaultRegistryTimeout,
+//		}
+//	default:
+//		return &registry.RegistryConfig{
+//			Protocol: protocol,
+//		}
+//	}
+//}
+//
+/////////////////////////////////////// registry config api
+//type RegistryConfigOpt func(config *registry.RegistryConfig) *registry.RegistryConfig
+//
+//// NewRegistryConfig creates New RegistryConfig with @opts
+//func NewRegistryConfig(opts ...RegistryConfigOpt) *registry.RegistryConfig {
+//	newRegistryConfig := NewDefaultRegistryConfig("")
+//	for _, v := range opts {
+//		newRegistryConfig = v(newRegistryConfig)
+//	}
+//	return newRegistryConfig
+//}
+//
+//// WithRegistryProtocol returns RegistryConfigOpt with given @regProtocol name
+//func WithRegistryProtocol(regProtocol string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Protocol = regProtocol
+//		return config
+//	}
+//}
+//
+//// WithRegistryAddress returns RegistryConfigOpt with given @addr registry address
+//func WithRegistryAddress(addr string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Address = addr
+//		return config
+//	}
+//}
+//
+//// WithRegistryTimeOut returns RegistryConfigOpt with given @timeout registry config
+//func WithRegistryTimeOut(timeout string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.TimeoutStr = timeout
+//		return config
+//	}
+//}
+//
+//// WithRegistryGroup returns RegistryConfigOpt with given @group registry group
+//func WithRegistryGroup(group string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Group = group
+//		return config
+//	}
+//}
+//
+//// WithRegistryTTL returns RegistryConfigOpt with given @ttl registry ttl
+//func WithRegistryTTL(ttl string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.TTL = ttl
+//		return config
+//	}
+//}
+//
+//// WithRegistryUserName returns RegistryConfigOpt with given @userName registry userName
+//func WithRegistryUserName(userName string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Username = userName
+//		return config
+//	}
+//}
+//
+//// WithRegistryPassword returns RegistryConfigOpt with given @psw registry password
+//func WithRegistryPassword(psw string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Password = psw
+//		return config
+//	}
+//}
+//
+//// WithRegistrySimplified returns RegistryConfigOpt with given @simplified registry simplified flag
+//func WithRegistrySimplified(simplified bool) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Simplified = simplified
+//		return config
+//	}
+//}
+//
+//// WithRegistryPreferred returns RegistryConfig with given @preferred registry preferred flag
+//func WithRegistryPreferred(preferred bool) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Preferred = preferred
+//		return config
+//	}
+//}
+//
+//// WithRegistryWeight returns RegistryConfigOpt with given @weight registry weight flag
+//func WithRegistryWeight(weight int64) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Weight = weight
+//		return config
+//	}
+//}
+//
+//// WithRegistryParams returns RegistryConfigOpt with given registry @params
+//func WithRegistryParams(params map[string]string) RegistryConfigOpt {
+//	return func(config *registry.RegistryConfig) *registry.RegistryConfig {
+//		config.Params = params
+//		return config
+//	}
+//}
+//
+/////////////////////////////////////// consumer config api
+//// ConsumerConfigOpt is the options to init ShutdownConfig
+//type ConsumerConfigOpt func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig
+//
+//// NewDefaultConsumerConfig returns default ShutdownConfig
+//// with connection timeout = 3s, request timeout = 3s
+//func NewDefaultConsumerConfig() *consumer.ShutdownConfig {
+//	check := true
+//	newConsumerConfig := &consumer.ShutdownConfig{
+//		BaseConfig:     base.ShutdownConfig{},
+//		Registries:     make(map[string]*registry.RegistryConfig, 8),
+//		References:     make(map[string]*reference.ReferenceConfig, 8),
+//		ConnectTimeout: 3 * time.Second,
+//		RequestTimeout: 3 * time.Second,
+//		Check:          &check,
+//	}
+//	return newConsumerConfig
+//}
+//
+//// NewConsumerConfig returns ShutdownConfig with @opts
+//func NewConsumerConfig(opts ...ConsumerConfigOpt) *consumer.ShutdownConfig {
+//	newConfig := NewDefaultConsumerConfig()
+//	for _, v := range opts {
+//		v(newConfig)
+//	}
+//	return newConfig
+//}
+//
+//// WithConsumerAppConfig returns ConsumerConfigOpt with given @appConfig
+//func WithConsumerAppConfig(appConfig *applicationConfig.ShutdownConfig) ConsumerConfigOpt {
+//	return func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig {
+//		config.ApplicationConfig = appConfig
+//		return config
+//	}
+//}
+//
+//// WithConsumerRegistryConfig returns ConsumerConfigOpt with given @registryKey and @regConfig
+//func WithConsumerRegistryConfig(registryKey string, regConfig *registry.RegistryConfig) ConsumerConfigOpt {
+//	return func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig {
+//		config.Registries[registryKey] = regConfig
+//		return config
+//	}
+//}
+//
+//// WithConsumerReferenceConfig returns ConsumerConfigOpt with
+//func WithConsumerReferenceConfig(referenceKey string, refConfig *reference.ReferenceConfig) ConsumerConfigOpt {
+//	return func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig {
+//		config.References[referenceKey] = refConfig
+//		return config
+//	}
+//}
+//
+//// WithConsumerConnTimeout returns ConsumerConfigOpt with given consumer conn @timeout
+//func WithConsumerConnTimeout(timeout time.Duration) ConsumerConfigOpt {
+//	return func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig {
+//		config.ConnectTimeout = timeout
+//		return config
+//	}
+//}
+//
+//// WithConsumerRequestTimeout returns ConsumerConfigOpt with given consumer request @timeout
+//func WithConsumerRequestTimeout(timeout time.Duration) ConsumerConfigOpt {
+//	return func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig {
+//		config.RequestTimeout = timeout
+//		return config
+//	}
+//}
+//
+//// WithConsumerConfigCenterConfig returns ConsumerConfigOpt with given @configCenterConfig
+//func WithConsumerConfigCenterConfig(configCenterConfig *center.ShutdownConfig) ConsumerConfigOpt {
+//	return func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig {
+//		config.ConfigCenterConfig = configCenterConfig
+//		return config
+//	}
+//}
+//
+//// WithConsumerConfigCheck returns ConsumerConfigOpt with given @check flag
+//func WithConsumerConfigCheck(check bool) ConsumerConfigOpt {
+//	return func(config *consumer.ShutdownConfig) *consumer.ShutdownConfig {
+//		*config.Check = check
+//		return config
+//	}
+//}
+//
+////////////////////////////////////// reference config api
+//// ReferenceConfigOpt is consumer's reference config
+//type ReferenceConfigOpt func(config *reference.ReferenceConfig) *reference.ReferenceConfig
+//
+//// NewDefaultReferenceConfig returns empty ReferenceConfig
+//func NewDefaultReferenceConfig() *reference.ReferenceConfig {
+//	newReferenceConfig := reference.NewReferenceConfig("")
+//	newReferenceConfig.Methods = make([]*method.MethodConfig, 0, 8)
+//	newReferenceConfig.Params = make(map[string]string, 8)
+//	return newReferenceConfig
+//}
+//
+//// NewReferenceConfigByAPI returns ReferenceConfig with given @opts
+//func NewReferenceConfigByAPI(opts ...ReferenceConfigOpt) *reference.ReferenceConfig {
+//	newReferenceConfig := NewDefaultReferenceConfig()
+//	for _, v := range opts {
+//		v(newReferenceConfig)
+//	}
+//	return newReferenceConfig
+//}
+//
+//// WithReferenceRegistry returns ReferenceConfigOpt with given registryKey: @registry
+//func WithReferenceRegistry(registry string) ReferenceConfigOpt {
+//	return func(config *reference.ReferenceConfig) *reference.ReferenceConfig {
+//		config.Registry = registry
+//		return config
+//	}
+//}
+//
+//// WithReferenceProtocol returns ReferenceConfigOpt with given protocolKey: @protocol
+//func WithReferenceProtocol(protocol string) ReferenceConfigOpt {
+//	return func(config *reference.ReferenceConfig) *reference.ReferenceConfig {
+//		config.Protocol = protocol
+//		return config
+//	}
+//}
+//
+//// WithReferenceInterface returns ReferenceConfigOpt with given @interfaceName
+//func WithReferenceInterface(interfaceName string) ReferenceConfigOpt {
+//	return func(config *reference.ReferenceConfig) *reference.ReferenceConfig {
+//		config.InterfaceName = interfaceName
+//		return config
+//	}
+//}
+//
+//// WithReferenceCluster returns ReferenceConfigOpt with given cluster name: @cluster
+//func WithReferenceCluster(cluster string) ReferenceConfigOpt {
+//	return func(config *reference.ReferenceConfig) *reference.ReferenceConfig {
+//		config.Cluster = cluster
+//		return config
+//	}
+//}
+//
+//// WithReferenceMethod returns ReferenceConfigOpt with given @method, @retries, and load balance: @lb
+//func WithReferenceMethod(methodName, retries, lb string) ReferenceConfigOpt {
+//	return func(config *reference.ReferenceConfig) *reference.ReferenceConfig {
+//		config.Methods = append(config.Methods, &method.MethodConfig{
+//			Name:        methodName,
+//			Retries:     retries,
+//			LoadBalance: lb,
+//		})
+//		return config
+//	}
+//}
+//
+/////////////////////////////////////// provider config api
+//// ProviderConfigOpt is the
+//type ProviderConfigOpt func(config *provider.ProviderConfig) *provider.ProviderConfig
+//
+//// NewDefaultProviderConfig returns ProviderConfig with default ShutdownConfig
+//func NewDefaultProviderConfig() *provider.ProviderConfig {
+//	newConsumerConfig := &provider.ProviderConfig{
+//		BaseConfig: base.ShutdownConfig{
+//			applicationConfig.ShutdownConfig: &applicationConfig.ShutdownConfig{
+//				Name:         "dubbo",
+//				Module:       "module",
+//				Organization: "dubbo_org",
+//				Owner:        "dubbo",
+//			},
+//		},
+//		Services:   make(map[string]*service.ShutdownConfig),
+//		Registries: make(map[string]*registry.RegistryConfig, 8),
+//		Protocols:  make(map[string]*protocol.ProtocolConfig, 8),
+//	}
+//	return newConsumerConfig
+//}
+//
+//// NewProviderConfig returns ProviderConfig with given @opts
+//func NewProviderConfig(opts ...ProviderConfigOpt) *provider.ProviderConfig {
+//	newConfig := NewDefaultProviderConfig()
+//	for _, v := range opts {
+//		v(newConfig)
+//	}
+//	return newConfig
+//}
+//
+//// WithProviderRegistryConfig returns ProviderConfigOpt with given registry config: @regConfig
+//func WithProviderRegistryConfig(regConfig *registry.RegistryConfig) ProviderConfigOpt {
+//	return func(config *provider.ProviderConfig) *provider.ProviderConfig {
+//		config.Registries[regConfig.Protocol] = regConfig
+//		return config
+//	}
+//}
+//
+//// WithProviderAppConfig returns ProviderConfigOpt with given @appConfig
+//func WithProviderAppConfig(appConfig *applicationConfig.ShutdownConfig) ProviderConfigOpt {
+//	return func(config *provider.ProviderConfig) *provider.ProviderConfig {
+//		config.ApplicationConfig = appConfig
+//		return config
+//	}
+//}
+//
+//// WithProviderServices returns ProviderConfig with given serviceNameKey @serviceName and @serviceConfig
+//func WithProviderServices(serviceName string, serviceConfig *service.ShutdownConfig) ProviderConfigOpt {
+//	return func(config *provider.ProviderConfig) *provider.ProviderConfig {
+//		config.Services[serviceName] = serviceConfig
+//		return config
+//	}
+//}
+//
+//// WithProviderProtocol returns ProviderConfigOpt with given @protocolKey, protocolName @protocol and @port
+//func WithProviderProtocol(protocolKey, protocol, port string) ProviderConfigOpt {
+//	return func(config *provider.ProviderConfig) *provider.ProviderConfig {
+//		config.Protocols[protocolKey] = &protocol.ProtocolConfig{
+//			Name: protocol,
+//			Port: port,
+//		}
+//		return config
+//	}
+//}
+//
+//// WithProviderRegistry returns ProviderConfigOpt with given @registryKey and registry @registryConfig
+//func WithProviderRegistry(registryKey string, registryConfig *registry.RegistryConfig) ProviderConfigOpt {
+//	return func(config *provider.ProviderConfig) *provider.ProviderConfig {
+//		config.Registries[registryKey] = registryConfig
+//		return config
+//	}
+//}
+//
+///////////////////////////////////////// service config api
+//// ServiceConfigOpt is the option to init ShutdownConfig
+//type ServiceConfigOpt func(config *service.ShutdownConfig) *service.ShutdownConfig
+//
+//// NewDefaultServiceConfig returns default ShutdownConfig
+//func NewDefaultServiceConfig() *service.ShutdownConfig {
+//	newServiceConfig := service.NewServiceConfig("")
+//	newServiceConfig.Params = make(map[string]string)
+//	newServiceConfig.Methods = make([]*method.MethodConfig, 0, 8)
+//	return newServiceConfig
+//}
+//
+//// NewServiceConfigByAPI is named as api, because there is NewServiceConfig func already declared
+//// NewServiceConfigByAPI returns ShutdownConfig with given @opts
+//func NewServiceConfigByAPI(opts ...ServiceConfigOpt) *service.ShutdownConfig {
+//	defaultServiceConfig := NewDefaultServiceConfig()
+//	for _, v := range opts {
+//		v(defaultServiceConfig)
+//	}
+//	return defaultServiceConfig
+//}
+//
+//// WithServiceRegistry returns ServiceConfigOpt with given registryKey @registry
+//func WithServiceRegistry(registry string) ServiceConfigOpt {
+//	return func(config *service.ShutdownConfig) *service.ShutdownConfig {
+//		config.Registry = registry
+//		return config
+//	}
+//}
+//
+//// WithServiceProtocol returns ServiceConfigOpt with given protocolKey @protocol
+//func WithServiceProtocol(protocol string) ServiceConfigOpt {
+//	return func(config *service.ShutdownConfig) *service.ShutdownConfig {
+//		config.Protocol = protocol
+//		return config
+//	}
+//}
+//
+//// WithServiceInterface returns ServiceConfigOpt with given @interfaceName
+//func WithServiceInterface(interfaceName string) ServiceConfigOpt {
+//	return func(config *service.ShutdownConfig) *service.ShutdownConfig {
+//		config.InterfaceName = interfaceName
+//		return config
+//	}
+//}
+//
+//// WithServiceLoadBalance returns ServiceConfigOpt with given load balance @lb
+//func WithServiceLoadBalance(lb string) ServiceConfigOpt {
+//	return func(config *service.ShutdownConfig) *service.ShutdownConfig {
+//		config.Loadbalance = lb
+//		return config
+//	}
+//}
+//
+//// WithServiceWarmUpTime returns ServiceConfigOpt with given @warmUp time
+//func WithServiceWarmUpTime(warmUp string) ServiceConfigOpt {
+//	return func(config *service.ShutdownConfig) *service.ShutdownConfig {
+//		config.Warmup = warmUp
+//		return config
+//	}
+//}
+//
+//// WithServiceCluster returns ServiceConfigOpt with given cluster name @cluster
+//func WithServiceCluster(cluster string) ServiceConfigOpt {
+//	return func(config *service.ShutdownConfig) *service.ShutdownConfig {
+//		config.Cluster = cluster
+//		return config
+//	}
+//}
+//
+//// WithServiceMethod returns ServiceConfigOpt with given @name, @retries and load balance @lb
+//func WithServiceMethod(name, retries, lb string) ServiceConfigOpt {
+//	return func(config *service.ShutdownConfig) *service.ShutdownConfig {
+//		config.Methods = append(config.Methods, &method.MethodConfig{
+//			Name:        name,
+//			Retries:     retries,
+//			LoadBalance: lb,
+//		})
+//		return config
+//	}
+//}
+//
+/////////////////////////////////////////// Application config api
+//// ApplicationConfigOpt is option to init ShutdownConfig
+//type ApplicationConfigOpt func(config *applicationConfig.ShutdownConfig) *applicationConfig.ShutdownConfig
+//
+//// NewDefaultApplicationConfig returns ShutdownConfig with default
+//// name: dubbo.io
+//// module: sample
+//// organization: dubbo.io
+//// owner: dubbogo
+//// version: 0.0.1
+//// environment dev
+//func NewDefaultApplicationConfig() *applicationConfig.ShutdownConfig {
+//	newAppConfig := &applicationConfig.ShutdownConfig{
+//		Name:         "dubbo.io",
+//		Module:       "sample",
+//		Organization: "dubbo.io",
+//		Owner:        "dubbogo",
+//		Version:      "0.0.1",
+//		Environment:  "dev",
+//	}
+//	return newAppConfig
+//}
+//
+//// NewApplicationConfig is named as api, because there is NewServiceConfig func already declared
+//// NewApplicationConfig returns ShutdownConfig with default applicationConfig config
+//func NewApplicationConfig(opts ...ApplicationConfigOpt) *applicationConfig.ShutdownConfig {
+//	defaultServiceConfig := NewDefaultApplicationConfig()
+//	for _, v := range opts {
+//		v(defaultServiceConfig)
+//	}
+//	return defaultServiceConfig
+//}
+//
+//// WithAppName returns ApplicationConfigOpt with given @name
+//func WithAppName(name string) ApplicationConfigOpt {
+//	return func(config *applicationConfig.ShutdownConfig) *applicationConfig.ShutdownConfig {
+//		config.Name = name
+//		return config
+//	}
+//}
+//
+//// WithAppModule returns ApplicationConfigOpt with given @module
+//func WithAppModule(module string) ApplicationConfigOpt {
+//	return func(config *applicationConfig.ShutdownConfig) *applicationConfig.ShutdownConfig {
+//		config.Module = module
+//		return config
+//	}
+//}
+//
+//// WithAppOrganization returns ApplicationConfigOpt wight given organization @org
+//func WithAppOrganization(org string) ApplicationConfigOpt {
+//	return func(config *applicationConfig.ShutdownConfig) *applicationConfig.ShutdownConfig {
+//		config.Organization = org
+//		return config
+//	}
+//}
+//
+//// WithAppOwner returns ApplicationConfigOpt with given @owner
+//func WithAppOwner(owner string) ApplicationConfigOpt {
+//	return func(config *applicationConfig.ShutdownConfig) *applicationConfig.ShutdownConfig {
+//		config.Owner = owner
+//		return config
+//	}
+//}
+//
+//// WithAppVersion returns ApplicationConfigOpt with given version @version
+//func WithAppVersion(version string) ApplicationConfigOpt {
+//	return func(config *applicationConfig.ShutdownConfig) *applicationConfig.ShutdownConfig {
+//		config.Version = version
+//		return config
+//	}
+//}
+//
+//// WithAppEnvironment returns ApplicationConfigOpt with given environment @env
+//func WithAppEnvironment(env string) ApplicationConfigOpt {
+//	return func(config *applicationConfig.ShutdownConfig) *applicationConfig.ShutdownConfig {
+//		config.Environment = env
+//		return config
+//	}
+//}
diff --git a/config/config_api_test.go b/config/config_api_test.go
index aa70a60..65899ed 100644
--- a/config/config_api_test.go
+++ b/config/config_api_test.go
@@ -17,149 +17,140 @@
 
 package config
 
-import (
-	"strconv"
-	"testing"
-	"time"
-)
-
-import (
-	"github.com/stretchr/testify/assert"
-)
-
-func TestNewDefaultServiceConfig(t *testing.T) {
-	serviceConfig := NewServiceConfigByAPI(
-		WithServiceCluster("test-cluster"),
-		WithServiceInterface("test-interface"),
-		WithServiceLoadBalance("test-loadbalance"),
-		WithServiceMethod("test-method1", "test-retries1", "test-lb1"),
-		WithServiceMethod("test-method2", "test-retries2", "test-lb2"),
-		WithServiceMethod("test-method3", "test-retries3", "test-lb3"),
-		WithServiceProtocol("test-protocol"),
-		WithServiceRegistry("test-registry"),
-		WithServiceWarmUpTime("test-warmup"),
-	)
-	assert.Equal(t, serviceConfig.Cluster, "test-cluster")
-	assert.Equal(t, serviceConfig.InterfaceName, "test-interface")
-	assert.Equal(t, serviceConfig.Loadbalance, "test-loadbalance")
-	for i, v := range serviceConfig.Methods {
-		backFix := strconv.Itoa(i + 1)
-		assert.Equal(t, v.Name, "test-method"+backFix)
-		assert.Equal(t, v.Retries, "test-retries"+backFix)
-		assert.Equal(t, v.LoadBalance, "test-lb"+backFix)
-	}
-	assert.Equal(t, serviceConfig.Protocol, "test-protocol")
-	assert.Equal(t, serviceConfig.Registry, "test-registry")
-	assert.Equal(t, serviceConfig.Warmup, "test-warmup")
-}
-
-func TestNewReferenceConfigByAPI(t *testing.T) {
-	refConfig := NewReferenceConfigByAPI(
-		WithReferenceCluster("test-cluster"),
-		WithReferenceInterface("test-interface"),
-		WithReferenceMethod("test-method1", "test-retries1", "test-lb1"),
-		WithReferenceMethod("test-method2", "test-retries2", "test-lb2"),
-		WithReferenceMethod("test-method3", "test-retries3", "test-lb3"),
-		WithReferenceProtocol("test-protocol"),
-		WithReferenceRegistry("test-registry"),
-	)
-	assert.Equal(t, refConfig.Cluster, "test-cluster")
-	assert.Equal(t, refConfig.InterfaceName, "test-interface")
-	for i, v := range refConfig.Methods {
-		backFix := strconv.Itoa(i + 1)
-		assert.Equal(t, v.Name, "test-method"+backFix)
-		assert.Equal(t, v.Retries, "test-retries"+backFix)
-		assert.Equal(t, v.LoadBalance, "test-lb"+backFix)
-	}
-	assert.Equal(t, refConfig.Protocol, "test-protocol")
-	assert.Equal(t, refConfig.Registry, "test-registry")
-}
-
-func TestNewRegistryConfig(t *testing.T) {
-	regConfig := NewRegistryConfig(
-		WithRegistryTimeOut("test-timeout"),
-		WithRegistryProtocol("test-protocol"),
-		WithRegistryGroup("test-group"),
-		WithRegistryAddress("test-address"),
-		WithRegistrySimplified(true),
-		WithRegistryUserName("test-username"),
-		WithRegistryPassword("test-password"),
-	)
-	assert.Equal(t, regConfig.TimeoutStr, "test-timeout")
-	assert.Equal(t, regConfig.Protocol, "test-protocol")
-	assert.Equal(t, regConfig.Group, "test-group")
-	assert.Equal(t, regConfig.Address, "test-address")
-	assert.Equal(t, regConfig.Simplified, true)
-	assert.Equal(t, regConfig.Username, "test-username")
-	assert.Equal(t, regConfig.Password, "test-password")
-}
-
-func TestNewConsumerConfig(t *testing.T) {
-	referConfig := NewReferenceConfigByAPI(
-		WithReferenceCluster("test-cluster"),
-		WithReferenceInterface("test-interface"),
-		WithReferenceMethod("test-method1", "test-retries1", "test-lb1"),
-		WithReferenceMethod("test-method2", "test-retries2", "test-lb2"),
-		WithReferenceMethod("test-method3", "test-retries3", "test-lb3"),
-		WithReferenceProtocol("test-protocol"),
-		WithReferenceRegistry("test-registry"),
-	)
-	defaultZKRegistry := NewDefaultRegistryConfig("zookeeper")
-	assert.Equal(t, defaultZKRegistry.Address, defaultZKAddr)
-	assert.Equal(t, defaultZKRegistry.Protocol, "zookeeper")
-	assert.Equal(t, defaultZKRegistry.TimeoutStr, defaultRegistryTimeout)
-
-	testConsumerConfig := NewConsumerConfig(
-		WithConsumerConfigCheck(true),
-		WithConsumerConnTimeout(time.Minute),
-		WithConsumerRequestTimeout(time.Hour),
-		WithConsumerReferenceConfig("UserProvider", referConfig),
-		WithConsumerRegistryConfig("demoZK", defaultZKRegistry),
-	)
-
-	assert.Equal(t, *testConsumerConfig.Check, true)
-	assert.Equal(t, testConsumerConfig.ConnectTimeout, time.Minute)
-	assert.Equal(t, testConsumerConfig.RequestTimeout, time.Hour)
-	assert.Equal(t, testConsumerConfig.Registries["demoZK"], defaultZKRegistry)
-	assert.Equal(t, testConsumerConfig.References["UserProvider"], referConfig)
-}
-
-// TestNewProviderConfig test NewProviderConfig api
-func TestNewProviderConfig(t *testing.T) {
-	serviceConfig := NewServiceConfigByAPI(
-		WithServiceCluster("test-cluster"),
-		WithServiceInterface("test-interface"),
-		WithServiceLoadBalance("test-loadbalance"),
-		WithServiceMethod("test-method1", "test-retries1", "test-lb1"),
-		WithServiceMethod("test-method2", "test-retries2", "test-lb2"),
-		WithServiceMethod("test-method3", "test-retries3", "test-lb3"),
-		WithServiceProtocol("test-protocol"),
-		WithServiceRegistry("test-registry"),
-		WithServiceWarmUpTime("test-warmup"),
-	)
-
-	defaultNacosRegistry := NewDefaultRegistryConfig("nacos")
-	assert.Equal(t, defaultNacosRegistry.Address, defaultNacosAddr)
-	assert.Equal(t, defaultNacosRegistry.Protocol, "nacos")
-	assert.Equal(t, defaultNacosRegistry.TimeoutStr, defaultRegistryTimeout)
-
-	testProviderConfig := NewProviderConfig(
-		WithProviderServices("UserProvider", serviceConfig),
-		WithProviderProtocol("dubbo", "dubbo", "20000"),
-		WithProviderRegistry("demoNacos", defaultNacosRegistry),
-	)
-
-	assert.NotNil(t, testProviderConfig.Services)
-	for k, v := range testProviderConfig.Services {
-		assert.Equal(t, k, "UserProvider")
-		assert.Equal(t, v, serviceConfig)
-	}
-	assert.NotNil(t, testProviderConfig.Registries)
-
-	if registry, ok := testProviderConfig.Registries["demoNacos"]; ok {
-		assert.Equal(t, registry, defaultNacosRegistry)
-	}
-	assert.NotNil(t, testProviderConfig.Protocols)
-	assert.Equal(t, testProviderConfig.Protocols["dubbo"].Name, "dubbo")
-	assert.Equal(t, testProviderConfig.Protocols["dubbo"].Port, "20000")
-}
+//
+//func TestNewDefaultServiceConfig(t *testing.T) {
+//	serviceConfig := NewServiceConfigByAPI(
+//		WithServiceCluster("test-cluster"),
+//		WithServiceInterface("test-interface"),
+//		WithServiceLoadBalance("test-loadbalance"),
+//		WithServiceMethod("test-method1", "test-retries1", "test-lb1"),
+//		WithServiceMethod("test-method2", "test-retries2", "test-lb2"),
+//		WithServiceMethod("test-method3", "test-retries3", "test-lb3"),
+//		WithServiceProtocol("test-protocol"),
+//		WithServiceRegistry("test-registry"),
+//		WithServiceWarmUpTime("test-warmup"),
+//	)
+//	assert.Equal(t, serviceConfig.Cluster, "test-cluster")
+//	assert.Equal(t, serviceConfig.InterfaceName, "test-interface")
+//	assert.Equal(t, serviceConfig.Loadbalance, "test-loadbalance")
+//	for i, v := range serviceConfig.Methods {
+//		backFix := strconv.Itoa(i + 1)
+//		assert.Equal(t, v.Name, "test-method"+backFix)
+//		assert.Equal(t, v.Retries, "test-retries"+backFix)
+//		assert.Equal(t, v.LoadBalance, "test-lb"+backFix)
+//	}
+//	assert.Equal(t, serviceConfig.Protocol, "test-protocol")
+//	assert.Equal(t, serviceConfig.Registry, "test-registry")
+//	assert.Equal(t, serviceConfig.Warmup, "test-warmup")
+//}
+//
+//func TestNewReferenceConfigByAPI(t *testing.T) {
+//	refConfig := NewReferenceConfigByAPI(
+//		WithReferenceCluster("test-cluster"),
+//		WithReferenceInterface("test-interface"),
+//		WithReferenceMethod("test-method1", "test-retries1", "test-lb1"),
+//		WithReferenceMethod("test-method2", "test-retries2", "test-lb2"),
+//		WithReferenceMethod("test-method3", "test-retries3", "test-lb3"),
+//		WithReferenceProtocol("test-protocol"),
+//		WithReferenceRegistry("test-registry"),
+//	)
+//	assert.Equal(t, refConfig.Cluster, "test-cluster")
+//	assert.Equal(t, refConfig.InterfaceName, "test-interface")
+//	for i, v := range refConfig.Methods {
+//		backFix := strconv.Itoa(i + 1)
+//		assert.Equal(t, v.Name, "test-method"+backFix)
+//		assert.Equal(t, v.Retries, "test-retries"+backFix)
+//		assert.Equal(t, v.LoadBalance, "test-lb"+backFix)
+//	}
+//	assert.Equal(t, refConfig.Protocol, "test-protocol")
+//	assert.Equal(t, refConfig.Registry, "test-registry")
+//}
+//
+//func TestNewRegistryConfig(t *testing.T) {
+//	regConfig := NewRegistryConfig(
+//		WithRegistryTimeOut("test-timeout"),
+//		WithRegistryProtocol("test-protocol"),
+//		WithRegistryGroup("test-group"),
+//		WithRegistryAddress("test-address"),
+//		WithRegistrySimplified(true),
+//		WithRegistryUserName("test-username"),
+//		WithRegistryPassword("test-password"),
+//	)
+//	assert.Equal(t, regConfig.TimeoutStr, "test-timeout")
+//	assert.Equal(t, regConfig.Protocol, "test-protocol")
+//	assert.Equal(t, regConfig.Group, "test-group")
+//	assert.Equal(t, regConfig.Address, "test-address")
+//	assert.Equal(t, regConfig.Simplified, true)
+//	assert.Equal(t, regConfig.Username, "test-username")
+//	assert.Equal(t, regConfig.Password, "test-password")
+//}
+//
+//func TestNewConsumerConfig(t *testing.T) {
+//	referConfig := NewReferenceConfigByAPI(
+//		WithReferenceCluster("test-cluster"),
+//		WithReferenceInterface("test-interface"),
+//		WithReferenceMethod("test-method1", "test-retries1", "test-lb1"),
+//		WithReferenceMethod("test-method2", "test-retries2", "test-lb2"),
+//		WithReferenceMethod("test-method3", "test-retries3", "test-lb3"),
+//		WithReferenceProtocol("test-protocol"),
+//		WithReferenceRegistry("test-registry"),
+//	)
+//	defaultZKRegistry := NewDefaultRegistryConfig("zookeeper")
+//	assert.Equal(t, defaultZKRegistry.Address, defaultZKAddr)
+//	assert.Equal(t, defaultZKRegistry.Protocol, "zookeeper")
+//	assert.Equal(t, defaultZKRegistry.TimeoutStr, defaultRegistryTimeout)
+//
+//	testConsumerConfig := NewConsumerConfig(
+//		WithConsumerConfigCheck(true),
+//		WithConsumerConnTimeout(time.Minute),
+//		WithConsumerRequestTimeout(time.Hour),
+//		WithConsumerReferenceConfig("UserProvider", referConfig),
+//		WithConsumerRegistryConfig("demoZK", defaultZKRegistry),
+//	)
+//
+//	assert.Equal(t, *testConsumerConfig.Check, true)
+//	assert.Equal(t, testConsumerConfig.ConnectTimeout, time.Minute)
+//	assert.Equal(t, testConsumerConfig.RequestTimeout, time.Hour)
+//	assert.Equal(t, testConsumerConfig.Registries["demoZK"], defaultZKRegistry)
+//	assert.Equal(t, testConsumerConfig.References["UserProvider"], referConfig)
+//}
+//
+//// TestNewProviderConfig test NewProviderConfig api
+//func TestNewProviderConfig(t *testing.T) {
+//	serviceConfig := NewServiceConfigByAPI(
+//		WithServiceCluster("test-cluster"),
+//		WithServiceInterface("test-interface"),
+//		WithServiceLoadBalance("test-loadbalance"),
+//		WithServiceMethod("test-method1", "test-retries1", "test-lb1"),
+//		WithServiceMethod("test-method2", "test-retries2", "test-lb2"),
+//		WithServiceMethod("test-method3", "test-retries3", "test-lb3"),
+//		WithServiceProtocol("test-protocol"),
+//		WithServiceRegistry("test-registry"),
+//		WithServiceWarmUpTime("test-warmup"),
+//	)
+//
+//	defaultNacosRegistry := NewDefaultRegistryConfig("nacos")
+//	assert.Equal(t, defaultNacosRegistry.Address, defaultNacosAddr)
+//	assert.Equal(t, defaultNacosRegistry.Protocol, "nacos")
+//	assert.Equal(t, defaultNacosRegistry.TimeoutStr, defaultRegistryTimeout)
+//
+//	testProviderConfig := NewProviderConfig(
+//		WithProviderServices("UserProvider", serviceConfig),
+//		WithProviderProtocol("dubbo", "dubbo", "20000"),
+//		WithProviderRegistry("demoNacos", defaultNacosRegistry),
+//	)
+//
+//	assert.NotNil(t, testProviderConfig.Services)
+//	for k, v := range testProviderConfig.Services {
+//		assert.Equal(t, k, "UserProvider")
+//		assert.Equal(t, v, serviceConfig)
+//	}
+//	assert.NotNil(t, testProviderConfig.Registries)
+//
+//	if registry, ok := testProviderConfig.Registries["demoNacos"]; ok {
+//		assert.Equal(t, registry, defaultNacosRegistry)
+//	}
+//	assert.NotNil(t, testProviderConfig.Protocols)
+//	assert.Equal(t, testProviderConfig.Protocols["dubbo"].Name, "dubbo")
+//	assert.Equal(t, testProviderConfig.Protocols["dubbo"].Port, "20000")
+//}
diff --git a/config/config_center_config.go b/config/config_center_config.go
index 360818c..d3c1976 100644
--- a/config/config_center_config.go
+++ b/config/config_center_config.go
@@ -19,58 +19,70 @@ package config
 
 import (
 	"net/url"
-	"reflect"
+	"strings"
 )
 
 import (
 	"github.com/creasty/defaults"
-	perrors "github.com/pkg/errors"
+	"github.com/pkg/errors"
 )
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/common"
-	"dubbo.apache.org/dubbo-go/v3/common/config"
+	conf "dubbo.apache.org/dubbo-go/v3/common/config"
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 )
 
-// ConfigCenterConfig is configuration for config center
+// CenterConfig is configuration for config center
 //
 // ConfigCenter also introduced concepts of namespace and group to better manage Key-Value pairs by group,
 // those configs are already built-in in many professional third-party configuration centers.
 // In most cases, namespace is used to isolate different tenants, while group is used to divide the key set from one tenant into groups.
 //
-// ConfigCenter has currently supported Zookeeper, Nacos, Etcd, Consul, Apollo
-type ConfigCenterConfig struct {
-	Protocol      string            `required:"true"  yaml:"protocol"  json:"protocol,omitempty"`
-	Address       string            `yaml:"address" json:"address,omitempty"`
-	Cluster       string            `yaml:"cluster" json:"cluster,omitempty"`
-	Group         string            `default:"dubbo" yaml:"group" json:"group,omitempty"`
-	Username      string            `yaml:"username" json:"username,omitempty"`
-	Password      string            `yaml:"password" json:"password,omitempty"`
-	LogDir        string            `yaml:"log_dir" json:"log_dir,omitempty"`
-	ConfigFile    string            `default:"dubbo.properties" yaml:"config_file"  json:"config_file,omitempty"`
-	Namespace     string            `default:"dubbo" yaml:"namespace"  json:"namespace,omitempty"`
-	AppConfigFile string            `default:"dubbo.properties" yaml:"app_config_file"  json:"app_config_file,omitempty"`
-	AppID         string            `default:"dubbo" yaml:"app_id"  json:"app_id,omitempty"`
-	TimeoutStr    string            `yaml:"timeout"  json:"timeout,omitempty"`
-	RemoteRef     string            `required:"false"  yaml:"remote_ref"  json:"remote_ref,omitempty"`
-	Params        map[string]string `yaml:"params"  json:"parameters,omitempty"`
+// CenterConfig has currently supported Zookeeper, Nacos, Etcd, Consul, Apollo
+type CenterConfig struct {
+	Protocol      string `yaml:"protocol"  json:"protocol,omitempty"`
+	Address       string `yaml:"address" json:"address,omitempty"`
+	Cluster       string `yaml:"cluster" json:"cluster,omitempty"`
+	Group         string `default:"dubbo" yaml:"group" json:"group,omitempty"`
+	Username      string `yaml:"username" json:"username,omitempty"`
+	Password      string `yaml:"password" json:"password,omitempty"`
+	LogDir        string `yaml:"log-dir" json:"log-dir,omitempty"`
+	ConfigFile    string `default:"dubbo.properties" yaml:"config-file"  json:"config-file,omitempty"`
+	Namespace     string `default:"dubbo" yaml:"namespace"  json:"namespace,omitempty"`
+	AppConfigFile string `default:"dubbo.properties" yaml:"app-config-file"  json:"app-config-file,omitempty"`
+	AppID         string `default:"dubbo" yaml:"app-id"  json:"app-id,omitempty"`
+	Timeout       string `default:"10s" yaml:"timeout"  json:"timeout,omitempty"`
+	// Deprecated
+	RemoteRef string            `required:"false"  yaml:"remote-ref"  json:"remote-ref,omitempty"`
+	Params    map[string]string `yaml:"params"  json:"parameters,omitempty"`
 }
 
-// UnmarshalYAML unmarshals the ConfigCenterConfig by @unmarshal function
-func (c *ConfigCenterConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+func (c *CenterConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(c)
+	c.translateConfigAddress()
+	return verify(c)
+}
+
+func (c *CenterConfig) Validate() {
+	// todo set default application
+}
+
+// UnmarshalYAML unmarshal the ConfigCenterConfig by @unmarshal function
+func (c *CenterConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	if err := defaults.Set(c); err != nil {
 		return err
 	}
-	type plain ConfigCenterConfig
+	type plain CenterConfig
 	return unmarshal((*plain)(c))
 }
 
 // GetUrlMap gets url map from ConfigCenterConfig
-func (c *ConfigCenterConfig) GetUrlMap() url.Values {
+func (c *CenterConfig) GetUrlMap() url.Values {
 	urlMap := url.Values{}
 	urlMap.Set(constant.CONFIG_NAMESPACE_KEY, c.Namespace)
 	urlMap.Set(constant.CONFIG_GROUP_KEY, c.Group)
@@ -79,7 +91,7 @@ func (c *ConfigCenterConfig) GetUrlMap() url.Values {
 	urlMap.Set(constant.CONFIG_LOG_DIR_KEY, c.LogDir)
 	urlMap.Set(constant.CONFIG_USERNAME_KEY, c.Username)
 	urlMap.Set(constant.CONFIG_PASSWORD_KEY, c.Password)
-	urlMap.Set(constant.CONFIG_TIMEOUT_KEY, c.TimeoutStr)
+	urlMap.Set(constant.CONFIG_TIMEOUT_KEY, c.Timeout)
 
 	for key, val := range c.Params {
 		urlMap.Set(key, val)
@@ -87,94 +99,107 @@ func (c *ConfigCenterConfig) GetUrlMap() url.Values {
 	return urlMap
 }
 
-type configCenter struct{}
-
-// toURL will compatible with baseConfig.ConfigCenterConfig.Address and baseConfig.ConfigCenterConfig.RemoteRef before 1.6.0
-// After 1.6.0 will not compatible, only baseConfig.ConfigCenterConfig.RemoteRef
-func (b *configCenter) toURL(baseConfig BaseConfig) (*common.URL, error) {
-	remoteRef := baseConfig.ConfigCenterConfig.RemoteRef
-	// if set remote ref use remote
-	if len(remoteRef) <= 0 {
-		return common.NewURL(baseConfig.ConfigCenterConfig.Address,
-			common.WithProtocol(baseConfig.ConfigCenterConfig.Protocol),
-			common.WithParams(baseConfig.ConfigCenterConfig.GetUrlMap()))
-	}
-	rc, ok := baseConfig.GetRemoteConfig(remoteRef)
-	if !ok {
-		return nil, perrors.New("Could not find out the remote ref config, name: " + remoteRef)
-	}
-	// set protocol if remote not set
-	if len(rc.Protocol) <= 0 {
-		rc.Protocol = baseConfig.ConfigCenterConfig.Protocol
+//translateConfigAddress translate config address
+//  eg:address=nacos://127.0.0.1:8848 will return 127.0.0.1:8848 and protocol will set nacos
+func (c *CenterConfig) translateConfigAddress() string {
+	if strings.Contains(c.Address, "://") {
+		translatedUrl, err := url.Parse(c.Address)
+		if err != nil {
+			logger.Errorf("The config address:%s is invalid, error: %#v", c.Address, err)
+			panic(err)
+		}
+		c.Protocol = translatedUrl.Scheme
+		c.Address = strings.Replace(c.Address, translatedUrl.Scheme+"://", "", -1)
 	}
-	newURL, err := rc.ToURL()
-	return newURL, err
+	return c.Address
+}
+
+// toURL will compatible with baseConfig.ShutdownConfig.Address and baseConfig.ShutdownConfig.RemoteRef before 1.6.0
+// After 1.6.0 will not compatible, only baseConfig.ShutdownConfig.RemoteRef
+func (c *CenterConfig) toURL() (*common.URL, error) {
+	//remoteRef := baseConfig.ConfigCenterConfig.RemoteRef
+	//// if set remote ref use remote
+	//if len(remoteRef) <= 0 {
+	//	return common.NewURL(baseConfig.ConfigCenterConfig.Address,
+	//		common.WithProtocol(baseConfig.ConfigCenterConfig.Protocol),
+	//		common.WithParams(baseConfig.ConfigCenterConfig.GetUrlMap()))
+	//}
+	//rc, ok := baseConfig.GetRemoteConfig(remoteRef)
+	//if !ok {
+	//	return nil, perrors.New("Could not find out the remote ref config, name: " + remoteRef)
+	//}
+	//// set protocol if remote not set
+	//if len(rc.Protocol) <= 0 {
+	//	rc.Protocol = baseConfig.ConfigCenterConfig.Protocol
+	//}
+	return common.NewURL(c.Address,
+		common.WithProtocol(c.Protocol),
+		common.WithParams(c.GetUrlMap()))
 }
 
 // startConfigCenter will start the config center.
 // it will prepare the environment
-func (b *configCenter) startConfigCenter(baseConfig BaseConfig) error {
-	newUrl, err := b.toURL(baseConfig)
+func (c *CenterConfig) startConfigCenter() error {
+	newUrl, err := c.toURL()
 	if err != nil {
 		return err
 	}
-	if err = b.prepareEnvironment(baseConfig, newUrl); err != nil {
-		return perrors.WithMessagef(err, "start config center error!")
+	if err = c.prepareEnvironment(newUrl); err != nil {
+		return errors.WithMessagef(err, "start config center error!")
 	}
 	// c.fresh()
 	return nil
 }
 
-func (b *configCenter) prepareEnvironment(baseConfig BaseConfig, configCenterUrl *common.URL) error {
+func (c *CenterConfig) prepareEnvironment(configCenterUrl *common.URL) error {
 	factory := extension.GetConfigCenterFactory(configCenterUrl.Protocol)
 	dynamicConfig, err := factory.GetDynamicConfiguration(configCenterUrl)
 	if err != nil {
 		logger.Errorf("Get dynamic configuration error , error message is %v", err)
-		return perrors.WithStack(err)
+		return errors.WithStack(err)
 	}
-	envInstance := config.GetEnvInstance()
+	envInstance := conf.GetEnvInstance()
 	envInstance.SetDynamicConfiguration(dynamicConfig)
-	content, err := dynamicConfig.GetProperties(baseConfig.ConfigCenterConfig.ConfigFile,
-		config_center.WithGroup(baseConfig.ConfigCenterConfig.Group))
+	_, err = dynamicConfig.GetProperties(c.ConfigFile, config_center.WithGroup(c.Group))
 	if err != nil {
 		logger.Errorf("Get config content in dynamic configuration error , error message is %v", err)
-		return perrors.WithStack(err)
-	}
-	var appGroup string
-	var appContent string
-	if providerConfig != nil && providerConfig.ApplicationConfig != nil &&
-		reflect.ValueOf(baseConfig.fatherConfig).Elem().Type().Name() == "ProviderConfig" {
-		appGroup = providerConfig.ApplicationConfig.Name
-	} else if consumerConfig != nil && consumerConfig.ApplicationConfig != nil &&
-		reflect.ValueOf(baseConfig.fatherConfig).Elem().Type().Name() == "ConsumerConfig" {
-		appGroup = consumerConfig.ApplicationConfig.Name
-	}
-
-	if len(appGroup) != 0 {
-		configFile := baseConfig.ConfigCenterConfig.AppConfigFile
-		if len(configFile) == 0 {
-			configFile = baseConfig.ConfigCenterConfig.ConfigFile
-		}
-		appContent, err = dynamicConfig.GetProperties(configFile, config_center.WithGroup(appGroup))
-		if err != nil {
-			return perrors.WithStack(err)
-		}
-	}
-	// global config file
-	mapContent, err := dynamicConfig.Parser().Parse(content)
-	if err != nil {
-		return perrors.WithStack(err)
-	}
-	envInstance.UpdateExternalConfigMap(mapContent)
-
-	// appGroup config file
-	if len(appContent) != 0 {
-		appMapContent, err := dynamicConfig.Parser().Parse(appContent)
-		if err != nil {
-			return perrors.WithStack(err)
-		}
-		envInstance.UpdateAppExternalConfigMap(appMapContent)
+		return errors.WithStack(err)
 	}
+	//var appGroup string
+	//var appContent string
+	//if config2.providerConfig != nil && config2.providerConfig.ApplicationConfig != nil &&
+	//	reflect.ValueOf(baseConfig.fatherConfig).Elem().Type().Name() == "ProviderConfig" {
+	//	appGroup = config2.providerConfig.ApplicationConfig.Name
+	//} else if config2.consumerConfig != nil && config2.consumerConfig.ApplicationConfig != nil &&
+	//	reflect.ValueOf(baseConfig.fatherConfig).Elem().Type().Name() == "ConsumerConfig" {
+	//	appGroup = config2.consumerConfig.ApplicationConfig.Name
+	//}
+	//
+	//if len(appGroup) != 0 {
+	//	configFile := baseConfig.ConfigCenterConfig.AppConfigFile
+	//	if len(configFile) == 0 {
+	//		configFile = baseConfig.ConfigCenterConfig.ConfigFile
+	//	}
+	//	appContent, err = dynamicConfig.GetProperties(configFile, config_center.WithGroup(appGroup))
+	//	if err != nil {
+	//		return perrors.WithStack(err)
+	//	}
+	//}
+	//// global config file
+	//mapContent, err := dynamicConfig.Parser().Parse(content)
+	//if err != nil {
+	//	return perrors.WithStack(err)
+	//}
+	//envInstance.UpdateExternalConfigMap(mapContent)
+	//
+	//// appGroup config file
+	//if len(appContent) != 0 {
+	//	appMapContent, err := dynamicConfig.Parser().Parse(appContent)
+	//	if err != nil {
+	//		return perrors.WithStack(err)
+	//	}
+	//	envInstance.UpdateAppExternalConfigMap(appMapContent)
+	//}
 
 	return nil
 }
diff --git a/config/config_center_config_test.go b/config/config_center_config_test.go
deleted file mode 100644
index ec11947..0000000
--- a/config/config_center_config_test.go
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 config
-
-import (
-	"testing"
-)
-
-import (
-	"github.com/stretchr/testify/assert"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common/config"
-	"dubbo.apache.org/dubbo-go/v3/common/extension"
-	"dubbo.apache.org/dubbo-go/v3/config_center"
-)
-
-func TestStartConfigCenter(t *testing.T) {
-	extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
-		return &config_center.MockDynamicConfigurationFactory{}
-	})
-	baseConfig := &BaseConfig{ConfigCenterConfig: &ConfigCenterConfig{
-		Protocol:   "mock",
-		Address:    "172.0.0.1",
-		Group:      "dubbo",
-		ConfigFile: "mockDubbo.properties",
-	}}
-
-	c := &configCenter{}
-	err := c.startConfigCenter(*baseConfig)
-	assert.NoError(t, err)
-	b, v := config.GetEnvInstance().Configuration().Back().Value.(*config.InmemoryConfiguration).GetProperty("dubbo.application.organization")
-	assert.True(t, b)
-	assert.Equal(t, "ikurento.com", v)
-}
-
-func TestStartConfigCenterWithRemoteRef(t *testing.T) {
-	extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
-		return &config_center.MockDynamicConfigurationFactory{}
-	})
-	m := make(map[string]*RemoteConfig)
-	m["mock"] = &RemoteConfig{Protocol: "mock", Address: "172.0.0.1"}
-	baseConfig := &BaseConfig{
-		Remotes: m,
-		ConfigCenterConfig: &ConfigCenterConfig{
-			Protocol:   "mock",
-			Group:      "dubbo",
-			RemoteRef:  "mock",
-			ConfigFile: "mockDubbo.properties",
-		},
-	}
-
-	c := &configCenter{}
-	err := c.startConfigCenter(*baseConfig)
-	assert.NoError(t, err)
-	b, v := config.GetEnvInstance().Configuration().Back().Value.(*config.InmemoryConfiguration).GetProperty("dubbo.application.organization")
-	assert.True(t, b)
-	assert.Equal(t, "ikurento.com", v)
-}
diff --git a/config/config_loader.go b/config/config_loader.go
index 48af47e..634eb22 100644
--- a/config/config_loader.go
+++ b/config/config_loader.go
@@ -18,401 +18,489 @@
 package config
 
 import (
-	"flag"
+	"dubbo.apache.org/dubbo-go/v3/common"
+	"errors"
 	"fmt"
-	"io/ioutil"
-	"os"
-	"reflect"
-	"strconv"
-	"sync"
-	"time"
 )
-
 import (
-	hessian "github.com/apache/dubbo-go-hessian2"
-	perrors "github.com/pkg/errors"
+	"github.com/knadh/koanf"
+	"github.com/knadh/koanf/parsers/json"
+	"github.com/knadh/koanf/parsers/toml"
+	"github.com/knadh/koanf/parsers/yaml"
+	"github.com/knadh/koanf/providers/file"
 )
 
 import (
-	"dubbo.apache.org/dubbo-go/v3/common"
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/extension"
-	"dubbo.apache.org/dubbo-go/v3/common/logger"
 	_ "dubbo.apache.org/dubbo-go/v3/common/observer/dispatcher"
-	"dubbo.apache.org/dubbo-go/v3/common/yaml"
-	"dubbo.apache.org/dubbo-go/v3/registry"
 )
 
 var (
-	consumerConfig *ConsumerConfig
-	providerConfig *ProviderConfig
-	// baseConfig = providerConfig.BaseConfig or consumerConfig
-	baseConfig *BaseConfig
-	sslEnabled = false
-
-	// configAccessMutex is used to make sure that xxxxConfig will only be created once if needed.
-	// it should be used combine with double-check to avoid the race condition
-	configAccessMutex sync.Mutex
-
-	maxWait                         = 3
-	confRouterFile                  string
-	confBaseFile                    string
-	uniformVirtualServiceConfigPath string
-	uniformDestRuleConfigPath       string
+	rootConfig *RootConfig
+
+	//consumerConfig *consumer.ShutdownConfig
+	//providerConfig *provider.ProviderConfig
+	//// baseConfig = providerConfig.BaseConfig or consumerConfig
+	//baseConfig *root.ShutdownConfig
+	//sslEnabled = false
+	//
+	//// configAccessMutex is used to make sure that xxxxConfig will only be created once if needed.
+	//// it should be used combine with double-check to avoid the race condition
+	//configAccessMutex sync.Mutex
+	//
+	maxWait = 3
 )
 
-// loaded consumer & provider config from xxx.yml, and log config from xxx.xml
-// Namely: dubbo.consumer.xml & dubbo.provider.xml in java dubbo
-func DefaultInit() []LoaderInitOption {
-	var (
-		confConFile string
-		confProFile string
-	)
-
-	fs := flag.NewFlagSet("config", flag.ContinueOnError)
-	fs.StringVar(&confConFile, "conConf", os.Getenv(constant.CONF_CONSUMER_FILE_PATH), "default client config path")
-	fs.StringVar(&confProFile, "proConf", os.Getenv(constant.CONF_PROVIDER_FILE_PATH), "default server config path")
-	fs.StringVar(&confRouterFile, "rouConf", os.Getenv(constant.CONF_ROUTER_FILE_PATH), "default router config path")
-	fs.StringVar(&uniformVirtualServiceConfigPath, "vsConf", os.Getenv(constant.CONF_VIRTUAL_SERVICE_FILE_PATH), "default virtual service of uniform router config path")
-	fs.StringVar(&uniformDestRuleConfigPath, "drConf", os.Getenv(constant.CONF_DEST_RULE_FILE_PATH), "default destination rule of uniform router config path")
-	fs.Parse(os.Args[1:])
-	for len(fs.Args()) != 0 {
-		fs.Parse(fs.Args()[1:])
-	}
-	// If user did not set the environment variables or flags,
-	// we provide default value
-	if confConFile == "" {
-		confConFile = constant.DEFAULT_CONSUMER_CONF_FILE_PATH
+func Load(opts ...LoaderConfOption) {
+	// pares CommandLine
+	//parseCommandLine()
+	// conf
+	conf := NewLoaderConf(opts...)
+	for _, opt := range opts {
+		opt.apply(conf)
 	}
-	if confProFile == "" {
-		confProFile = constant.DEFAULT_PROVIDER_CONF_FILE_PATH
-	}
-	if confRouterFile == "" {
-		confRouterFile = constant.DEFAULT_ROUTER_CONF_FILE_PATH
-	}
-	return []LoaderInitOption{RouterInitOption(confRouterFile), BaseInitOption(""), ConsumerInitOption(confConFile), ProviderInitOption(confProFile)}
-}
 
-// setDefaultValue set default value for providerConfig or consumerConfig if it is null
-func setDefaultValue(target interface{}) {
-	registryConfig := &RegistryConfig{
-		Protocol:   constant.DEFAULT_REGISTRY_ZK_PROTOCOL,
-		TimeoutStr: constant.DEFAULT_REGISTRY_ZK_TIMEOUT,
-		Address:    constant.DEFAULT_REGISTRY_ZK_ADDRESS,
-	}
-	switch target.(type) {
-	case *ProviderConfig:
-		p := target.(*ProviderConfig)
-		if len(p.Registries) == 0 && p.Registry == nil {
-			p.Registries[constant.DEFAULT_REGISTRY_ZK_ID] = registryConfig
-		}
-		if len(p.Protocols) == 0 {
-			p.Protocols[constant.DEFAULT_PROTOCOL] = &ProtocolConfig{
-				Name: constant.DEFAULT_PROTOCOL,
-				Port: strconv.Itoa(constant.DEFAULT_PORT),
-			}
-		}
-		if p.ApplicationConfig == nil {
-			p.ApplicationConfig = NewDefaultApplicationConfig()
-		}
-	default:
-		c := target.(*ConsumerConfig)
-		if len(c.Registries) == 0 && c.Registry == nil {
-			c.Registries[constant.DEFAULT_REGISTRY_ZK_ID] = registryConfig
-		}
-		if c.ApplicationConfig == nil {
-			c.ApplicationConfig = NewDefaultApplicationConfig()
-		}
-	}
-}
+	// init config
+	rootConfig = NewRootConfig()
+	viper := getKoanf(conf)
 
-func checkRegistries(registries map[string]*RegistryConfig, singleRegistry *RegistryConfig) {
-	if len(registries) == 0 && singleRegistry != nil {
-		registries[constant.DEFAULT_KEY] = singleRegistry
-	}
-}
-
-func checkApplicationName(config *ApplicationConfig) {
-	if config == nil || len(config.Name) == 0 {
-		errMsg := "application config must not be nil, pls check your configuration"
-		logger.Errorf(errMsg)
-		panic(errMsg)
-	}
-}
-
-func loadConsumerConfig() {
-	if consumerConfig == nil {
-		logger.Warnf("consumerConfig is nil!")
-		return
-	}
-	// init other consumer config
-	conConfigType := consumerConfig.ConfigType
-	for key, value := range extension.GetDefaultConfigReader() {
-		if conConfigType != nil {
-			if v, ok := conConfigType[key]; ok {
-				value = v
-			}
-		}
-		if err := extension.GetConfigReaders(value).ReadConsumerConfig(consumerConfig.fileStream); err != nil {
-			logger.Errorf("ReadConsumerConfig error: %#v for %s", perrors.WithStack(err), value)
-		}
-	}
-
-	checkApplicationName(consumerConfig.ApplicationConfig)
-	if err := configCenterRefreshConsumer(); err != nil {
-		logger.Errorf("[consumer config center refresh] %#v", err)
-	}
-
-	// start the metadata report if config set
-	if err := startMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
-		logger.Errorf("Provider starts metadata report error, and the error is {%#v}", err)
-		return
+	if err := viper.UnmarshalWithConf(rootConfig.Prefix(), &rootConfig, koanf.UnmarshalConf{Tag: "yaml"}); err != nil {
+		panic(err)
 	}
-
-	checkRegistries(consumerConfig.Registries, consumerConfig.Registry)
-	for key, ref := range consumerConfig.References {
-		if ref.Generic {
-			genericService := NewGenericService(key)
-			SetConsumerService(genericService)
-		}
-		rpcService := GetConsumerService(key)
-		if rpcService == nil {
-			logger.Warnf("%s does not exist!", key)
-			continue
-		}
-		ref.id = key
-		ref.Refer(rpcService)
-		ref.Implement(rpcService)
+	if rootConfig.ConfigCenter != nil {
+		//监听远程配置刷新本地指定配置
 	}
-
-	// Write current configuration to cache file.
-	if consumerConfig.CacheFile != "" {
-		if data, err := yaml.MarshalYML(consumerConfig); err != nil {
-			logger.Errorf("Marshal consumer config err: %s", err.Error())
-		} else {
-			if err := ioutil.WriteFile(consumerConfig.CacheFile, data, 0666); err != nil {
-				logger.Errorf("Write consumer config cache file err: %s", err.Error())
-			}
-		}
+	if err := rootConfig.CheckConfig(); err != nil {
+		panic(err)
 	}
+	rootConfig.Validate()
+	// root config init finish
 
-	// wait for invoker is available, if wait over default 3s, then panic
-	var count int
-	for {
-		checkok := true
-		for _, refconfig := range consumerConfig.References {
-			if (refconfig.Check != nil && *refconfig.Check) ||
-				(refconfig.Check == nil && consumerConfig.Check != nil && *consumerConfig.Check) ||
-				(refconfig.Check == nil && consumerConfig.Check == nil) { // default to true
-
-				if refconfig.invoker != nil && !refconfig.invoker.IsAvailable() {
-					checkok = false
-					count++
-					if count > maxWait {
-						errMsg := fmt.Sprintf("Failed to check the status of the service %v. No provider available for the service to the consumer use dubbo version %v", refconfig.InterfaceName, constant.Version)
-						logger.Error(errMsg)
-						panic(errMsg)
-					}
-					time.Sleep(time.Second * 1)
-					break
-				}
-				if refconfig.invoker == nil {
-					logger.Warnf("The interface %s invoker not exist, may you should check your interface config.", refconfig.InterfaceName)
-				}
-			}
-		}
-		if checkok {
-			break
-		}
-	}
+	// todo why this line
+	//extension.SetAndInitGlobalDispatcher(rootConfig.EventDispatcherType)
+	rootConfig.Provider.Load()
+	rootConfig.Consumer.Load()
 }
 
-func loadProviderConfig() {
-	if providerConfig == nil {
-		logger.Warnf("providerConfig is nil!")
-		return
-	}
-
-	// init other provider config
-	proConfigType := providerConfig.ConfigType
-	for key, value := range extension.GetDefaultConfigReader() {
-		if proConfigType != nil {
-			if v, ok := proConfigType[key]; ok {
-				value = v
-			}
-		}
-		if err := extension.GetConfigReaders(value).ReadProviderConfig(providerConfig.fileStream); err != nil {
-			logger.Errorf("ReadProviderConfig error: %#v for %s", perrors.WithStack(err), value)
-		}
-	}
-
-	checkApplicationName(providerConfig.ApplicationConfig)
-	if err := configCenterRefreshProvider(); err != nil {
-		logger.Errorf("[provider config center refresh] %#v", err)
+func check() error {
+	if rootConfig == nil {
+		return errors.New("execute the config.Load() method first")
 	}
-
-	// start the metadata report if config set
-	if err := startMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
-		logger.Errorf("Provider starts metadata report error, and the error is {%#v}", err)
-		return
-	}
-
-	checkRegistries(providerConfig.Registries, providerConfig.Registry)
-
-	// Write the current configuration to cache file.
-	if providerConfig.CacheFile != "" {
-		if data, err := yaml.MarshalYML(providerConfig); err != nil {
-			logger.Errorf("Marshal provider config err: %s", err.Error())
-		} else {
-			if err := ioutil.WriteFile(providerConfig.CacheFile, data, 0666); err != nil {
-				logger.Errorf("Write provider config cache file err: %s", err.Error())
-			}
-		}
-	}
-
-	for key, svs := range providerConfig.Services {
-		rpcService := GetProviderService(key)
-		if rpcService == nil {
-			logger.Warnf("%s does not exist!", key)
-			continue
-		}
-		svs.id = key
-		svs.Implement(rpcService)
-		svs.Protocols = providerConfig.Protocols
-		if err := svs.Export(); err != nil {
-			panic(fmt.Sprintf("service %s export failed! err: %#v", key, err))
-		}
-	}
-	registerServiceInstance()
+	return nil
 }
 
-// registerServiceInstance register service instance
-func registerServiceInstance() {
-	url := selectMetadataServiceExportedURL()
-	if url == nil {
-		return
-	}
-	instance, err := createInstance(url)
-	if err != nil {
-		panic(err)
-	}
-	p := extension.GetProtocol(constant.REGISTRY_KEY)
-	var rp registry.RegistryFactory
-	var ok bool
-	if rp, ok = p.(registry.RegistryFactory); !ok {
-		panic("dubbo registry protocol{" + reflect.TypeOf(p).String() + "} is invalid")
-	}
-	rs := rp.GetRegistries()
-	for _, r := range rs {
-		var sdr registry.ServiceDiscoveryHolder
-		if sdr, ok = r.(registry.ServiceDiscoveryHolder); !ok {
-			continue
-		}
-		err := sdr.GetServiceDiscovery().Register(instance)
-		if err != nil {
-			panic(err)
-		}
-	}
-	// todo publish metadata to remote
-	if remoteMetadataService, err := extension.GetRemoteMetadataService(); err == nil {
-		remoteMetadataService.PublishMetadata(GetApplicationConfig().Name)
-	}
-}
+//parseCommandLine parse command line
+//func parseCommandLine() {
+//	flag.String("delim", ".", "config file delim")
+//	flag.String("name", "conf_application.yaml", "config file name")
+//	flag.String("genre", "yaml", "config file type")
+//	flag.String("path", "./conf", "config file path default")
+//
+//	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
+//	pflag.Parse()
+//
+//	if err := viper.BindPFlags(pflag.CommandLine); err != nil {
+//		panic(err)
+//	}
+//}
+
+func getKoanf(conf *loaderConf) *koanf.Koanf {
+	var (
+		k   *koanf.Koanf
+		err error
+	)
 
-// nolint
-func createInstance(url *common.URL) (registry.ServiceInstance, error) {
-	appConfig := GetApplicationConfig()
-	port, err := strconv.ParseInt(url.Port, 10, 32)
-	if err != nil {
-		return nil, perrors.WithMessage(err, "invalid port: "+url.Port)
-	}
+	k = koanf.New(conf.delim)
 
-	host := url.Ip
-	if len(host) == 0 {
-		host = common.GetLocalIp()
+	switch conf.genre {
+	case "yaml", "yml":
+		err = k.Load(file.Provider(conf.path), yaml.Parser())
+	case "json":
+		err = k.Load(file.Provider(conf.path), json.Parser())
+	case "toml":
+		err = k.Load(file.Provider(conf.path), toml.Parser())
+	default:
+		err = errors.New(fmt.Sprintf("Unsupported %s file type", conf.genre))
 	}
 
-	// usually we will add more metadata
-	metadata := make(map[string]string, 8)
-	metadata[constant.METADATA_STORAGE_TYPE_PROPERTY_NAME] = appConfig.MetadataType
-
-	return &registry.DefaultServiceInstance{
-		ServiceName: appConfig.Name,
-		Host:        host,
-		Port:        int(port),
-		ID:          host + constant.KEY_SEPARATOR + url.Port,
-		Enable:      true,
-		Healthy:     true,
-		Metadata:    metadata,
-	}, nil
-}
-
-// selectMetadataServiceExportedURL get already be exported url
-func selectMetadataServiceExportedURL() *common.URL {
-	var selectedUrl *common.URL
-	metaDataService, err := extension.GetLocalMetadataService("")
-	if err != nil {
-		logger.Warn(err)
-		return nil
-	}
-	urlList, err := metaDataService.GetExportedURLs(constant.ANY_VALUE, constant.ANY_VALUE, constant.ANY_VALUE, constant.ANY_VALUE)
 	if err != nil {
 		panic(err)
 	}
-	if len(urlList) == 0 {
-		return nil
-	}
-	for _, url := range urlList {
-		selectedUrl = url
-		// rest first
-		if url.Protocol == "rest" {
-			break
-		}
-	}
-	return selectedUrl
-}
-
-func initRouter() {
-	if uniformDestRuleConfigPath != "" && uniformVirtualServiceConfigPath != "" {
-		if err := RouterInit(uniformVirtualServiceConfigPath, uniformDestRuleConfigPath); err != nil {
-			logger.Warnf("[routerConfig init] %#v", err)
-		}
-	}
-}
-
-// Load Dubbo Init
-func Load() {
-	options := DefaultInit()
-	LoadWithOptions(options...)
-}
-
-func LoadWithOptions(options ...LoaderInitOption) {
-	// register metadata info and service info
-	hessian.RegisterPOJO(&common.MetadataInfo{})
-	hessian.RegisterPOJO(&common.ServiceInfo{})
-	hessian.RegisterPOJO(&common.URL{})
-
-	for _, option := range options {
-		option.init()
-	}
-	for _, option := range options {
-		option.apply()
-	}
-	// init router
-	initRouter()
-
-	// init the shutdown callback
-	GracefulShutdownInit()
+	return k
 }
 
+//
+//func GetConfigCenterConfig() (*center.ConfigCenterConfig, error) {
+//	if err := check(); err != nil {
+//		return nil, err
+//	}
+//	if configCenterConfig != nil {
+//		return configCenterConfig, nil
+//	}
+//	conf := center.GetConfigCenterConfig(rootConfig.ConfigCenter, rootConfig.Koanf)
+//
+//	if err := conf.SetDefault(); err != nil {
+//		return nil, err
+//	}
+//	conf.TranslateConfigAddress()
+//	if err := conf.Validate(rootConfig.Validate); err != nil {
+//		return nil, err
+//	}
+//	configCenterConfig = conf
+//	return conf, nil
+//}
+//
+//// loaded consumer & provider config from xxx.yml, and log config from xxx.xml
+//// Namely: dubbo.consumer.xml & dubbo.provider.xml in java dubbo
+//func DefaultInit() []LoaderInitOption {
+//	var (
+//		confConFile string
+//		confProFile string
+//	)
+//
+//	fs := flag.NewFlagSet("config", flag.ContinueOnError)
+//	fs.StringVar(&confConFile, "conConf", os.Getenv(constant.CONF_CONSUMER_FILE_PATH), "default client config path")
+//	fs.StringVar(&confProFile, "proConf", os.Getenv(constant.CONF_PROVIDER_FILE_PATH), "default server config path")
+//	fs.StringVar(&confRouterFile, "rouConf", os.Getenv(constant.CONF_ROUTER_FILE_PATH), "default router config path")
+//	fs.StringVar(&uniformVirtualServiceConfigPath, "vsConf", os.Getenv(constant.CONF_VIRTUAL_SERVICE_FILE_PATH), "default virtual service of uniform router config path")
+//	fs.StringVar(&uniformDestRuleConfigPath, "drConf", os.Getenv(constant.CONF_DEST_RULE_FILE_PATH), "default destination rule of uniform router config path")
+//	fs.Parse(os.Args[1:])
+//	for len(fs.Args()) != 0 {
+//		fs.Parse(fs.Args()[1:])
+//	}
+//	// If user did not set the environment variables or flags,
+//	// we provide default value
+//	if confConFile == "" {
+//		confConFile = constant.DEFAULT_CONSUMER_CONF_FILE_PATH
+//	}
+//	if confProFile == "" {
+//		confProFile = constant.DEFAULT_PROVIDER_CONF_FILE_PATH
+//	}
+//	if confRouterFile == "" {
+//		confRouterFile = constant.DEFAULT_ROUTER_CONF_FILE_PATH
+//	}
+//	return []LoaderInitOption{RouterInitOption(confRouterFile), BaseInitOption(""), ConsumerInitOption(confConFile), ProviderInitOption(confProFile)}
+//}
+//
+//// setDefaultValue set default value for providerConfig or consumerConfig if it is null
+//func setDefaultValue(target interface{}) {
+//	registryConfig := &registry2.RegistryConfig{
+//		Protocol:   constant.DEFAULT_REGISTRY_ZK_PROTOCOL,
+//		TimeoutStr: constant.DEFAULT_REGISTRY_ZK_TIMEOUT,
+//		Address:    constant.DEFAULT_REGISTRY_ZK_ADDRESS,
+//	}
+//	switch target.(type) {
+//	case *provider.ProviderConfig:
+//		p := target.(*provider.ProviderConfig)
+//		if len(p.Registries) == 0 && p.Registry == nil {
+//			p.Registries[constant.DEFAULT_REGISTRY_ZK_ID] = registryConfig
+//		}
+//		if len(p.Protocols) == 0 {
+//			p.Protocols[constant.DEFAULT_PROTOCOL] = &protocol.ProtocolConfig{
+//				Name: constant.DEFAULT_PROTOCOL,
+//				Port: strconv.Itoa(constant.DEFAULT_PORT),
+//			}
+//		}
+//		if p.ApplicationConfig == nil {
+//			p.ApplicationConfig = NewDefaultApplicationConfig()
+//		}
+//	default:
+//		c := target.(*consumer.ShutdownConfig)
+//		if len(c.Registries) == 0 && c.Registry == nil {
+//			c.Registries[constant.DEFAULT_REGISTRY_ZK_ID] = registryConfig
+//		}
+//		if c.ApplicationConfig == nil {
+//			c.ApplicationConfig = NewDefaultApplicationConfig()
+//		}
+//	}
+//}
+//
+//func checkRegistries(registriesConfig map[string]*registry2.RegistryConfig, singleRegistry *registry2.RegistryConfig) {
+//	if len(registriesConfig) == 0 && singleRegistry != nil {
+//		registriesConfig[constant.DEFAULT_KEY] = singleRegistry
+//	}
+//}
+//
+//func checkApplicationName(config *applicationConfig.ShutdownConfig) {
+//	if config == nil || len(config.Name) == 0 {
+//		errMsg := "applicationConfig config must not be nil, pls check your configuration"
+//		logger.Errorf(errMsg)
+//		panic(errMsg)
+//	}
+//}
+//
+//func loadConsumerConfig() {
+//	if consumerConfig == nil {
+//		logger.Warnf("consumerConfig is nil!")
+//		return
+//	}
+//	// init other consumer config
+//	conConfigType := consumerConfig.ConfigType
+//	for key, value := range extension.GetDefaultConfigReader() {
+//		if conConfigType != nil {
+//			if v, ok := conConfigType[key]; ok {
+//				value = v
+//			}
+//		}
+//		if err := extension.GetConfigReaders(value).ReadConsumerConfig(consumerConfig.fileStream); err != nil {
+//			logger.Errorf("ReadConsumerConfig error: %#v for %s", perrors.WithStack(err), value)
+//		}
+//	}
+//
+//	checkApplicationName(consumerConfig.ApplicationConfig)
+//	if err := consumer.configCenterRefreshConsumer(); err != nil {
+//		logger.Errorf("[consumer config center refresh] %#v", err)
+//	}
+//
+//	// start the metadata report if config set
+//	if err := report.startMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
+//		logger.Errorf("Provider starts metadata report error, and the error is {%#v}", err)
+//		return
+//	}
+//
+//	checkRegistries(consumerConfig.Registries, consumerConfig.Registry)
+//	for key, ref := range consumerConfig.References {
+//		if ref.Generic {
+//			genericService := generic.NewGenericService(key)
+//			instance.SetConsumerService(genericService)
+//		}
+//		rpcService := instance.GetConsumerService(key)
+//		if rpcService == nil {
+//			logger.Warnf("%s does not exist!", key)
+//			continue
+//		}
+//		ref.id = key
+//		ref.Refer(rpcService)
+//		ref.Implement(rpcService)
+//	}
+//
+//	// Write current configuration to cache file.
+//	if consumerConfig.CacheFile != "" {
+//		if data, err := yaml.MarshalYML(consumerConfig); err != nil {
+//			logger.Errorf("Marshal consumer config err: %s", err.Error())
+//		} else {
+//			if err := ioutil.WriteFile(consumerConfig.CacheFile, data, 0666); err != nil {
+//				logger.Errorf("Write consumer config cache file err: %s", err.Error())
+//			}
+//		}
+//	}
+//
+//	// wait for invoker is available, if wait over default 3s, then panic
+//	var count int
+//	for {
+//		checkok := true
+//		for _, refconfig := range consumerConfig.References {
+//			if (refconfig.Check != nil && *refconfig.Check) ||
+//				(refconfig.Check == nil && consumerConfig.Check != nil && *consumerConfig.Check) ||
+//				(refconfig.Check == nil && consumerConfig.Check == nil) { // default to true
+//
+//				if refconfig.invoker != nil && !refconfig.invoker.IsAvailable() {
+//					checkok = false
+//					count++
+//					if count > maxWait {
+//						errMsg := fmt.Sprintf("Failed to check the status of the service %v. No provider available for the service to the consumer use dubbo version %v", refconfig.InterfaceName, constant.Version)
+//						logger.Error(errMsg)
+//						panic(errMsg)
+//					}
+//					time.Sleep(time.Second * 1)
+//					break
+//				}
+//				if refconfig.invoker == nil {
+//					logger.Warnf("The interface %s invoker not exist, may you should check your interface config.", refconfig.InterfaceName)
+//				}
+//			}
+//		}
+//		if checkok {
+//			break
+//		}
+//	}
+//}
+//
+//func loadProviderConfig() {
+//	if providerConfig == nil {
+//		logger.Warnf("providerConfig is nil!")
+//		return
+//	}
+//
+//	// init other provider config
+//	proConfigType := providerConfig.ConfigType
+//	for key, value := range extension.GetDefaultConfigReader() {
+//		if proConfigType != nil {
+//			if v, ok := proConfigType[key]; ok {
+//				value = v
+//			}
+//		}
+//		if err := extension.GetConfigReaders(value).ReadProviderConfig(providerConfig.fileStream); err != nil {
+//			logger.Errorf("ReadProviderConfig error: %#v for %s", perrors.WithStack(err), value)
+//		}
+//	}
+//
+//	checkApplicationName(providerConfig.ApplicationConfig)
+//	if err := provider.configCenterRefreshProvider(); err != nil {
+//		logger.Errorf("[provider config center refresh] %#v", err)
+//	}
+//
+//	// start the metadata report if config set
+//	if err := report.startMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
+//		logger.Errorf("Provider starts metadata report error, and the error is {%#v}", err)
+//		return
+//	}
+//
+//	checkRegistries(providerConfig.Registries, providerConfig.Registry)
+//
+//	// Write the current configuration to cache file.
+//	if providerConfig.CacheFile != "" {
+//		if data, err := yaml.MarshalYML(providerConfig); err != nil {
+//			logger.Errorf("Marshal provider config err: %s", err.Error())
+//		} else {
+//			if err := ioutil.WriteFile(providerConfig.CacheFile, data, 0666); err != nil {
+//				logger.Errorf("Write provider config cache file err: %s", err.Error())
+//			}
+//		}
+//	}
+//
+//	for key, svs := range providerConfig.Services {
+//		rpcService := instance.GetProviderService(key)
+//		if rpcService == nil {
+//			logger.Warnf("%s does not exist!", key)
+//			continue
+//		}
+//		svs.id = key
+//		svs.Implement(rpcService)
+//		svs.Protocols = providerConfig.Protocols
+//		if err := svs.Export(); err != nil {
+//			panic(fmt.Sprintf("service %s export failed! err: %#v", key, err))
+//		}
+//	}
+//	registerServiceInstance()
+//}
+//
+//// registerServiceInstance register service instance
+//func registerServiceInstance() {
+//	url := selectMetadataServiceExportedURL()
+//	if url == nil {
+//		return
+//	}
+//	instance, err := createInstance(url)
+//	if err != nil {
+//		panic(err)
+//	}
+//	p := extension.GetProtocol(constant.REGISTRY_KEY)
+//	var rp registry.RegistryFactory
+//	var ok bool
+//	if rp, ok = p.(registry.RegistryFactory); !ok {
+//		panic("dubbo registry protocol{" + reflect.TypeOf(p).String() + "} is invalid")
+//	}
+//	rs := rp.GetRegistries()
+//	for _, r := range rs {
+//		var sdr registry.ServiceDiscoveryHolder
+//		if sdr, ok = r.(registry.ServiceDiscoveryHolder); !ok {
+//			continue
+//		}
+//		err := sdr.GetServiceDiscovery().Register(instance)
+//		if err != nil {
+//			panic(err)
+//		}
+//	}
+//	// todo publish metadata to remote
+//	if remoteMetadataService, err := extension.GetRemoteMetadataService(); err == nil {
+//		remoteMetadataService.PublishMetadata(GetApplicationConfig().Name)
+//	}
+//}
+//
+//// nolint
+//func createInstance(url *common.URL) (registry.ServiceInstance, error) {
+//	appConfig := GetApplicationConfig()
+//	port, err := strconv.ParseInt(url.Port, 10, 32)
+//	if err != nil {
+//		return nil, perrors.WithMessage(err, "invalid port: "+url.Port)
+//	}
+//
+//	host := url.Ip
+//	if len(host) == 0 {
+//		host = common.GetLocalIp()
+//	}
+//
+//	// usually we will add more metadata
+//	metadata := make(map[string]string, 8)
+//	metadata[constant.METADATA_STORAGE_TYPE_PROPERTY_NAME] = appConfig.MetadataType
+//
+//	return &registry.DefaultServiceInstance{
+//		ServiceName: appConfig.Name,
+//		Host:        host,
+//		Port:        int(port),
+//		ID:          host + constant.KEY_SEPARATOR + url.Port,
+//		Enable:      true,
+//		Healthy:     true,
+//		Metadata:    metadata,
+//	}, nil
+//}
+//
+//// selectMetadataServiceExportedURL get already be exported url
+//func selectMetadataServiceExportedURL() *common.URL {
+//	var selectedUrl *common.URL
+//	metaDataService, err := extension.GetLocalMetadataService("")
+//	if err != nil {
+//		logger.Warn(err)
+//		return nil
+//	}
+//	urlList, err := metaDataService.GetExportedURLs(constant.ANY_VALUE, constant.ANY_VALUE, constant.ANY_VALUE, constant.ANY_VALUE)
+//	if err != nil {
+//		panic(err)
+//	}
+//	if len(urlList) == 0 {
+//		return nil
+//	}
+//	for _, url := range urlList {
+//		selectedUrl = url
+//		// rest first
+//		if url.Protocol == "rest" {
+//			break
+//		}
+//	}
+//	return selectedUrl
+//}
+//
+//func initRouter() {
+//	if uniformDestRuleConfigPath != "" && uniformVirtualServiceConfigPath != "" {
+//		if err := router.RouterInit(uniformVirtualServiceConfigPath, uniformDestRuleConfigPath); err != nil {
+//			logger.Warnf("[routerConfig init] %#v", err)
+//		}
+//	}
+//}
+//
+//// Load Dubbo Init
+//func Load() {
+//	options := DefaultInit()
+//	LoadWithOptions(options...)
+//}
+//
+//func LoadWithOptions(options ...LoaderInitOption) {
+//	// register metadata info and service info
+//	hessian.RegisterPOJO(&common.MetadataInfo{})
+//	hessian.RegisterPOJO(&common.ServiceInfo{})
+//	hessian.RegisterPOJO(&common.URL{})
+//
+//	for _, option := range options {
+//		option.init()
+//	}
+//	for _, option := range options {
+//		option.apply()
+//	}
+//	// init router
+//	initRouter()
+//
+//	// init the shutdown callback
+//	shutdown.GracefulShutdownInit()
+//}
+//
 // GetRPCService get rpc service for consumer
 func GetRPCService(name string) common.RPCService {
-	return consumerConfig.References[name].GetRPCService()
+	return rootConfig.Consumer.References[name].GetRPCService()
 }
 
 // RPCService create rpc service for consumer
 func RPCService(service common.RPCService) {
-	consumerConfig.References[service.Reference()].Implement(service)
+	rootConfig.Consumer.References[service.Reference()].Implement(service)
 }
 
 // GetMetricConfig find the MetricConfig
@@ -421,83 +509,71 @@ func RPCService(service common.RPCService) {
 // In general, it will be locked 0 or 1 time.
 // So you don't need to worry about the race condition
 func GetMetricConfig() *MetricConfig {
-	if GetBaseConfig().MetricConfig == nil {
-		configAccessMutex.Lock()
-		defer configAccessMutex.Unlock()
-		if GetBaseConfig().MetricConfig == nil {
-			GetBaseConfig().MetricConfig = &MetricConfig{}
-		}
-	}
-	return GetBaseConfig().MetricConfig
+	// todo
+	//if GetBaseConfig().MetricConfig == nil {
+	//	configAccessMutex.Lock()
+	//	defer configAccessMutex.Unlock()
+	//	if GetBaseConfig().MetricConfig == nil {
+	//		GetBaseConfig().MetricConfig = &metric.MetricConfig{}
+	//	}
+	//}
+	//return GetBaseConfig().MetricConfig
+	return rootConfig.MetricConfig
 }
 
-// GetApplicationConfig find the application config
+// GetApplicationConfig find the applicationConfig config
 // if not, we will create one
 // Usually applicationConfig will be initialized when system start
 // we use double-check to reduce race condition
 // In general, it will be locked 0 or 1 time.
 // So you don't need to worry about the race condition
-func GetApplicationConfig() *ApplicationConfig {
-	if GetBaseConfig().ApplicationConfig == nil {
-		configAccessMutex.Lock()
-		defer configAccessMutex.Unlock()
-		if GetBaseConfig().ApplicationConfig == nil {
-			GetBaseConfig().ApplicationConfig = &ApplicationConfig{}
-		}
-	}
-	return GetBaseConfig().ApplicationConfig
-}
+//func GetApplicationConfig() *ShutdownConfig {
+//	// todo
+//	//if GetBaseConfig().ApplicationConfig == nil {
+//	//	configAccessMutex.Lock()
+//	//	defer configAccessMutex.Unlock()
+//	//	if GetBaseConfig().ApplicationConfig == nil {
+//	//		GetBaseConfig().ApplicationConfig = &applicationConfig.ShutdownConfig{}
+//	//	}
+//	//}
+//	//return GetBaseConfig().ApplicationConfig
+//	return rootConfig.
+//}
 
 // GetProviderConfig find the provider config
 // if not found, create new one
-func GetProviderConfig() ProviderConfig {
-	if providerConfig == nil {
-		if providerConfig == nil {
-			return ProviderConfig{}
-		}
-	}
-	return *providerConfig
-}
+//func GetProviderConfig() provider.ProviderConfig {
+//	if providerConfig == nil {
+//		if providerConfig == nil {
+//			return provider.ProviderConfig{}
+//		}
+//	}
+//	return *providerConfig
+//}
 
 // GetConsumerConfig find the consumer config
 // if not found, create new one
 // we use double-check to reduce race condition
 // In general, it will be locked 0 or 1 time.
 // So you don't need to worry about the race condition
-func GetConsumerConfig() ConsumerConfig {
-	if consumerConfig == nil {
-		if consumerConfig == nil {
-			return ConsumerConfig{}
-		}
-	}
-	return *consumerConfig
-}
-
-func GetBaseConfig() *BaseConfig {
-	if baseConfig == nil {
-		configAccessMutex.Lock()
-		defer configAccessMutex.Unlock()
-		if baseConfig == nil {
-			baseConfig = &BaseConfig{
-				MetricConfig:       &MetricConfig{},
-				ConfigCenterConfig: &ConfigCenterConfig{},
-				Remotes:            make(map[string]*RemoteConfig),
-				ApplicationConfig:  &ApplicationConfig{},
-				ServiceDiscoveries: make(map[string]*ServiceDiscoveryConfig),
-			}
-		}
-	}
-	return baseConfig
-}
-
-func GetSslEnabled() bool {
-	return sslEnabled
-}
-
-func SetSslEnabled(enabled bool) {
-	sslEnabled = enabled
-}
+//func GetConsumerConfig() consumer.ShutdownConfig {
+//	if consumerConfig == nil {
+//		if consumerConfig == nil {
+//			return consumer.ShutdownConfig{}
+//		}
+//	}
+//	return *consumerConfig
+//}
+
+//func GetSslEnabled() bool {
+//	return sslEnabled
+//}
+//
+//func SetSslEnabled(enabled bool) {
+//	sslEnabled = enabled
+//}
 
 func IsProvider() bool {
-	return providerConfig != nil
+	// FixME
+	return rootConfig.Provider != nil
 }
diff --git a/config/config_loader_options.go b/config/config_loader_options.go
index bc8aff1..685447a 100644
--- a/config/config_loader_options.go
+++ b/config/config_loader_options.go
@@ -1,138 +1,252 @@
 /*
- * 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 config
 
 import (
-	"log"
+	"fmt"
+	"os"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strings"
 )
-
 import (
-	"dubbo.apache.org/dubbo-go/v3/common/extension"
+	"github.com/pkg/errors"
 )
 
-type LoaderInitOption interface {
-	init()
-	apply()
+type loaderConf struct {
+	// loaderConf file type default yaml
+	genre string
+	// loaderConf file path default ./conf
+	path string
+	// loaderConf file delim default .
+	delim string
 }
 
-type optionFunc struct {
-	initFunc  func()
-	applyFunc func()
-}
+func NewLoaderConf(opts ...LoaderConfOption) *loaderConf {
+	conf := &loaderConf{
+		genre: "yaml",
+		path:  "./conf/application.yaml",
+		delim: ".",
+	}
 
-func (f *optionFunc) init() {
-	f.initFunc()
+	for _, opt := range opts {
+		opt.apply(conf)
+	}
+	return conf
 }
 
-func (f *optionFunc) apply() {
-	f.applyFunc()
+type LoaderConfOption interface {
+	apply(vc *loaderConf)
 }
 
-func ConsumerInitOption(confConFile string) LoaderInitOption {
-	return consumerInitOption(confConFile, false)
-}
+type loaderConfigFunc func(*loaderConf)
 
-func ConsumerMustInitOption(confConFile string) LoaderInitOption {
-	return consumerInitOption(confConFile, true)
+func (fn loaderConfigFunc) apply(vc *loaderConf) {
+	fn(vc)
 }
 
-func consumerInitOption(confConFile string, must bool) LoaderInitOption {
-	return &optionFunc{
-		func() {
-			if consumerConfig != nil && !must {
-				return
-			}
-			if errCon := ConsumerInit(confConFile); errCon != nil {
-				log.Printf("[consumerInit] %#v", errCon)
-				consumerConfig = nil
-			} else if confBaseFile == "" {
-				// Check if there are some important key fields missing,
-				// if so, we set a default value for it
-				setDefaultValue(consumerConfig)
-				// Even though baseConfig has been initialized, we override it
-				// because we think read from config file is correct config
-				baseConfig = &consumerConfig.BaseConfig
-			}
-		},
-		func() {
-			loadConsumerConfig()
-		},
-	}
+// WithGenre set loaderConf Genre
+func WithGenre(genre string) LoaderConfOption {
+	return loaderConfigFunc(func(conf *loaderConf) {
+		g := strings.ToLower(genre)
+		if err := checkGenre(g); err != nil {
+			panic(err)
+		}
+		conf.genre = g
+	})
 }
 
-func ProviderInitOption(confProFile string) LoaderInitOption {
-	return providerInitOption(confProFile, false)
+// WithPath set loaderConf path
+func WithPath(path string) LoaderConfOption {
+	return loaderConfigFunc(func(conf *loaderConf) {
+		conf.path = absolutePath(path)
+	})
 }
 
-func ProviderMustInitOption(confProFile string) LoaderInitOption {
-	return providerInitOption(confProFile, true)
+func WithDelim(delim string) LoaderConfOption {
+	return loaderConfigFunc(func(conf *loaderConf) {
+		conf.delim = delim
+	})
 }
 
-func providerInitOption(confProFile string, must bool) LoaderInitOption {
-	return &optionFunc{
-		func() {
-			if providerConfig != nil && !must {
-				return
-			}
-			if errPro := ProviderInit(confProFile); errPro != nil {
-				log.Printf("[providerInit] %#v", errPro)
-				providerConfig = nil
-			} else if confBaseFile == "" {
-				// Check if there are some important key fields missing,
-				// if so, we set a default value for it
-				setDefaultValue(providerConfig)
-				// Even though baseConfig has been initialized, we override it
-				// because we think read from config file is correct config
-				baseConfig = &providerConfig.BaseConfig
-			}
-		},
-		func() {
-			loadProviderConfig()
-		},
+// absolutePath get absolut path
+func absolutePath(inPath string) string {
+
+	if inPath == "$HOME" || strings.HasPrefix(inPath, "$HOME"+string(os.PathSeparator)) {
+		inPath = userHomeDir() + inPath[5:]
 	}
+
+	if filepath.IsAbs(inPath) {
+		return filepath.Clean(inPath)
+	}
+
+	p, err := filepath.Abs(inPath)
+	if err == nil {
+		return filepath.Clean(p)
+	}
+
+	return ""
 }
 
-func RouterInitOption(crf string) LoaderInitOption {
-	return &optionFunc{
-		func() {
-			confRouterFile = crf
-		},
-		func() {
-			initRouter()
-		},
+//userHomeDir get gopath
+func userHomeDir() string {
+	if runtime.GOOS == "windows" {
+		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+		if home == "" {
+			home = os.Getenv("USERPROFILE")
+		}
+		return home
 	}
+	return os.Getenv("HOME")
 }
 
-func BaseInitOption(cbf string) LoaderInitOption {
-	return &optionFunc{
-		func() {
-			if cbf == "" {
-				return
-			}
-			confBaseFile = cbf
-			if err := BaseInit(cbf); err != nil {
-				log.Printf("[BaseInit] %#v", err)
-				baseConfig = nil
-			}
-		},
-		func() {
-			// init the global event dispatcher
-			extension.SetAndInitGlobalDispatcher(GetBaseConfig().EventDispatcherType)
-		},
+// checkGenre check Genre
+func checkGenre(genre string) error {
+	genres := []string{"json", "toml", "yaml", "yml"}
+	sort.Strings(genres)
+	idx := sort.SearchStrings(genres, genre)
+	if genres[idx] != genre {
+		return errors.New(fmt.Sprintf("no support %s", genre))
 	}
+	return nil
 }
+
+//
+//import (
+//	"dubbo.apache.org/dubbo-go/v3/loaderConf/base"
+//	"dubbo.apache.org/dubbo-go/v3/loaderConf/consumer"
+//	"dubbo.apache.org/dubbo-go/v3/loaderConf/provider"
+//	"log"
+//)
+//
+//import (
+//	"dubbo.apache.org/dubbo-go/v3/common/extension"
+//)
+//
+//type LoaderInitOption interface {
+//	init()
+//	apply()
+//}
+//
+//type loaderConfigFunc struct {
+//	initFunc  func()
+//	applyFunc func()
+//}
+//
+//func (f *loaderConfigFunc) init() {
+//	f.initFunc()
+//}
+//
+//func (f *loaderConfigFunc) apply() {
+//	f.applyFunc()
+//}
+//
+//func ConsumerInitOption(confConFile string) LoaderInitOption {
+//	return consumerInitOption(confConFile, false)
+//}
+//
+//func ConsumerMustInitOption(confConFile string) LoaderInitOption {
+//	return consumerInitOption(confConFile, true)
+//}
+//
+//func consumerInitOption(confConFile string, must bool) LoaderInitOption {
+//	return &loaderConfigFunc{
+//		func() {
+//			if consumerConfig != nil && !must {
+//				return
+//			}
+//			if errCon := consumer.ConsumerInit(confConFile); errCon != nil {
+//				log.Printf("[consumerInit] %#v", errCon)
+//				consumerConfig = nil
+//			} else if confBaseFile == "" {
+//				// Check if there are some important key fields missing,
+//				// if so, we set a default value for it
+//				setDefaultValue(consumerConfig)
+//				// Even though baseConfig has been initialized, we override it
+//				// because we think read from loaderConf file is correct loaderConf
+//				baseConfig = &consumerConfig.BaseConfig
+//			}
+//		},
+//		func() {
+//			loadConsumerConfig()
+//		},
+//	}
+//}
+//
+//func ProviderInitOption(confProFile string) LoaderInitOption {
+//	return providerInitOption(confProFile, false)
+//}
+//
+//func ProviderMustInitOption(confProFile string) LoaderInitOption {
+//	return providerInitOption(confProFile, true)
+//}
+//
+//func providerInitOption(confProFile string, must bool) LoaderInitOption {
+//	return &loaderConfigFunc{
+//		func() {
+//			if providerConfig != nil && !must {
+//				return
+//			}
+//			if errPro := provider.ProviderInit(confProFile); errPro != nil {
+//				log.Printf("[providerInit] %#v", errPro)
+//				providerConfig = nil
+//			} else if confBaseFile == "" {
+//				// Check if there are some important key fields missing,
+//				// if so, we set a default value for it
+//				setDefaultValue(providerConfig)
+//				// Even though baseConfig has been initialized, we override it
+//				// because we think read from loaderConf file is correct loaderConf
+//				baseConfig = &providerConfig.BaseConfig
+//			}
+//		},
+//		func() {
+//			loadProviderConfig()
+//		},
+//	}
+//}
+//
+//func RouterInitOption(crf string) LoaderInitOption {
+//	return &loaderConfigFunc{
+//		func() {
+//			confRouterFile = crf
+//		},
+//		func() {
+//			initRouter()
+//		},
+//	}
+//}
+//
+//func BaseInitOption(cbf string) LoaderInitOption {
+//	return &loaderConfigFunc{
+//		func() {
+//			if cbf == "" {
+//				return
+//			}
+//			confBaseFile = cbf
+//			if err := base.BaseInit(cbf); err != nil {
+//				log.Printf("[BaseInit] %#v", err)
+//				baseConfig = nil
+//			}
+//		},
+//		func() {
+//			// init the global event dispatcher
+//			extension.SetAndInitGlobalDispatcher(GetBaseConfig().EventDispatcherType)
+//		},
+//	}
+//}
diff --git a/config/config_loader_options_test.go b/config/config_loader_options_test.go
new file mode 100644
index 0000000..0004898
--- /dev/null
+++ b/config/config_loader_options_test.go
@@ -0,0 +1,61 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package config
+
+import (
+	"testing"
+)
+
+import "github.com/stretchr/testify/assert"
+
+func TestCheckGenre(t *testing.T) {
+
+	err := checkGenre("abc")
+	assert.NotNil(t, err)
+
+	err = checkGenre("json")
+	assert.Nil(t, err)
+}
+
+func TestNewLoaderConf(t *testing.T) {
+	conf := NewLoaderConf()
+	assert.Equal(t, ".", conf.delim)
+	assert.Equal(t, "yaml", conf.genre)
+	assert.Equal(t, "./conf/application.yaml", conf.path)
+}
+
+func TestWithDelim(t *testing.T) {
+	conf := NewLoaderConf(WithDelim(":"))
+	assert.Equal(t, ":", conf.delim)
+	assert.Equal(t, "yaml", conf.genre)
+	assert.Equal(t, "./conf/application.yaml", conf.path)
+}
+
+func TestWithPath(t *testing.T) {
+	conf := NewLoaderConf(WithPath("./conf/app.yaml"))
+	assert.Equal(t, ".", conf.delim)
+	assert.Equal(t, "yaml", conf.genre)
+	assert.Equal(t, absolutePath("./conf/app.yaml"), conf.path)
+}
+
+func TestWithGenre(t *testing.T) {
+	conf := NewLoaderConf(WithGenre("json"))
+	assert.Equal(t, ".", conf.delim)
+	assert.Equal(t, "json", conf.genre)
+	assert.Equal(t, "./conf/application.yaml", conf.path)
+}
diff --git a/config/config_loader_test.go b/config/config_loader_test.go
index 737b6f6..a3fade1 100644
--- a/config/config_loader_test.go
+++ b/config/config_loader_test.go
@@ -18,605 +18,624 @@
 package config
 
 import (
-	"context"
-	"path/filepath"
-	"sort"
-	"sync"
+	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"testing"
 )
 
-import (
-	"github.com/Workiva/go-datastructures/slice/skip"
-	gxset "github.com/dubbogo/gost/container/set"
-	gxpage "github.com/dubbogo/gost/hash/page"
-	"github.com/stretchr/testify/assert"
-	"go.uber.org/atomic"
-)
+import "github.com/stretchr/testify/assert"
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/cluster/cluster_impl"
-	"dubbo.apache.org/dubbo-go/v3/common"
-	"dubbo.apache.org/dubbo-go/v3/common/config"
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/extension"
-	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/common/proxy/proxy_factory"
-	"dubbo.apache.org/dubbo-go/v3/config_center"
-	"dubbo.apache.org/dubbo-go/v3/filter"
-	"dubbo.apache.org/dubbo-go/v3/metadata/service"
-	"dubbo.apache.org/dubbo-go/v3/protocol"
-	"dubbo.apache.org/dubbo-go/v3/registry"
-)
+import "dubbo.apache.org/dubbo-go/v3/config/testdata/config/service"
+
+func init() {
+	SetProviderService(new(service.OrderService))
+	SetProviderService(new(service.HelloService))
+}
 
 const (
-	mockConsumerConfigPath = "./testdata/consumer_config.yml"
-	mockProviderConfigPath = "./testdata/provider_config.yml"
+	configPath = "./testdata/application.yaml"
 )
 
-func TestConfigLoader(t *testing.T) {
-	conPath, err := filepath.Abs(mockConsumerConfigPath)
-	assert.NoError(t, err)
-	proPath, err := filepath.Abs(mockProviderConfigPath)
-	assert.NoError(t, err)
-
-	assert.Nil(t, consumerConfig)
-	assert.Equal(t, ConsumerConfig{}, GetConsumerConfig())
-	assert.Nil(t, providerConfig)
-	assert.Equal(t, ProviderConfig{}, GetProviderConfig())
-
-	err = ConsumerInit(conPath)
-	assert.NoError(t, err)
-	err = ProviderInit(proPath)
-	assert.NoError(t, err)
-
-	assert.NotNil(t, consumerConfig)
-	assert.NotEqual(t, ConsumerConfig{}, GetConsumerConfig())
-	assert.NotNil(t, providerConfig)
-	assert.NotEqual(t, ProviderConfig{}, GetProviderConfig())
-	assert.Equal(t, "soa.com.ikurento.user.UserProvider", GetConsumerConfig().References["UserProvider"].Params["serviceid"])
-}
-
 func TestLoad(t *testing.T) {
-	extension.SetFilter(constant.GracefulShutdownConsumerFilterKey, func() filter.Filter {
-		return &mockGracefulShutdownFilter{}
-	})
-	extension.SetFilter(constant.GracefulShutdownProviderFilterKey, func() filter.Filter {
-		return &mockGracefulShutdownFilter{}
+	Load(WithPath(configPath))
+
+	t.Run("application", func(t *testing.T) {
+		application := rootConfig.Application
+
+		assert.Equal(t, application.Organization, "dubbo.io")
+		assert.Equal(t, application.Name, "dubbo-go")
+		assert.Equal(t, application.Module, "local")
+		assert.Equal(t, application.Version, "1.0.0")
+		assert.Equal(t, application.Owner, "zhaoyunxing")
+		assert.Equal(t, application.Environment, "dev")
+		assert.Equal(t, application.MetadataType, "local")
 	})
 
-	doInitConsumer()
-	doInitProvider()
+	t.Run("registries", func(t *testing.T) {
+		registries := rootConfig.Registries
 
-	ms := &MockService{}
-	SetConsumerService(ms)
-	SetProviderService(ms)
-
-	extension.SetProtocol("registry", GetProtocol)
-	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
-	extension.SetProxyFactory("default", proxy_factory.NewDefaultProxyFactory)
-	GetApplicationConfig().MetadataType = "mock"
-	var mm *mockMetadataService
-	extension.SetLocalMetadataService("mock", func() (metadataService service.MetadataService, err error) {
-		if mm == nil {
-			mm = &mockMetadataService{
-				exportedServiceURLs: new(sync.Map),
-				lock:                new(sync.RWMutex),
-			}
-		}
-		return mm, nil
+		assert.Equal(t, 2, len(registries))
+		//address= nacos://127.0.0.1:8848 Translate Registry Address
+		assert.Equal(t, "nacos", registries["nacos"].Protocol)
+		assert.Equal(t, "10s", registries["zk"].Timeout)
 	})
-	Load()
-
-	assert.Equal(t, ms, GetRPCService(ms.Reference()))
-	ms2 := &struct {
-		MockService
-	}{}
-	RPCService(ms2)
-	assert.NotEqual(t, ms2, GetRPCService(ms2.Reference()))
-
-	conServices = map[string]common.RPCService{}
-	proServices = map[string]common.RPCService{}
-	err := common.ServiceMap.UnRegister("com.MockService", "mock",
-		common.ServiceKey("com.MockService", "huadong_idc", "1.0.0"))
-	assert.Nil(t, err)
-	consumerConfig = nil
-	providerConfig = nil
-}
 
-func TestLoadWithSingleReg(t *testing.T) {
-	doInitConsumerWithSingleRegistry()
-	mockInitProviderWithSingleRegistry()
+	//config-center
+	t.Run("config-center", func(t *testing.T) {
+		conf := rootConfig.ConfigCenter
 
-	ms := &MockService{}
-	SetConsumerService(ms)
-	SetProviderService(ms)
-
-	extension.SetProtocol("registry", GetProtocol)
-	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
-	extension.SetProxyFactory("default", proxy_factory.NewDefaultProxyFactory)
-	var mm *mockMetadataService
-	GetApplicationConfig().MetadataType = "mock"
-	extension.SetLocalMetadataService("mock", func() (metadataService service.MetadataService, err error) {
-		if mm == nil {
-			mm = &mockMetadataService{
-				exportedServiceURLs: new(sync.Map),
-				lock:                new(sync.RWMutex),
-			}
-		}
-		return mm, nil
+		assert.Equal(t, "nacos", conf.Protocol)
 	})
-	Load()
-
-	assert.Equal(t, ms, GetRPCService(ms.Reference()))
-	ms2 := &struct {
-		MockService
-	}{}
-	RPCService(ms2)
-	assert.NotEqual(t, ms2, GetRPCService(ms2.Reference()))
 
-	conServices = map[string]common.RPCService{}
-	proServices = map[string]common.RPCService{}
-	common.ServiceMap.UnRegister("com.MockService", "mock", common.ServiceKey("com.MockService", "huadong_idc", "1.0.0"))
-	consumerConfig = nil
-	providerConfig = nil
 }
 
-func TestWithNoRegLoad(t *testing.T) {
-	doInitConsumer()
-	doInitProvider()
-	providerConfig.Services["MockService"].Registry = ""
-	consumerConfig.References["MockService"].Registry = ""
-	ms := &MockService{}
-	SetConsumerService(ms)
-	SetProviderService(ms)
+//TestLoadConfigCenter test key  config_center、config-center 、configCenter
+func TestLoadConfigCenter(t *testing.T) {
 
-	extension.SetProtocol("registry", GetProtocol)
-	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
-	extension.SetProxyFactory("default", proxy_factory.NewDefaultProxyFactory)
-	var mm *mockMetadataService
-	GetApplicationConfig().MetadataType = "mock"
-	extension.SetLocalMetadataService("mock", func() (metadataService service.MetadataService, err error) {
-		if mm == nil {
-			mm = &mockMetadataService{
-				exportedServiceURLs: new(sync.Map),
-				lock:                new(sync.RWMutex),
-			}
-		}
-		return mm, nil
+	t.Run("config-center", func(t *testing.T) {
+		Load(WithPath("./testdata/config/center/conf-application.yaml"))
+		conf := rootConfig.ConfigCenter
+		assert.Equal(t, "nacos", conf.Protocol)
+		assert.Equal(t, "10s", conf.Timeout)
+		assert.Equal(t, "./logs", conf.LogDir)
 	})
-	Load()
-
-	assert.Equal(t, ms, GetRPCService(ms.Reference()))
-	ms2 := &struct {
-		MockService
-	}{}
-	RPCService(ms2)
-	assert.NotEqual(t, ms2, GetRPCService(ms2.Reference()))
-
-	conServices = map[string]common.RPCService{}
-	proServices = map[string]common.RPCService{}
-	err := common.ServiceMap.UnRegister("com.MockService", "mock",
-		common.ServiceKey("com.MockService", "huadong_idc", "1.0.0"))
-	assert.Nil(t, err)
-	common.ServiceMap.UnRegister("com.MockService", "mock", common.ServiceKey("com.MockService", "huadong_idc", "1.0.0"))
-	consumerConfig = nil
-	providerConfig = nil
 }
 
-func TestSetDefaultValue(t *testing.T) {
-	proConfig := &ProviderConfig{Registries: make(map[string]*RegistryConfig), Protocols: make(map[string]*ProtocolConfig)}
-	assert.Nil(t, proConfig.ApplicationConfig)
-	setDefaultValue(proConfig)
-	assert.Equal(t, proConfig.Registries["demoZK"].Address, "127.0.0.1:2181")
-	assert.Equal(t, proConfig.Registries["demoZK"].TimeoutStr, "3s")
-	assert.Equal(t, proConfig.Registries["demoZK"].Protocol, "zookeeper")
-	assert.Equal(t, proConfig.Protocols["dubbo"].Name, "dubbo")
-	assert.Equal(t, proConfig.Protocols["dubbo"].Port, "20000")
-	assert.NotNil(t, proConfig.ApplicationConfig)
-
-	conConfig := &ConsumerConfig{Registries: make(map[string]*RegistryConfig)}
-	assert.Nil(t, conConfig.ApplicationConfig)
-	setDefaultValue(conConfig)
-	assert.Equal(t, conConfig.Registries["demoZK"].Address, "127.0.0.1:2181")
-	assert.Equal(t, conConfig.Registries["demoZK"].TimeoutStr, "3s")
-	assert.Equal(t, conConfig.Registries["demoZK"].Protocol, "zookeeper")
-	assert.NotNil(t, conConfig.ApplicationConfig)
-
-}
-func TestConfigLoaderWithConfigCenter(t *testing.T) {
-	extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
-		return &config_center.MockDynamicConfigurationFactory{}
-	})
-
-	conPath, err := filepath.Abs("./testdata/consumer_config_with_configcenter.yml")
-	assert.NoError(t, err)
-	proPath, err := filepath.Abs(mockProviderConfigPath)
-	assert.NoError(t, err)
+func TestGetRegistriesConfig(t *testing.T) {
 
-	assert.Nil(t, consumerConfig)
-	assert.Equal(t, ConsumerConfig{}, GetConsumerConfig())
-	assert.Nil(t, providerConfig)
-	assert.Equal(t, ProviderConfig{}, GetProviderConfig())
+	t.Run("registry", func(t *testing.T) {
+		Load(WithPath("./testdata/config/registry/application.yaml"))
 
-	err = ConsumerInit(conPath)
-	assert.NoError(t, err)
-	err = configCenterRefreshConsumer()
-	assert.NoError(t, err)
-	err = ProviderInit(proPath)
-	assert.NoError(t, err)
-	err = configCenterRefreshProvider()
-	assert.NoError(t, err)
+		registries := rootConfig.Registries
 
-	assert.NotNil(t, consumerConfig)
-	assert.NotEqual(t, ConsumerConfig{}, GetConsumerConfig())
-	assert.NotNil(t, providerConfig)
-	assert.NotEqual(t, ProviderConfig{}, GetProviderConfig())
-
-	assert.Equal(t, "BDTService", consumerConfig.ApplicationConfig.Name)
-	assert.Equal(t, "127.0.0.1:2181", consumerConfig.Registries["hangzhouzk"].Address)
-}
-
-func TestConfigLoaderWithConfigCenterSingleRegistry(t *testing.T) {
-	consumerConfig = nil
-	providerConfig = nil
-	config.NewEnvInstance()
-	extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
-		return &config_center.MockDynamicConfigurationFactory{Content: `
-	dubbo.consumer.request_timeout=5s
-	dubbo.consumer.connect_timeout=5s
-	dubbo.application.organization=ikurento.com
-	dubbo.application.name=BDTService
-	dubbo.application.module=dubbogo user-info server
-	dubbo.application.version=0.0.1
-	dubbo.application.owner=ZX
-	dubbo.application.environment=dev
-	dubbo.registry.address=mock://127.0.0.1:2182
-	dubbo.service.com.ikurento.user.UserProvider.protocol=dubbo
-	dubbo.service.com.ikurento.user.UserProvider.interface=com.ikurento.user.UserProvider
-	dubbo.service.com.ikurento.user.UserProvider.loadbalance=random
-	dubbo.service.com.ikurento.user.UserProvider.warmup=100
-	dubbo.service.com.ikurento.user.UserProvider.cluster=failover
-	dubbo.protocols.jsonrpc1.name=jsonrpc
-	dubbo.protocols.jsonrpc1.ip=127.0.0.1
-	dubbo.protocols.jsonrpc1.port=20001
-`}
+		assert.Equal(t, 2, len(registries))
+		// nacos
+		assert.Equal(t, "nacos", registries["nacos"].Protocol)
+		assert.Equal(t, "5s", registries["nacos"].Timeout)
+		assert.Equal(t, "127.0.0.1:8848", registries["nacos"].Address)
+		assert.Equal(t, "dev", registries["nacos"].Group)
+		// zk
+		assert.Equal(t, "zookeeper", registries["zk"].Protocol)
+		assert.Equal(t, "10s", registries["zk"].Timeout)
+		assert.Equal(t, "127.0.0.1:2181", registries["zk"].Address)
+		assert.Equal(t, "test", registries["zk"].Group)
 	})
-
-	conPath, err := filepath.Abs("./testdata/consumer_config_with_configcenter.yml")
-	assert.NoError(t, err)
-	proPath, err := filepath.Abs(mockProviderConfigPath)
-	assert.NoError(t, err)
-
-	assert.Nil(t, consumerConfig)
-	assert.Equal(t, ConsumerConfig{}, GetConsumerConfig())
-	assert.Nil(t, providerConfig)
-	assert.Equal(t, ProviderConfig{}, GetProviderConfig())
-
-	err = ConsumerInit(conPath)
-	assert.NoError(t, err)
-	checkApplicationName(consumerConfig.ApplicationConfig)
-	err = configCenterRefreshConsumer()
-	checkRegistries(consumerConfig.Registries, consumerConfig.Registry)
-	assert.NoError(t, err)
-	err = ProviderInit(proPath)
-	assert.NoError(t, err)
-	checkApplicationName(providerConfig.ApplicationConfig)
-	err = configCenterRefreshProvider()
-	checkRegistries(providerConfig.Registries, providerConfig.Registry)
-	assert.NoError(t, err)
-
-	assert.NotNil(t, consumerConfig)
-	assert.NotEqual(t, ConsumerConfig{}, GetConsumerConfig())
-	assert.NotNil(t, providerConfig)
-	assert.NotEqual(t, ProviderConfig{}, GetProviderConfig())
-
-	assert.Equal(t, "BDTService", consumerConfig.ApplicationConfig.Name)
-	assert.Equal(t, "mock://127.0.0.1:2182", consumerConfig.Registries[constant.DEFAULT_KEY].Address)
-}
-
-func TestGetBaseConfig(t *testing.T) {
-	bc := GetBaseConfig()
-	assert.NotNil(t, bc)
-	_, found := bc.GetRemoteConfig("mock")
-	assert.False(t, found)
-}
-
-// mockInitProviderWithSingleRegistry will init a mocked providerConfig
-func mockInitProviderWithSingleRegistry() {
-	providerConfig = &ProviderConfig{
-		BaseConfig: BaseConfig{
-			ApplicationConfig: &ApplicationConfig{
-				Organization: "dubbo_org",
-				Name:         "dubbo",
-				Module:       "module",
-				Version:      "1.0.0",
-				Owner:        "dubbo",
-				Environment:  "test",
-			},
-		},
-
-		Registry: &RegistryConfig{
-			Address:  "mock://127.0.0.1:2181",
-			Username: "user1",
-			Password: "pwd1",
-		},
-		Registries: map[string]*RegistryConfig{},
-
-		Services: map[string]*ServiceConfig{
-			"MockService": {
-				InterfaceName: "com.MockService",
-				Protocol:      "mock",
-				Cluster:       "failover",
-				Loadbalance:   "random",
-				Retries:       "3",
-				Group:         "huadong_idc",
-				Version:       "1.0.0",
-				Methods: []*MethodConfig{
-					{
-						Name:        "GetUser",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-					{
-						Name:        "GetUser1",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-				},
-				exported: new(atomic.Bool),
-			},
-		},
-		Protocols: map[string]*ProtocolConfig{
-			"mock": {
-				Name: "mock",
-				Ip:   "127.0.0.1",
-				Port: "20000",
-			},
-		},
-	}
-}
-
-type mockMetadataService struct {
-	exportedServiceURLs *sync.Map
-	lock                *sync.RWMutex
-}
-
-func (m *mockMetadataService) GetExportedURLs(serviceInterface string, group string, version string, protocol string) ([]*common.URL, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) GetMetadataInfo(revision string) (*common.MetadataInfo, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) GetExportedServiceURLs() []*common.URL {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) GetMetadataServiceURL() *common.URL {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) SetMetadataServiceURL(url *common.URL) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) Reference() string {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) ServiceName() (string, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) ExportURL(url *common.URL) (bool, error) {
-	return m.addURL(m.exportedServiceURLs, url), nil
-}
-
-func (m *mockMetadataService) UnexportURL(*common.URL) error {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) SubscribeURL(*common.URL) (bool, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) UnsubscribeURL(*common.URL) error {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) PublishServiceDefinition(*common.URL) error {
-	return nil
-}
-
-func (m *mockMetadataService) MethodMapper() map[string]string {
-	panic("implement me")
 }
 
-func (m *mockMetadataService) GetSubscribedURLs() ([]*common.URL, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) GetServiceDefinition(string, string, string) (string, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) GetServiceDefinitionByServiceKey(string) (string, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) RefreshMetadata(string, string) (bool, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) Version() (string, error) {
-	panic("implement me")
-}
-
-func (m *mockMetadataService) addURL(targetMap *sync.Map, url *common.URL) bool {
-	var (
-		urlSet interface{}
-		loaded bool
-	)
-	logger.Debug(url.ServiceKey())
-	if urlSet, loaded = targetMap.LoadOrStore(url.ServiceKey(), skip.New(uint64(0))); loaded {
-		m.lock.RLock()
-		wantedUrl := urlSet.(*skip.SkipList).Get(url)
-		if len(wantedUrl) > 0 && wantedUrl[0] != nil {
-			m.lock.RUnlock()
-			return false
-		}
-		m.lock.RUnlock()
-	}
-	m.lock.Lock()
-	// double chk
-	wantedUrl := urlSet.(*skip.SkipList).Get(url)
-	if len(wantedUrl) > 0 && wantedUrl[0] != nil {
-		m.lock.Unlock()
-		return false
-	}
-	urlSet.(*skip.SkipList).Insert(url)
-	m.lock.Unlock()
-	return true
-}
-
-func (m *mockMetadataService) getAllService(services *sync.Map) []*common.URL {
-	// using skip list to dedup and sorting
-	var res []*common.URL
-	services.Range(func(key, value interface{}) bool {
-		urls := value.(*skip.SkipList)
-		for i := uint64(0); i < urls.Len(); i++ {
-			url := urls.ByPosition(i).(*common.URL)
-			if url.GetParam(constant.INTERFACE_KEY, url.Path) != constant.METADATA_SERVICE_NAME {
-				res = append(res, url)
-			}
-		}
-		return true
+func TestGetProtocolsConfig(t *testing.T) {
+
+	//t.Run("empty protocols", func(t *testing.T) {
+	//	Load(WithPath("./testdata/config/protocol/empty_application.yaml"))
+	//
+	//	protocols := rootConfig.Protocols
+	//	assert.NotNil(t, protocols)
+	//	// default
+	//	assert.Equal(t, "dubbo", protocols["default"].Name)
+	//	assert.Equal(t, "127.0.0.1", protocols["default"].Ip)
+	//	assert.Equal(t, 0, protocols["default"].Port)
+	//})
+
+	t.Run("protocols", func(t *testing.T) {
+		Load(WithPath("./testdata/config/protocol/application.yaml"))
+
+		protocols := rootConfig.Protocols
+		assert.NotNil(t, protocols)
+		// default
+		assert.Equal(t, "dubbo", protocols["dubbo"].Name)
+		assert.Equal(t, "127.0.0.1", protocols["dubbo"].Ip)
+		assert.Equal(t, string("20000"), protocols["dubbo"].Port)
 	})
-	sort.Sort(common.URLSlice(res))
-	return res
-}
-
-type mockServiceDiscoveryRegistry struct{}
-
-func (mr *mockServiceDiscoveryRegistry) GetURL() *common.URL {
-	panic("implement me")
-}
-
-func (mr *mockServiceDiscoveryRegistry) IsAvailable() bool {
-	panic("implement me")
-}
-
-func (mr *mockServiceDiscoveryRegistry) Destroy() {
-	panic("implement me")
-}
-
-func (mr *mockServiceDiscoveryRegistry) Register(*common.URL) error {
-	panic("implement me")
-}
-
-func (mr *mockServiceDiscoveryRegistry) UnRegister(*common.URL) error {
-	panic("implement me")
-}
-
-func (mr *mockServiceDiscoveryRegistry) Subscribe(*common.URL, registry.NotifyListener) error {
-	panic("implement me")
-}
-
-func (mr *mockServiceDiscoveryRegistry) UnSubscribe(*common.URL, registry.NotifyListener) error {
-	panic("implement me")
-}
-
-func (mr *mockServiceDiscoveryRegistry) GetServiceDiscovery() registry.ServiceDiscovery {
-	return &mockServiceDiscovery{}
-}
-
-type mockServiceDiscovery struct{}
-
-func (m *mockServiceDiscovery) String() string {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) Destroy() error {
-	panic("implement me")
 }
 
-func (m *mockServiceDiscovery) Register(registry.ServiceInstance) error {
-	return nil
-}
-
-func (m *mockServiceDiscovery) Update(registry.ServiceInstance) error {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) Unregister(registry.ServiceInstance) error {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) GetDefaultPageSize() int {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) GetServices() *gxset.HashSet {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) GetInstances(string) []registry.ServiceInstance {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) GetInstancesByPage(string, int, int) gxpage.Pager {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) GetHealthyInstancesByPage(string, int, int, bool) gxpage.Pager {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) GetRequestInstances([]string, int, int) map[string]gxpage.Pager {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) AddListener(registry.ServiceInstancesChangedListener) error {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) DispatchEventByServiceName(string) error {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) DispatchEventForInstances(string, []registry.ServiceInstance) error {
-	panic("implement me")
-}
-
-func (m *mockServiceDiscovery) DispatchEvent(*registry.ServiceInstancesChangedEvent) error {
-	panic("implement me")
-}
-
-func ConvertURLArrToIntfArr(urls []*common.URL) []interface{} {
-	if len(urls) == 0 {
-		return []interface{}{}
-	}
-
-	res := make([]interface{}, 0, len(urls))
-	for _, u := range urls {
-		res = append(res, u.String())
-	}
-	return res
-}
-
-type mockGracefulShutdownFilter struct{}
-
-func (f *mockGracefulShutdownFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
-	panic("implement me")
-}
+func TestGetProviderConfig(t *testing.T) {
+	// empty registry
+	t.Run("empty registry", func(t *testing.T) {
+		Load(WithPath("./testdata/config/provider/empty_registry_application.yaml"))
+		provider := rootConfig.Provider
+		assert.NotNil(t, constant.DEFAULT_Key, provider.Registry[0])
+	})
 
-func (f *mockGracefulShutdownFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
-	panic("implement me")
+	t.Run("root registry", func(t *testing.T) {
+		Load(WithPath("./testdata/config/provider/registry_application.yaml"))
+		provider := rootConfig.Provider
+		assert.NotNil(t, provider)
+	})
 }
 
-func (f *mockGracefulShutdownFilter) Set(name string, config interface{}) {
-	return
-}
+//
+//func TestLoadWithSingleReg(t *testing.T) {
+//	reference.doInitConsumerWithSingleRegistry()
+//	mockInitProviderWithSingleRegistry()
+//
+//	ms := &MockService{}
+//	instance.SetConsumerService(ms)
+//	instance.SetProviderService(ms)
+//
+//	extension.SetProtocol("registry", reference.GetProtocol)
+//	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
+//	extension.SetProxyFactory("default", proxy_factory.NewDefaultProxyFactory)
+//	var mm *mockMetadataService
+//	GetApplicationConfig().MetadataType = "mock"
+//	extension.SetLocalMetadataService("mock", func() (metadataService service.MetadataService, err error) {
+//		if mm == nil {
+//			mm = &mockMetadataService{
+//				exportedServiceURLs: new(sync.Map),
+//				lock:                new(sync.RWMutex),
+//			}
+//		}
+//		return mm, nil
+//	})
+//	Load()
+//
+//	assert.Equal(t, ms, GetRPCService(ms.Reference()))
+//	ms2 := &struct {
+//		MockService
+//	}{}
+//	RPCService(ms2)
+//	assert.NotEqual(t, ms2, GetRPCService(ms2.Reference()))
+//
+//	service2.conServices = map[string]common.RPCService{}
+//	service2.proServices = map[string]common.RPCService{}
+//	common.ServiceMap.UnRegister("com.MockService", "mock", common.ServiceKey("com.MockService", "huadong_idc", "1.0.0"))
+//	consumerConfig = nil
+//	providerConfig = nil
+//}
+//
+//func TestWithNoRegLoad(t *testing.T) {
+//	reference.doInitConsumer()
+//	service2.doInitProvider()
+//	providerConfig.Services["MockService"].Registry = ""
+//	consumerConfig.References["MockService"].Registry = ""
+//	ms := &MockService{}
+//	instance.SetConsumerService(ms)
+//	instance.SetProviderService(ms)
+//
+//	extension.SetProtocol("registry", reference.GetProtocol)
+//	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
+//	extension.SetProxyFactory("default", proxy_factory.NewDefaultProxyFactory)
+//	var mm *mockMetadataService
+//	GetApplicationConfig().MetadataType = "mock"
+//	extension.SetLocalMetadataService("mock", func() (metadataService service.MetadataService, err error) {
+//		if mm == nil {
+//			mm = &mockMetadataService{
+//				exportedServiceURLs: new(sync.Map),
+//				lock:                new(sync.RWMutex),
+//			}
+//		}
+//		return mm, nil
+//	})
+//	Load()
+//
+//	assert.Equal(t, ms, GetRPCService(ms.Reference()))
+//	ms2 := &struct {
+//		MockService
+//	}{}
+//	RPCService(ms2)
+//	assert.NotEqual(t, ms2, GetRPCService(ms2.Reference()))
+//
+//	service2.conServices = map[string]common.RPCService{}
+//	service2.proServices = map[string]common.RPCService{}
+//	err := common.ServiceMap.UnRegister("com.MockService", "mock",
+//		common.ServiceKey("com.MockService", "huadong_idc", "1.0.0"))
+//	assert.Nil(t, err)
+//	common.ServiceMap.UnRegister("com.MockService", "mock", common.ServiceKey("com.MockService", "huadong_idc", "1.0.0"))
+//	consumerConfig = nil
+//	providerConfig = nil
+//}
+//
+//func TestSetDefaultValue(t *testing.T) {
+//	proConfig := &provider.ProviderConfig{Registries: make(map[string]*registry2.RegistryConfig), Protocols: make(map[string]*protocol2.ProtocolConfig)}
+//	assert.Nil(t, proConfig.ApplicationConfig)
+//	setDefaultValue(proConfig)
+//	assert.Equal(t, proConfig.Registries["demoZK"].Address, "127.0.0.1:2181")
+//	assert.Equal(t, proConfig.Registries["demoZK"].TimeoutStr, "3s")
+//	assert.Equal(t, proConfig.Registries["demoZK"].Protocol, "zookeeper")
+//	assert.Equal(t, proConfig.Protocols["dubbo"].Name, "dubbo")
+//	assert.Equal(t, proConfig.Protocols["dubbo"].Port, "20000")
+//	assert.NotNil(t, proConfig.ApplicationConfig)
+//
+//	conConfig := &consumer.ShutdownConfig{Registries: make(map[string]*registry2.RegistryConfig)}
+//	assert.Nil(t, conConfig.ApplicationConfig)
+//	setDefaultValue(conConfig)
+//	assert.Equal(t, conConfig.Registries["demoZK"].Address, "127.0.0.1:2181")
+//	assert.Equal(t, conConfig.Registries["demoZK"].TimeoutStr, "3s")
+//	assert.Equal(t, conConfig.Registries["demoZK"].Protocol, "zookeeper")
+//	assert.NotNil(t, conConfig.ApplicationConfig)
+//
+//}
+//func TestConfigLoaderWithConfigCenter(t *testing.T) {
+//	extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
+//		return &config_center.MockDynamicConfigurationFactory{}
+//	})
+//
+//	conPath, err := filepath.Abs("./testdata/consumer_config_with_configcenter.yml")
+//	assert.NoError(t, err)
+//	proPath, err := filepath.Abs(mockProviderConfigPath)
+//	assert.NoError(t, err)
+//
+//	assert.Nil(t, consumerConfig)
+//	assert.Equal(t, consumer.ShutdownConfig{}, GetConsumerConfig())
+//	assert.Nil(t, providerConfig)
+//	assert.Equal(t, provider.ProviderConfig{}, GetProviderConfig())
+//
+//	err = consumer.ConsumerInit(conPath)
+//	assert.NoError(t, err)
+//	err = consumer.configCenterRefreshConsumer()
+//	assert.NoError(t, err)
+//	err = provider.ProviderInit(proPath)
+//	assert.NoError(t, err)
+//	err = provider.configCenterRefreshProvider()
+//	assert.NoError(t, err)
+//
+//	assert.NotNil(t, consumerConfig)
+//	assert.NotEqual(t, consumer.ShutdownConfig{}, GetConsumerConfig())
+//	assert.NotNil(t, providerConfig)
+//	assert.NotEqual(t, provider.ProviderConfig{}, GetProviderConfig())
+//
+//	assert.Equal(t, "BDTService", consumerConfig.ApplicationConfig.Name)
+//	assert.Equal(t, "127.0.0.1:2181", consumerConfig.Registries["hangzhouzk"].Address)
+//}
+//
+//func TestConfigLoaderWithConfigCenterSingleRegistry(t *testing.T) {
+//	consumerConfig = nil
+//	providerConfig = nil
+//	config.NewEnvInstance()
+//	extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
+//		return &config_center.MockDynamicConfigurationFactory{Content: `
+//	dubbo.consumer.request_timeout=5s
+//	dubbo.consumer.connect_timeout=5s
+//	dubbo.applicationConfig.organization=ikurento.com
+//	dubbo.applicationConfig.name=BDTService
+//	dubbo.applicationConfig.module=dubbogo user-info server
+//	dubbo.applicationConfig.version=0.0.1
+//	dubbo.applicationConfig.owner=ZX
+//	dubbo.applicationConfig.environment=dev
+//	dubbo.registry.address=mock://127.0.0.1:2182
+//	dubbo.service.com.ikurento.user.UserProvider.protocol=dubbo
+//	dubbo.service.com.ikurento.user.UserProvider.interface=com.ikurento.user.UserProvider
+//	dubbo.service.com.ikurento.user.UserProvider.loadbalance=random
+//	dubbo.service.com.ikurento.user.UserProvider.warmup=100
+//	dubbo.service.com.ikurento.user.UserProvider.cluster=failover
+//	dubbo.protocols.jsonrpc1.name=jsonrpc
+//	dubbo.protocols.jsonrpc1.ip=127.0.0.1
+//	dubbo.protocols.jsonrpc1.port=20001
+//`}
+//	})
+//
+//	conPath, err := filepath.Abs("./testdata/consumer_config_with_configcenter.yml")
+//	assert.NoError(t, err)
+//	proPath, err := filepath.Abs(mockProviderConfigPath)
+//	assert.NoError(t, err)
+//
+//	assert.Nil(t, consumerConfig)
+//	assert.Equal(t, consumer.ShutdownConfig{}, GetConsumerConfig())
+//	assert.Nil(t, providerConfig)
+//	assert.Equal(t, provider.ProviderConfig{}, GetProviderConfig())
+//
+//	err = consumer.ConsumerInit(conPath)
+//	assert.NoError(t, err)
+//	checkApplicationName(consumerConfig.ApplicationConfig)
+//	err = consumer.configCenterRefreshConsumer()
+//	checkRegistries(consumerConfig.Registries, consumerConfig.Registry)
+//	assert.NoError(t, err)
+//	err = provider.ProviderInit(proPath)
+//	assert.NoError(t, err)
+//	checkApplicationName(providerConfig.ApplicationConfig)
+//	err = provider.configCenterRefreshProvider()
+//	checkRegistries(providerConfig.Registries, providerConfig.Registry)
+//	assert.NoError(t, err)
+//
+//	assert.NotNil(t, consumerConfig)
+//	assert.NotEqual(t, consumer.ShutdownConfig{}, GetConsumerConfig())
+//	assert.NotNil(t, providerConfig)
+//	assert.NotEqual(t, provider.ProviderConfig{}, GetProviderConfig())
+//
+//	assert.Equal(t, "BDTService", consumerConfig.ApplicationConfig.Name)
+//	assert.Equal(t, "mock://127.0.0.1:2182", consumerConfig.Registries[constant.DEFAULT_KEY].Address)
+//}
+//
+//func TestGetBaseConfig(t *testing.T) {
+//	bc := GetBaseConfig()
+//	assert.NotNil(t, bc)
+//	_, found := bc.GetRemoteConfig("mock")
+//	assert.False(t, found)
+//}
+//
+//// mockInitProviderWithSingleRegistry will init a mocked providerConfig
+//func mockInitProviderWithSingleRegistry() {
+//	providerConfig = &provider.ProviderConfig{
+//		BaseConfig: base.ShutdownConfig{
+//			applicationConfig.ShutdownConfig: &applicationConfig.ShutdownConfig{
+//				Organization: "dubbo_org",
+//				Name:         "dubbo",
+//				Module:       "module",
+//				Version:      "1.0.0",
+//				Owner:        "dubbo",
+//				Environment:  "test",
+//			},
+//		},
+//
+//		Registry: &registry2.RegistryConfig{
+//			Address:  "mock://127.0.0.1:2181",
+//			Username: "user1",
+//			Password: "pwd1",
+//		},
+//		Registries: map[string]*registry2.RegistryConfig{},
+//
+//		Services: map[string]*service2.ShutdownConfig{
+//			"MockService": {
+//				InterfaceName: "com.MockService",
+//				Protocol:      "mock",
+//				Cluster:       "failover",
+//				Loadbalance:   "random",
+//				Retries:       "3",
+//				Group:         "huadong_idc",
+//				Version:       "1.0.0",
+//				Methods: []*method.MethodConfig{
+//					{
+//						Name:        "GetUser",
+//						Retries:     "2",
+//						LoadBalance: "random",
+//						Weight:      200,
+//					},
+//					{
+//						Name:        "GetUser1",
+//						Retries:     "2",
+//						LoadBalance: "random",
+//						Weight:      200,
+//					},
+//				},
+//				exported: new(atomic.Bool),
+//			},
+//		},
+//		Protocols: map[string]*protocol2.ProtocolConfig{
+//			"mock": {
+//				Name: "mock",
+//				Ip:   "127.0.0.1",
+//				Port: "20000",
+//			},
+//		},
+//	}
+//}
+//
+//type mockMetadataService struct {
+//	exportedServiceURLs *sync.Map
+//	lock                *sync.RWMutex
+//}
+//
+//func (m *mockMetadataService) GetExportedURLs(serviceInterface string, group string, version string, protocol string) ([]*common.URL, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) GetMetadataInfo(revision string) (*common.MetadataInfo, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) GetExportedServiceURLs() []*common.URL {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) GetMetadataServiceURL() *common.URL {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) SetMetadataServiceURL(url *common.URL) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) Reference() string {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) ServiceName() (string, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) ExportURL(url *common.URL) (bool, error) {
+//	return m.addURL(m.exportedServiceURLs, url), nil
+//}
+//
+//func (m *mockMetadataService) UnexportURL(*common.URL) error {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) SubscribeURL(*common.URL) (bool, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) UnsubscribeURL(*common.URL) error {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) PublishServiceDefinition(*common.URL) error {
+//	return nil
+//}
+//
+//func (m *mockMetadataService) MethodMapper() map[string]string {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) GetSubscribedURLs() ([]*common.URL, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) GetServiceDefinition(string, string, string) (string, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) GetServiceDefinitionByServiceKey(string) (string, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) RefreshMetadata(string, string) (bool, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) Version() (string, error) {
+//	panic("implement me")
+//}
+//
+//func (m *mockMetadataService) addURL(targetMap *sync.Map, url *common.URL) bool {
+//	var (
+//		urlSet interface{}
+//		loaded bool
+//	)
+//	logger.Debug(url.ServiceKey())
+//	if urlSet, loaded = targetMap.LoadOrStore(url.ServiceKey(), skip.New(uint64(0))); loaded {
+//		m.lock.RLock()
+//		wantedUrl := urlSet.(*skip.SkipList).Get(url)
+//		if len(wantedUrl) > 0 && wantedUrl[0] != nil {
+//			m.lock.RUnlock()
+//			return false
+//		}
+//		m.lock.RUnlock()
+//	}
+//	m.lock.Lock()
+//	// double chk
+//	wantedUrl := urlSet.(*skip.SkipList).Get(url)
+//	if len(wantedUrl) > 0 && wantedUrl[0] != nil {
+//		m.lock.Unlock()
+//		return false
+//	}
+//	urlSet.(*skip.SkipList).Insert(url)
+//	m.lock.Unlock()
+//	return true
+//}
+//
+//func (m *mockMetadataService) getAllService(services *sync.Map) []*common.URL {
+//	// using skip list to dedup and sorting
+//	var res []*common.URL
+//	services.Range(func(key, value interface{}) bool {
+//		urls := value.(*skip.SkipList)
+//		for i := uint64(0); i < urls.Len(); i++ {
+//			url := urls.ByPosition(i).(*common.URL)
+//			if url.GetParam(constant.INTERFACE_KEY, url.Path) != constant.METADATA_SERVICE_NAME {
+//				res = append(res, url)
+//			}
+//		}
+//		return true
+//	})
+//	sort.Sort(common.URLSlice(res))
+//	return res
+//}
+//
+//type mockServiceDiscoveryRegistry struct{}
+//
+//func (mr *mockServiceDiscoveryRegistry) GetURL() *common.URL {
+//	panic("implement me")
+//}
+//
+//func (mr *mockServiceDiscoveryRegistry) IsAvailable() bool {
+//	panic("implement me")
+//}
+//
+//func (mr *mockServiceDiscoveryRegistry) Destroy() {
+//	panic("implement me")
+//}
+//
+//func (mr *mockServiceDiscoveryRegistry) Register(*common.URL) error {
+//	panic("implement me")
+//}
+//
+//func (mr *mockServiceDiscoveryRegistry) UnRegister(*common.URL) error {
+//	panic("implement me")
+//}
+//
+//func (mr *mockServiceDiscoveryRegistry) Subscribe(*common.URL, registry.NotifyListener) error {
+//	panic("implement me")
+//}
+//
+//func (mr *mockServiceDiscoveryRegistry) UnSubscribe(*common.URL, registry.NotifyListener) error {
+//	panic("implement me")
+//}
+//
+//func (mr *mockServiceDiscoveryRegistry) GetServiceDiscovery() registry.ServiceDiscovery {
+//	return &mockServiceDiscovery{}
+//}
+//
+//type mockServiceDiscovery struct{}
+//
+//func (m *mockServiceDiscovery) String() string {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) Destroy() error {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) Register(registry.ServiceInstance) error {
+//	return nil
+//}
+//
+//func (m *mockServiceDiscovery) Update(registry.ServiceInstance) error {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) Unregister(registry.ServiceInstance) error {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) GetDefaultPageSize() int {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) GetServices() *gxset.HashSet {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) GetInstances(string) []registry.ServiceInstance {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) GetInstancesByPage(string, int, int) gxpage.Pager {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) GetHealthyInstancesByPage(string, int, int, bool) gxpage.Pager {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) GetRequestInstances([]string, int, int) map[string]gxpage.Pager {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) AddListener(registry.ServiceInstancesChangedListener) error {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) DispatchEventByServiceName(string) error {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) DispatchEventForInstances(string, []registry.ServiceInstance) error {
+//	panic("implement me")
+//}
+//
+//func (m *mockServiceDiscovery) DispatchEvent(*registry.ServiceInstancesChangedEvent) error {
+//	panic("implement me")
+//}
+//
+//func ConvertURLArrToIntfArr(urls []*common.URL) []interface{} {
+//	if len(urls) == 0 {
+//		return []interface{}{}
+//	}
+//
+//	res := make([]interface{}, 0, len(urls))
+//	for _, u := range urls {
+//		res = append(res, u.String())
+//	}
+//	return res
+//}
+//
+//type mockGracefulShutdownFilter struct{}
+//
+//func (f *mockGracefulShutdownFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+//	panic("implement me")
+//}
+//
+//func (f *mockGracefulShutdownFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+//	panic("implement me")
+//}
+//
+//func (f *mockGracefulShutdownFilter) Set(name string, config interface{}) {
+//	return
+//}
diff --git a/config/config_utils.go b/config/config_utils.go
index 5464502..868567f 100644
--- a/config/config_utils.go
+++ b/config/config_utils.go
@@ -19,6 +19,8 @@ package config
 
 import (
 	"fmt"
+	"github.com/go-playground/validator/v10"
+	"github.com/pkg/errors"
 	"regexp"
 	"strings"
 )
@@ -27,6 +29,12 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 )
 
+var validate *validator.Validate
+
+func init() {
+	validate = validator.New()
+}
+
 func mergeValue(str1, str2, def string) string {
 	if str1 == "" && str2 == "" {
 		return def
@@ -63,3 +71,37 @@ func removeMinus(strArr []string) string {
 	normalStr = reg.ReplaceAllString(strings.Trim(normalStr, ","), ",")
 	return normalStr
 }
+
+// removeDuplicateElement remove duplicate element
+func removeDuplicateElement(items []string) []string {
+	result := make([]string, 0, len(items))
+	temp := map[string]struct{}{}
+	for _, item := range items {
+		if _, ok := temp[item]; !ok && item != "" {
+			temp[item] = struct{}{}
+			result = append(result, item)
+		}
+	}
+	return result
+}
+
+// translateRegistryIds string "nacos,zk" => ["nacos","zk"]
+func translateRegistryIds(registryIds []string) []string {
+	ids := make([]string, 0)
+	for _, id := range registryIds {
+		ids = append(ids, strings.Split(id, ",")...)
+	}
+	return removeDuplicateElement(ids)
+}
+
+func verify(s interface{}) error {
+	if err := validate.Struct(s); err != nil {
+		errs := err.(validator.ValidationErrors)
+		var slice []string
+		for _, msg := range errs {
+			slice = append(slice, msg.Error())
+		}
+		return errors.New(strings.Join(slice, ","))
+	}
+	return nil
+}
diff --git a/config/consumer_config.go b/config/consumer_config.go
index e3c0e0a..163f946 100644
--- a/config/consumer_config.go
+++ b/config/consumer_config.go
@@ -18,19 +18,18 @@
 package config
 
 import (
-	"bytes"
+	"dubbo.apache.org/dubbo-go/v3/common/logger"
+	"dubbo.apache.org/dubbo-go/v3/config/generic"
+	"fmt"
 	"time"
 )
 
 import (
 	"github.com/creasty/defaults"
-	perrors "github.com/pkg/errors"
 )
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/common/yaml"
 )
 
 const (
@@ -39,29 +38,36 @@ const (
 
 // ConsumerConfig is Consumer default configuration
 type ConsumerConfig struct {
-	BaseConfig   `yaml:",inline" property:"base"`
-	configCenter `yaml:"-"`
-	Filter       string `yaml:"filter" json:"filter,omitempty" property:"filter"`
+	//root.RootConfig         `yaml:",inline" property:"base"`
+	//center.ConsumerConfig `yaml:"-"`
+	Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
 	// client
 	Connect_Timeout string `default:"100ms"  yaml:"connect_timeout" json:"connect_timeout,omitempty" property:"connect_timeout"`
 	ConnectTimeout  time.Duration
 
-	Registry   *RegistryConfig            `yaml:"registry" json:"registry,omitempty" property:"registry"`
-	Registries map[string]*RegistryConfig `default:"{}" yaml:"registries" json:"registries" property:"registries"`
+	Registry []string `yaml:"registry" json:"registry,omitempty" property:"registry"`
+	//Registries map[string]*RegistryConfig `default:"{}" yaml:"registriesConfig" json:"registriesConfig" property:"registriesConfig"`
 
 	Request_Timeout string `yaml:"request_timeout" default:"5s" json:"request_timeout,omitempty" property:"request_timeout"`
 	RequestTimeout  time.Duration
 	ProxyFactory    string `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty" property:"proxy_factory"`
 	Check           *bool  `yaml:"check"  json:"check,omitempty" property:"check"`
 
-	References     map[string]*ReferenceConfig `yaml:"references" json:"references,omitempty" property:"references"`
-	ProtocolConf   interface{}                 `yaml:"protocol_conf" json:"protocol_conf,omitempty" property:"protocol_conf"`
-	FilterConf     interface{}                 `yaml:"filter_conf" json:"filter_conf,omitempty" property:"filter_conf"`
-	ShutdownConfig *ShutdownConfig             `yaml:"shutdown_conf" json:"shutdown_conf,omitempty" property:"shutdown_conf"`
-	ConfigType     map[string]string           `yaml:"config_type" json:"config_type,omitempty" property:"config_type"`
+	References   map[string]*ReferenceConfig `yaml:"references" json:"references,omitempty" property:"references"`
+	ProtocolConf interface{}                 `yaml:"protocol_conf" json:"protocol_conf,omitempty" property:"protocol_conf"`
+	FilterConf   interface{}                 `yaml:"filter_conf" json:"filter_conf,omitempty" property:"filter_conf"`
+	//ShutdownConfig *ShutdownConfig                             `yaml:"shutdown_conf" json:"shutdown_conf,omitempty" property:"shutdown_conf"`
+	ConfigType map[string]string `yaml:"config_type" json:"config_type,omitempty" property:"config_type"`
+
+	rootConfig *RootConfig
 }
 
-// UnmarshalYAML unmarshals the ConsumerConfig by @unmarshal function
+// Prefix dubbo.consumer
+func (ConsumerConfig) Prefix() string {
+	return constant.ConsumerConfigPrefix
+}
+
+// UnmarshalYAML unmarshal the ConsumerConfig by @unmarshal function
 func (c *ConsumerConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	if err := defaults.Set(c); err != nil {
 		return err
@@ -70,74 +76,209 @@ func (c *ConsumerConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
 	return unmarshal((*plain)(c))
 }
 
-// nolint
-func (*ConsumerConfig) Prefix() string {
-	return constant.ConsumerConfigPrefix
+func (c *ConsumerConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(c)
+	return verify(c)
 }
 
-// SetConsumerConfig sets consumerConfig by @c
-func SetConsumerConfig(c ConsumerConfig) {
-	consumerConfig = &c
+func (c *ConsumerConfig) Validate(rootConfig *RootConfig) {
+	for k, _ := range c.References {
+		c.References[k].Validate(rootConfig)
+	}
+	c.rootConfig = rootConfig
+	// todo set default application
 }
 
-// ConsumerInit loads config file to init consumer config
-func ConsumerInit(confConFile string) error {
-	if confConFile == "" {
-		return perrors.Errorf("application configure(consumer) file name is nil")
-	}
-	consumerConfig = &ConsumerConfig{}
-	fileStream, err := yaml.UnmarshalYMLConfig(confConFile, consumerConfig)
-	if err != nil {
-		return perrors.Errorf("unmarshalYmlConfig error %v", perrors.WithStack(err))
-	}
-	consumerConfig.fileStream = bytes.NewBuffer(fileStream)
-	// set method interfaceId & interfaceName
-	for k, v := range consumerConfig.References {
-		// set id for reference
-		for _, n := range consumerConfig.References[k].Methods {
-			n.InterfaceName = v.InterfaceName
-			n.InterfaceId = k
-		}
-	}
-	if consumerConfig.Request_Timeout != "" {
-		if consumerConfig.RequestTimeout, err = time.ParseDuration(consumerConfig.Request_Timeout); err != nil {
-			return perrors.WithMessagef(err, "time.ParseDuration(Request_Timeout{%#v})", consumerConfig.Request_Timeout)
+func (c *ConsumerConfig) Load() {
+	for key, ref := range c.References {
+		if ref.Generic {
+			genericService := generic.NewGenericService(key)
+			SetConsumerService(genericService)
 		}
-		if consumerConfig.RequestTimeout >= time.Duration(MaxWheelTimeSpan) {
-			return perrors.WithMessagef(err, "request_timeout %s should be less than %s",
-				consumerConfig.Request_Timeout, time.Duration(MaxWheelTimeSpan))
+		rpcService := GetConsumerService(key)
+		if rpcService == nil {
+			logger.Warnf("%s does not exist!", key)
+			continue
 		}
+		ref.id = key
+		ref.Refer(rpcService)
+		ref.Implement(rpcService)
 	}
-	if consumerConfig.Connect_Timeout != "" {
-		if consumerConfig.ConnectTimeout, err = time.ParseDuration(consumerConfig.Connect_Timeout); err != nil {
-			return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
+
+	// todo Write current configuration to cache file.
+	//if c.CacheFile != "" {
+	//	if data, err := yaml.MarshalYML(c); err != nil {
+	//		logger.Errorf("Marshal consumer config err: %s", err.Error())
+	//	} else {
+	//		if err := ioutil.WriteFile(c.CacheFile, data, 0666); err != nil {
+	//			logger.Errorf("Write consumer config cache file err: %s", err.Error())
+	//		}
+	//	}
+	//}
+
+	// wait for invoker is available, if wait over default 3s, then panic
+	var count int
+	for {
+		checkok := true
+		for _, refconfig := range c.References {
+			if (refconfig.Check != nil && *refconfig.Check) ||
+				(refconfig.Check == nil && c.Check != nil && *c.Check) ||
+				(refconfig.Check == nil && c.Check == nil) { // default to true
+
+				if refconfig.invoker != nil && !refconfig.invoker.IsAvailable() {
+					checkok = false
+					count++
+					if count > maxWait {
+						errMsg := fmt.Sprintf("Failed to check the status of the service %v. No provider available for the service to the consumer use dubbo version %v", refconfig.InterfaceName, constant.Version)
+						logger.Error(errMsg)
+						panic(errMsg)
+					}
+					time.Sleep(time.Second * 1)
+					break
+				}
+				if refconfig.invoker == nil {
+					logger.Warnf("The interface %s invoker not exist, may you should check your interface config.", refconfig.InterfaceName)
+				}
+			}
+		}
+		if checkok {
+			break
 		}
 	}
 
-	logger.Debugf("consumer config{%#v}\n", consumerConfig)
+}
+
+// SetConsumerConfig sets consumerConfig by @c
+func SetConsumerConfig(c ConsumerConfig) {
+	rootConfig.Consumer = &c
+}
+
+// ConsumerInit loads config file to init consumer config
+func ConsumerInit(confConFile string) error {
+	//if confConFile == "" {
+	//	return perrors.Errorf("applicationConfig configure(consumer) file name is nil")
+	//}
+	//consumerConfig = &ShutdownConfig{}
+	//fileStream, err := yaml.UnmarshalYMLConfig(confConFile, consumerConfig)
+	//if err != nil {
+	//	return perrors.Errorf("unmarshalYmlConfig error %v", perrors.WithStack(err))
+	//}
+	//consumerConfig.fileStream = bytes.NewBuffer(fileStream)
+	//// set method interfaceId & interfaceName
+	//for k, v := range consumerConfig.References {
+	//	// set id for reference
+	//	for _, n := range consumerConfig.References[k].Methods {
+	//		n.InterfaceName = v.InterfaceName
+	//		n.InterfaceId = k
+	//	}
+	//}
+	//if consumerConfig.Request_Timeout != "" {
+	//	if consumerConfig.RequestTimeout, err = time.ParseDuration(consumerConfig.Request_Timeout); err != nil {
+	//		return perrors.WithMessagef(err, "time.ParseDuration(Request_Timeout{%#v})", consumerConfig.Request_Timeout)
+	//	}
+	//	if consumerConfig.RequestTimeout >= time.Duration(MaxWheelTimeSpan) {
+	//		return perrors.WithMessagef(err, "request_timeout %s should be less than %s",
+	//			consumerConfig.Request_Timeout, time.Duration(MaxWheelTimeSpan))
+	//	}
+	//}
+	//if consumerConfig.Connect_Timeout != "" {
+	//	if consumerConfig.ConnectTimeout, err = time.ParseDuration(consumerConfig.Connect_Timeout); err != nil {
+	//		return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
+	//	}
+	//}
+	//
+	//logger.Debugf("consumer config{%#v}\n", consumerConfig)
 
 	return nil
 }
 
 func configCenterRefreshConsumer() error {
-	// fresh it
-	var err error
-	if consumerConfig.Request_Timeout != "" {
-		if consumerConfig.RequestTimeout, err = time.ParseDuration(consumerConfig.Request_Timeout); err != nil {
-			return perrors.WithMessagef(err, "time.ParseDuration(Request_Timeout{%#v})", consumerConfig.Request_Timeout)
-		}
+	//// fresh it
+	//var err error
+	//if consumerConfig.Request_Timeout != "" {
+	//	if consumerConfig.RequestTimeout, err = time.ParseDuration(consumerConfig.Request_Timeout); err != nil {
+	//		return perrors.WithMessagef(err, "time.ParseDuration(Request_Timeout{%#v})", consumerConfig.Request_Timeout)
+	//	}
+	//}
+	//if consumerConfig.Connect_Timeout != "" {
+	//	if consumerConfig.ConnectTimeout, err = time.ParseDuration(consumerConfig.Connect_Timeout); err != nil {
+	//		return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
+	//	}
+	//}
+	//if consumerConfig.ConfigCenterConfig != nil {
+	//	consumerConfig.SetFatherConfig(consumerConfig)
+	//	if err = consumerConfig.startConfigCenter((*consumerConfig).BaseConfig); err != nil {
+	//		return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
+	//	}
+	//	consumerConfig.fresh()
+	//}
+	return nil
+}
+
+///////////////////////////////////// consumer config api
+// ConsumerConfigOpt is the options to init ConsumerConfig
+type ConsumerConfigOpt func(config *ConsumerConfig) *ConsumerConfig
+
+// NewEmptyConsumerConfig returns default ConsumerConfig
+// with connection timeout = 3s, request timeout = 3s
+func NewEmptyConsumerConfig() *ConsumerConfig {
+	check := true
+	newConsumerConfig := &ConsumerConfig{
+		//Registries:     make(map[string]*RegistryConfig, 8),
+		References:     make(map[string]*ReferenceConfig, 8),
+		ConnectTimeout: 3 * time.Second,
+		RequestTimeout: 3 * time.Second,
+		Check:          &check,
 	}
-	if consumerConfig.Connect_Timeout != "" {
-		if consumerConfig.ConnectTimeout, err = time.ParseDuration(consumerConfig.Connect_Timeout); err != nil {
-			return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
-		}
+	return newConsumerConfig
+}
+
+// NewConsumerConfig returns ConsumerConfig with @opts
+func NewConsumerConfig(opts ...ConsumerConfigOpt) *ConsumerConfig {
+	newConfig := NewEmptyConsumerConfig()
+	for _, v := range opts {
+		v(newConfig)
 	}
-	if consumerConfig.ConfigCenterConfig != nil {
-		consumerConfig.SetFatherConfig(consumerConfig)
-		if err = consumerConfig.startConfigCenter((*consumerConfig).BaseConfig); err != nil {
-			return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
-		}
-		consumerConfig.fresh()
+	return newConfig
+}
+
+// WithRootConfig returns ConsumerConfigOpt with given @rootConfig
+func WithRootConfig(rootConfig *RootConfig) ConsumerConfigOpt {
+	return func(config *ConsumerConfig) *ConsumerConfig {
+		config.rootConfig = rootConfig
+		return config
+	}
+}
+
+// WithConsumerReferenceConfig returns ConsumerConfigOpt with
+func WithConsumerReferenceConfig(referenceKey string, refConfig *ReferenceConfig) ConsumerConfigOpt {
+	return func(config *ConsumerConfig) *ConsumerConfig {
+		config.References[referenceKey] = refConfig
+		return config
+	}
+}
+
+// WithConsumerConnTimeout returns ConsumerConfigOpt with given consumer conn @timeout
+func WithConsumerConnTimeout(timeout time.Duration) ConsumerConfigOpt {
+	return func(config *ConsumerConfig) *ConsumerConfig {
+		config.ConnectTimeout = timeout
+		return config
+	}
+}
+
+// WithConsumerRequestTimeout returns ConsumerConfigOpt with given consumer request @timeout
+func WithConsumerRequestTimeout(timeout time.Duration) ConsumerConfigOpt {
+	return func(config *ConsumerConfig) *ConsumerConfig {
+		config.RequestTimeout = timeout
+		return config
+	}
+}
+
+// WithConsumerConfigCheck returns ConsumerConfigOpt with given @check flag
+func WithConsumerConfigCheck(check bool) ConsumerConfigOpt {
+	return func(config *ConsumerConfig) *ConsumerConfig {
+		*config.Check = check
+		return config
 	}
-	return nil
 }
diff --git a/config/generic_service.go b/config/generic/generic_service.go
similarity index 98%
rename from config/generic_service.go
rename to config/generic/generic_service.go
index a3332af..34f2f7d 100644
--- a/config/generic_service.go
+++ b/config/generic/generic_service.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package config
+package generic
 
 import "context"
 
diff --git a/config/graceful_shutdown.go b/config/graceful_shutdown.go
index 6d2b716..d37ad82 100644
--- a/config/graceful_shutdown.go
+++ b/config/graceful_shutdown.go
@@ -18,9 +18,6 @@
 package config
 
 import (
-	"os"
-	"os/signal"
-	"runtime/debug"
 	"time"
 )
 
@@ -54,61 +51,61 @@ import (
 const defaultShutDownTime = time.Second * 60
 
 // nolint
-func GracefulShutdownInit() {
-	signals := make(chan os.Signal, 1)
-
-	signal.Notify(signals, ShutdownSignals...)
-
-	// retrieve ShutdownConfig for gracefulShutdownFilter
-	if filter, ok := extension.GetFilter(constant.GracefulShutdownConsumerFilterKey).(Setter); ok && GetConsumerConfig().ShutdownConfig != nil {
-		filter.Set(GracefulShutdownFilterShutdownConfig, GetConsumerConfig().ShutdownConfig)
-	}
-	if filter, ok := extension.GetFilter(constant.GracefulShutdownProviderFilterKey).(Setter); ok && GetProviderConfig().ShutdownConfig != nil {
-		filter.Set(GracefulShutdownFilterShutdownConfig, GetProviderConfig().ShutdownConfig)
-	}
-
-	go func() {
-		select {
-		case sig := <-signals:
-			logger.Infof("get signal %s, application will shutdown.", sig)
-			// gracefulShutdownOnce.Do(func() {
-			time.AfterFunc(totalTimeout(), func() {
-				logger.Warn("Shutdown gracefully timeout, application will shutdown immediately. ")
-				os.Exit(0)
-			})
-			BeforeShutdown()
-			// those signals' original behavior is exit with dump ths stack, so we try to keep the behavior
-			for _, dumpSignal := range DumpHeapShutdownSignals {
-				if sig == dumpSignal {
-					debug.WriteHeapDump(os.Stdout.Fd())
-				}
-			}
-			os.Exit(0)
-		}
-	}()
-}
+//func GracefulShutdownInit() {
+//	signals := make(chan os.Signal, 1)
+//
+//	signal.Notify(signals, ShutdownSignals...)
+//
+//	// retrieve ShutdownConfig for gracefulShutdownFilter
+//	if filter, ok := extension.GetFilter(constant.GracefulShutdownConsumerFilterKey).(config.Setter); ok && config.GetConsumerConfig().ShutdownConfig != nil {
+//		filter.Set(config.GracefulShutdownFilterShutdownConfig, config.GetConsumerConfig().ShutdownConfig)
+//	}
+//	if filter, ok := extension.GetFilter(constant.GracefulShutdownProviderFilterKey).(config.Setter); ok && config.GetProviderConfig().ShutdownConfig != nil {
+//		filter.Set(config.GracefulShutdownFilterShutdownConfig, config.GetProviderConfig().ShutdownConfig)
+//	}
+//
+//	go func() {
+//		select {
+//		case sig := <-signals:
+//			logger.Infof("get signal %s, applicationConfig will shutdown.", sig)
+//			// gracefulShutdownOnce.Do(func() {
+//			time.AfterFunc(totalTimeout(), func() {
+//				logger.Warn("Shutdown gracefully timeout, applicationConfig will shutdown immediately. ")
+//				os.Exit(0)
+//			})
+//			BeforeShutdown()
+//			// those signals' original behavior is exit with dump ths stack, so we try to keep the behavior
+//			for _, dumpSignal := range DumpHeapShutdownSignals {
+//				if sig == dumpSignal {
+//					debug.WriteHeapDump(os.Stdout.Fd())
+//				}
+//			}
+//			os.Exit(0)
+//		}
+//	}()
+//}
 
 // BeforeShutdown provides processing flow before shutdown
 func BeforeShutdown() {
 	destroyAllRegistries()
 	// waiting for a short time so that the clients have enough time to get the notification that server shutdowns
 	// The value of configuration depends on how long the clients will get notification.
-	waitAndAcceptNewRequests()
+	//waitAndAcceptNewRequests()
 
 	// reject the new request, but keeping waiting for accepting requests
-	waitForReceivingRequests()
+	//waitForReceivingRequests()
 
 	// we fetch the protocols from Consumer.References. Consumer.ProtocolConfig doesn't contains all protocol, like jsonrpc
-	consumerProtocols := getConsumerProtocols()
+	//consumerProtocols := getConsumerProtocols()
 
-	// If this application is not the provider, it will do nothing
-	destroyProviderProtocols(consumerProtocols)
+	// If this applicationConfig is not the provider, it will do nothing
+	//destroyProviderProtocols(consumerProtocols)
 
 	// reject sending the new request, and waiting for response of sending requests
-	waitForSendingRequests()
+	//waitForSendingRequests()
 
-	// If this application is not the consumer, it will do nothing
-	destroyConsumerProtocols(consumerProtocols)
+	// If this applicationConfig is not the consumer, it will do nothing
+	//destroyConsumerProtocols(consumerProtocols)
 
 	logger.Info("Graceful shutdown --- Execute the custom callbacks.")
 	customCallbacks := extension.GetAllCustomShutdownCallbacks()
@@ -118,7 +115,7 @@ func BeforeShutdown() {
 }
 
 func destroyAllRegistries() {
-	logger.Info("Graceful shutdown --- Destroy all registries. ")
+	logger.Info("Graceful shutdown --- Destroy all registriesConfig. ")
 	registryProtocol := extension.GetProtocol(constant.REGISTRY_KEY)
 	registryProtocol.Destroy()
 }
@@ -132,59 +129,59 @@ func destroyConsumerProtocols(consumerProtocols *gxset.HashSet) {
 
 // destroyProviderProtocols destroys the provider's protocol.
 // if the protocol is consumer's protocol too, we will keep it
-func destroyProviderProtocols(consumerProtocols *gxset.HashSet) {
-	logger.Info("Graceful shutdown --- Destroy provider's protocols. ")
-
-	if providerConfig == nil || providerConfig.Protocols == nil {
-		return
-	}
-
-	for _, protocol := range providerConfig.Protocols {
-
-		// the protocol is the consumer's protocol too, we can not destroy it.
-		if consumerProtocols.Contains(protocol.Name) {
-			continue
-		}
-		extension.GetProtocol(protocol.Name).Destroy()
-	}
-}
-
-func waitAndAcceptNewRequests() {
-	logger.Info("Graceful shutdown --- Keep waiting and accept new requests for a short time. ")
-	if providerConfig == nil || providerConfig.ShutdownConfig == nil {
-		return
-	}
-
-	timeout := providerConfig.ShutdownConfig.GetStepTimeout()
-
-	// ignore this step
-	if timeout < 0 {
-		return
-	}
-	time.Sleep(timeout)
-}
+//func destroyProviderProtocols(consumerProtocols *gxset.HashSet) {
+//	logger.Info("Graceful shutdown --- Destroy provider's protocols. ")
+//
+//	if config.providerConfig == nil || config.providerConfig.Protocols == nil {
+//		return
+//	}
+//
+//	for _, protocol := range config.providerConfig.Protocols {
+//
+//		// the protocol is the consumer's protocol too, we can not destroy it.
+//		if consumerProtocols.Contains(protocol.Name) {
+//			continue
+//		}
+//		extension.GetProtocol(protocol.Name).Destroy()
+//	}
+//}
+
+//func waitAndAcceptNewRequests() {
+//	logger.Info("Graceful shutdown --- Keep waiting and accept new requests for a short time. ")
+//	if config.providerConfig == nil || config.providerConfig.ShutdownConfig == nil {
+//		return
+//	}
+//
+//	timeout := config.providerConfig.ShutdownConfig.GetStepTimeout()
+//
+//	// ignore this step
+//	if timeout < 0 {
+//		return
+//	}
+//	time.Sleep(timeout)
+//}
 
 // for provider. It will wait for processing receiving requests
-func waitForReceivingRequests() {
-	logger.Info("Graceful shutdown --- Keep waiting until accepting requests finish or timeout. ")
-	if providerConfig == nil || providerConfig.ShutdownConfig == nil {
-		// ignore this step
-		return
-	}
-	providerConfig.ShutdownConfig.RejectRequest = true
-	waitingProcessedTimeout(providerConfig.ShutdownConfig)
-}
+//func waitForReceivingRequests() {
+//	logger.Info("Graceful shutdown --- Keep waiting until accepting requests finish or timeout. ")
+//	if config.providerConfig == nil || config.providerConfig.ShutdownConfig == nil {
+//		// ignore this step
+//		return
+//	}
+//	config.providerConfig.ShutdownConfig.RejectRequest = true
+//	waitingProcessedTimeout(config.providerConfig.ShutdownConfig)
+//}
 
 // for consumer. It will wait for the response of sending requests
-func waitForSendingRequests() {
-	logger.Info("Graceful shutdown --- Keep waiting until sending requests getting response or timeout ")
-	if consumerConfig == nil || consumerConfig.ShutdownConfig == nil {
-		// ignore this step
-		return
-	}
-	consumerConfig.ShutdownConfig.RejectRequest = true
-	waitingProcessedTimeout(consumerConfig.ShutdownConfig)
-}
+//func waitForSendingRequests() {
+//	logger.Info("Graceful shutdown --- Keep waiting until sending requests getting response or timeout ")
+//	if config.consumerConfig == nil || config.consumerConfig.ShutdownConfig == nil {
+//		// ignore this step
+//		return
+//	}
+//	config.consumerConfig.ShutdownConfig.RejectRequest = true
+//	waitingProcessedTimeout(config.consumerConfig.ShutdownConfig)
+//}
 
 func waitingProcessedTimeout(shutdownConfig *ShutdownConfig) {
 	timeout := shutdownConfig.GetStepTimeout()
@@ -199,33 +196,33 @@ func waitingProcessedTimeout(shutdownConfig *ShutdownConfig) {
 	}
 }
 
-func totalTimeout() time.Duration {
-	providerShutdown := defaultShutDownTime
-	if providerConfig != nil && providerConfig.ShutdownConfig != nil {
-		providerShutdown = providerConfig.ShutdownConfig.GetTimeout()
-	}
-
-	var consumerShutdown time.Duration
-	if consumerConfig != nil && consumerConfig.ShutdownConfig != nil {
-		consumerShutdown = consumerConfig.ShutdownConfig.GetTimeout()
-	}
-
-	timeout := providerShutdown
-	if consumerShutdown > providerShutdown {
-		timeout = consumerShutdown
-	}
-	return timeout
-}
+//func totalTimeout() time.Duration {
+//	providerShutdown := defaultShutDownTime
+//	if config.providerConfig != nil && config.providerConfig.ShutdownConfig != nil {
+//		providerShutdown = config.providerConfig.ShutdownConfig.GetTimeout()
+//	}
+//
+//	var consumerShutdown time.Duration
+//	if config.consumerConfig != nil && config.consumerConfig.ShutdownConfig != nil {
+//		consumerShutdown = config.consumerConfig.ShutdownConfig.GetTimeout()
+//	}
+//
+//	timeout := providerShutdown
+//	if consumerShutdown > providerShutdown {
+//		timeout = consumerShutdown
+//	}
+//	return timeout
+//}
 
 // we can not get the protocols from consumerConfig because some protocol don't have configuration, like jsonrpc.
-func getConsumerProtocols() *gxset.HashSet {
-	result := gxset.NewSet()
-	if consumerConfig == nil || consumerConfig.References == nil {
-		return result
-	}
-
-	for _, reference := range consumerConfig.References {
-		result.Add(reference.Protocol)
-	}
-	return result
-}
+//func getConsumerProtocols() *gxset.HashSet {
+//	result := gxset.NewSet()
+//	if config.consumerConfig == nil || config.consumerConfig.References == nil {
+//		return result
+//	}
+//
+//	for _, reference := range config.consumerConfig.References {
+//		result.Add(reference.Protocol)
+//	}
+//	return result
+//}
diff --git a/config/graceful_shutdown_config.go b/config/graceful_shutdown_config.go
index fd0bfb4..76720a3 100644
--- a/config/graceful_shutdown_config.go
+++ b/config/graceful_shutdown_config.go
@@ -35,7 +35,7 @@ const (
 type ShutdownConfig struct {
 	/*
 	 * Total timeout. Even though we don't release all resources,
-	 * the application will shutdown if the costing time is over this configuration. The unit is ms.
+	 * the applicationConfig will shutdown if the costing time is over this configuration. The unit is ms.
 	 * default value is 60 * 1000 ms = 1 minutes
 	 * In general, it should be bigger than 3 * StepTimeout.
 	 */
@@ -48,7 +48,7 @@ type ShutdownConfig struct {
 	 * maybe (10 + 2*3) * 1000ms is a good choice.
 	 */
 	StepTimeout string `default:"10s" yaml:"step_timeout" json:"step.timeout,omitempty" property:"step.timeout"`
-	// when we try to shutdown the application, we will reject the new requests. In most cases, you don't need to configure this.
+	// when we try to shutdown the applicationConfig, we will reject the new requests. In most cases, you don't need to configure this.
 	RejectRequestHandler string `yaml:"reject_handler" json:"reject_handler,omitempty" property:"reject_handler"`
 	// true -> new request will be rejected.
 	RejectRequest bool
@@ -57,7 +57,7 @@ type ShutdownConfig struct {
 	RequestsFinished bool
 }
 
-// nolint
+// Prefix dubbo.shutdown
 func (config *ShutdownConfig) Prefix() string {
 	return constant.ShutdownConfigPrefix
 }
diff --git a/config/graceful_shutdown_test.go b/config/graceful_shutdown_test.go
index c30f6ea..825ba7e 100644
--- a/config/graceful_shutdown_test.go
+++ b/config/graceful_shutdown_test.go
@@ -17,92 +17,98 @@
 
 package config
 
-import (
-	"testing"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/extension"
-	"dubbo.apache.org/dubbo-go/v3/filter"
-	"dubbo.apache.org/dubbo-go/v3/protocol"
-)
-
-func TestGracefulShutdownInit(t *testing.T) {
-	extension.SetFilter(constant.GracefulShutdownConsumerFilterKey, func() filter.Filter {
-		return &mockGracefulShutdownFilter{}
-	})
-	extension.SetFilter(constant.GracefulShutdownProviderFilterKey, func() filter.Filter {
-		return &mockGracefulShutdownFilter{}
-	})
-	GracefulShutdownInit()
-}
-
-func TestBeforeShutdown(t *testing.T) {
-	extension.SetProtocol("registry", func() protocol.Protocol {
-		return &mockRegistryProtocol{}
-	})
-	extension.SetProtocol(constant.DUBBO, func() protocol.Protocol {
-		return &mockRegistryProtocol{}
-	})
-
-	extension.SetProtocol("mock", func() protocol.Protocol {
-		return &mockRegistryProtocol{}
-	})
-
-	consumerReferences := map[string]*ReferenceConfig{}
-	consumerReferences[constant.DUBBO] = &ReferenceConfig{
-		Protocol: constant.DUBBO,
-	}
-
-	// without configuration
-	consumerConfig = nil
-	providerConfig = nil
-	BeforeShutdown()
-
-	consumerConfig = &ConsumerConfig{
-		References: consumerReferences,
-		ShutdownConfig: &ShutdownConfig{
-			Timeout:     "1",
-			StepTimeout: "1s",
-		},
-	}
-
-	providerProtocols := map[string]*ProtocolConfig{}
-	providerProtocols[constant.DUBBO] = &ProtocolConfig{
-		Name: constant.DUBBO,
-	}
-
-	providerProtocols["mock"] = &ProtocolConfig{
-		Name: "mock",
-	}
-
-	providerConfig = &ProviderConfig{
-		ShutdownConfig: &ShutdownConfig{
-			Timeout:     "1",
-			StepTimeout: "1s",
-		},
-		Protocols: providerProtocols,
-	}
-	// test destroy protocol
-	BeforeShutdown()
-
-	providerConfig = &ProviderConfig{
-		ShutdownConfig: &ShutdownConfig{
-			Timeout:     "1",
-			StepTimeout: "-1s",
-		},
-		Protocols: providerProtocols,
-	}
-
-	consumerConfig = &ConsumerConfig{
-		References: consumerReferences,
-		ShutdownConfig: &ShutdownConfig{
-			Timeout:     "1",
-			StepTimeout: "-1s",
-		},
-	}
-
-	// test ignore steps
-	BeforeShutdown()
-}
+//
+//import (
+//	"dubbo.apache.org/dubbo-go/v3/config"
+//	"dubbo.apache.org/dubbo-go/v3/config/consumer"
+//	protocol2 "dubbo.apache.org/dubbo-go/v3/config/protocol"
+//	"dubbo.apache.org/dubbo-go/v3/config/provider"
+//	"dubbo.apache.org/dubbo-go/v3/config/reference"
+//	"testing"
+//)
+//
+//import (
+//	"dubbo.apache.org/dubbo-go/v3/common/constant"
+//	"dubbo.apache.org/dubbo-go/v3/common/extension"
+//	"dubbo.apache.org/dubbo-go/v3/filter"
+//	"dubbo.apache.org/dubbo-go/v3/protocol"
+//)
+//
+//func TestGracefulShutdownInit(t *testing.T) {
+//	extension.SetFilter(constant.GracefulShutdownConsumerFilterKey, func() filter.Filter {
+//		return &config.mockGracefulShutdownFilter{}
+//	})
+//	extension.SetFilter(constant.GracefulShutdownProviderFilterKey, func() filter.Filter {
+//		return &config.mockGracefulShutdownFilter{}
+//	})
+//	GracefulShutdownInit()
+//}
+//
+//func TestBeforeShutdown(t *testing.T) {
+//	extension.SetProtocol("registry", func() protocol.Protocol {
+//		return &config.mockRegistryProtocol{}
+//	})
+//	extension.SetProtocol(constant.DUBBO, func() protocol.Protocol {
+//		return &config.mockRegistryProtocol{}
+//	})
+//
+//	extension.SetProtocol("mock", func() protocol.Protocol {
+//		return &config.mockRegistryProtocol{}
+//	})
+//
+//	consumerReferences := map[string]*reference.ReferenceConfig{}
+//	consumerReferences[constant.DUBBO] = &reference.ReferenceConfig{
+//		Protocol: constant.DUBBO,
+//	}
+//
+//	// without configuration
+//	config.consumerConfig = nil
+//	config.providerConfig = nil
+//	BeforeShutdown()
+//
+//	config.consumerConfig = &consumer.ShutdownConfig{
+//		References: consumerReferences,
+//		ShutdownConfig: &ShutdownConfig{
+//			Timeout:     "1",
+//			StepTimeout: "1s",
+//		},
+//	}
+//
+//	providerProtocols := map[string]*protocol2.ProtocolConfig{}
+//	providerProtocols[constant.DUBBO] = &protocol2.ProtocolConfig{
+//		Name: constant.DUBBO,
+//	}
+//
+//	providerProtocols["mock"] = &protocol2.ProtocolConfig{
+//		Name: "mock",
+//	}
+//
+//	config.providerConfig = &provider.ProviderConfig{
+//		ShutdownConfig: &ShutdownConfig{
+//			Timeout:     "1",
+//			StepTimeout: "1s",
+//		},
+//		Protocols: providerProtocols,
+//	}
+//	// test destroy protocol
+//	BeforeShutdown()
+//
+//	config.providerConfig = &provider.ProviderConfig{
+//		ShutdownConfig: &ShutdownConfig{
+//			Timeout:     "1",
+//			StepTimeout: "-1s",
+//		},
+//		Protocols: providerProtocols,
+//	}
+//
+//	config.consumerConfig = &consumer.ShutdownConfig{
+//		References: consumerReferences,
+//		ShutdownConfig: &ShutdownConfig{
+//			Timeout:     "1",
+//			StepTimeout: "-1s",
+//		},
+//	}
+//
+//	// test ignore steps
+//	BeforeShutdown()
+//}
diff --git a/config/metadata_report_config.go b/config/metadata_report_config.go
index 050339a..6b59e21 100644
--- a/config/metadata_report_config.go
+++ b/config/metadata_report_config.go
@@ -18,31 +18,23 @@
 package config
 
 import (
-	"net/url"
-)
-
-import (
 	"github.com/creasty/defaults"
 	perrors "github.com/pkg/errors"
 )
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/common"
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/config/instance"
 )
 
-// MethodConfig is method level configuration
+// MetadataReportConfig is app level configuration
 type MetadataReportConfig struct {
-	Protocol  string            `required:"true"  yaml:"protocol"  json:"protocol,omitempty" property:"protocol"`
-	RemoteRef string            `required:"true"  yaml:"remote_ref"  json:"remote_ref,omitempty" property:"remote_ref"`
-	Params    map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
-	Group     string            `yaml:"group" json:"group,omitempty" property:"group"`
-}
-
-// nolint
-func (c *MetadataReportConfig) Prefix() string {
-	return constant.MetadataReportPrefix
+	Protocol string `required:"true"  yaml:"protocol"  json:"protocol,omitempty"`
+	Address  string `required:"true" yaml:"address" json:"address"`
+	Username string `yaml:"username" json:"username,omitempty"`
+	Password string `yaml:"password" json:"password,omitempty"`
+	Timeout  string `yaml:"timeout" json:"timeout,omitempty"`
+	Group    string `yaml:"group" json:"group,omitempty"`
 }
 
 // UnmarshalYAML unmarshal the MetadataReportConfig by @unmarshal function
@@ -57,34 +49,45 @@ func (c *MetadataReportConfig) UnmarshalYAML(unmarshal func(interface{}) error)
 	return nil
 }
 
-// nolint
-func (c *MetadataReportConfig) ToUrl() (*common.URL, error) {
-	urlMap := make(url.Values)
-
-	if c.Params != nil {
-		for k, v := range c.Params {
-			urlMap.Set(k, v)
-		}
-	}
+func (c *MetadataReportConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(c)
+	return verify(c)
+}
 
-	rc, ok := GetBaseConfig().GetRemoteConfig(c.RemoteRef)
+func (c *MetadataReportConfig) Validate() {
 
-	if !ok {
-		return nil, perrors.New("Could not find out the remote ref config, name: " + c.RemoteRef)
-	}
+	// todo set default application
+}
 
-	res, err := common.NewURL(rc.Address,
-		common.WithParams(urlMap),
-		common.WithUsername(rc.Username),
-		common.WithPassword(rc.Password),
-		common.WithLocation(rc.Address),
-		common.WithProtocol(c.Protocol),
-	)
-	if err != nil || len(res.Protocol) == 0 {
-		return nil, perrors.New("Invalid MetadataReportConfig.")
-	}
-	res.SetParam("metadata", res.Protocol)
-	return res, nil
+// nolint
+func (c *MetadataReportConfig) ToUrl() (*common.URL, error) {
+	//urlMap := make(url.Values)
+
+	//if c.Params != nil {
+	//	for k, v := range c.Params {
+	//		urlMap.Set(k, v)
+	//	}
+	//}
+	//
+	//rc, ok := config.GetBaseConfig().GetRemoteConfig(c.RemoteRef)
+	//
+	//if !ok {
+	//	return nil, perrors.New("Could not find out the remote ref config, name: " + c.RemoteRef)
+	//}
+	//
+	//res, err := common.NewURL(rc.Address,
+	//	common.WithParams(urlMap),
+	//	common.WithUsername(rc.Username),
+	//	common.WithPassword(rc.Password),
+	//	common.WithLocation(rc.Address),
+	//	common.WithProtocol(c.Protocol),
+	//)
+	//if err != nil || len(res.Protocol) == 0 {
+	//	return nil, perrors.New("Invalid MetadataReportConfig.")
+	//}
+	//res.SetParam("metadata", res.Protocol)
+	return nil, nil
 }
 
 func (c *MetadataReportConfig) IsValid() bool {
@@ -92,14 +95,15 @@ func (c *MetadataReportConfig) IsValid() bool {
 }
 
 // StartMetadataReport: The entry of metadata report start
-func startMetadataReport(metadataType string, metadataReportConfig *MetadataReportConfig) error {
+func (c *MetadataReportConfig) StartMetadataReport(metadataType string, metadataReportConfig *MetadataReportConfig) error {
 	if metadataReportConfig == nil || !metadataReportConfig.IsValid() {
 		return nil
 	}
-
-	if metadataType == constant.METACONFIG_REMOTE && len(metadataReportConfig.RemoteRef) == 0 {
-		return perrors.New("MetadataConfig remote ref can not be empty.")
-	}
+	// todo
+	//
+	//if metadataType == constant.METACONFIG_REMOTE && len(metadataReportConfig.RemoteRef) == 0 {
+	//	return perrors.New("MetadataConfig remote ref can not be empty.")
+	//}
 
 	if tmpUrl, err := metadataReportConfig.ToUrl(); err == nil {
 		instance.GetMetadataReportInstance(tmpUrl)
diff --git a/config/metadata_report_config_test.go b/config/metadata_report_config_test.go
deleted file mode 100644
index 46b7f83..0000000
--- a/config/metadata_report_config_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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 config
-
-import (
-	"testing"
-)
-
-import (
-	"github.com/stretchr/testify/assert"
-)
-
-func TestMetadataReportConfig_ToUrl(t *testing.T) {
-	GetBaseConfig().Remotes["mock"] = &RemoteConfig{
-		Address:    "127.0.0.1:2181",
-		Username:   "test",
-		Password:   "test",
-		TimeoutStr: "3s",
-	}
-	metadataReportConfig := MetadataReportConfig{
-		Protocol:  "mock",
-		RemoteRef: "mock",
-		Params: map[string]string{
-			"k": "v",
-		},
-	}
-	url, err := metadataReportConfig.ToUrl()
-	assert.NoError(t, err)
-	assert.Equal(t, "mock", url.Protocol)
-	assert.Equal(t, "127.0.0.1:2181", url.Location)
-	assert.Equal(t, "127.0.0.1", url.Ip)
-	assert.Equal(t, "2181", url.Port)
-	assert.Equal(t, "test", url.Username)
-	assert.Equal(t, "test", url.Password)
-	assert.Equal(t, "v", url.GetParam("k", ""))
-	assert.Equal(t, "mock", url.GetParam("metadata", ""))
-}
diff --git a/config/metric_config_test.go b/config/metric_config_test.go
index fe9d249..2bcdd6d 100644
--- a/config/metric_config_test.go
+++ b/config/metric_config_test.go
@@ -21,11 +21,7 @@ import (
 	"testing"
 )
 
-import (
-	"github.com/stretchr/testify/assert"
-)
-
 func TestGetMetricConfig(t *testing.T) {
-	empty := GetMetricConfig()
-	assert.NotNil(t, empty)
+	//empty := GetMetricConfig()
+	//assert.NotNil(t, empty)
 }
diff --git a/config/protocol_config.go b/config/protocol_config.go
index 92e93f1..cddfdd7 100644
--- a/config/protocol_config.go
+++ b/config/protocol_config.go
@@ -18,33 +18,23 @@
 package config
 
 import (
-	"strings"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
+	"github.com/creasty/defaults"
 )
 
 // ProtocolConfig is protocol configuration
 type ProtocolConfig struct {
-	Name string `required:"true" yaml:"name"  json:"name,omitempty" property:"name"`
-	Ip   string `required:"true" yaml:"ip"  json:"ip,omitempty" property:"ip"`
-	Port string `required:"true" yaml:"port"  json:"port,omitempty" property:"port"`
+	Name string `default:"dubbo" validate:"required" yaml:"name"  json:"name,omitempty" property:"name"`
+	Ip   string `default:"127.0.0.1" yaml:"ip"  json:"ip,omitempty" property:"ip"`
+	Port string `default:"0" yaml:"port" json:"port,omitempty" property:"port"`
 }
 
-// nolint
-func (c *ProtocolConfig) Prefix() string {
-	return constant.ProtocolConfigPrefix
+func (p *ProtocolConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(p)
+	return verify(p)
 }
 
-func loadProtocol(protocolsIds string, protocols map[string]*ProtocolConfig) []*ProtocolConfig {
-	returnProtocols := make([]*ProtocolConfig, 0, len(protocols))
-	for _, v := range strings.Split(protocolsIds, ",") {
-		for k, protocol := range protocols {
-			if v == k {
-				returnProtocols = append(returnProtocols, protocol)
-			}
-		}
-	}
-	return returnProtocols
+func (p *ProtocolConfig) Validate() {
+
+	// todo set default application
 }
diff --git a/config/provider_config.go b/config/provider_config.go
index 8f1b562..ea9a518 100644
--- a/config/provider_config.go
+++ b/config/provider_config.go
@@ -18,34 +18,51 @@
 package config
 
 import (
-	"bytes"
-)
-
-import (
+	"dubbo.apache.org/dubbo-go/v3/common/logger"
+	"fmt"
 	"github.com/creasty/defaults"
-	perrors "github.com/pkg/errors"
 )
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/yaml"
 )
 
 // ProviderConfig is the default configuration of service provider
 type ProviderConfig struct {
-	BaseConfig     `yaml:",inline" property:"base"`
-	configCenter   `yaml:"-"`
-	Filter         string                     `yaml:"filter" json:"filter,omitempty" property:"filter"`
-	ProxyFactory   string                     `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty" property:"proxy_factory"`
-	Services       map[string]*ServiceConfig  `yaml:"services" json:"services,omitempty" property:"services"`
+	//base.ShutdownConfig         `yaml:",inline" property:"base"`
+	//center.configCenter `yaml:"-"`
+	Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
+	// Register whether registration is required
+	Register bool `yaml:"register" json:"register" property:"register"`
+	// Registry registry ids
+	Registry []string `yaml:"registry" json:"registry" property:"registry"`
+	// Services services
+	Services map[string]*ServiceConfig `yaml:"services" json:"services,omitempty" property:"services"`
+
+	ProxyFactory   string                     `default:"default" yaml:"proxy-factory" json:"proxy-factory,omitempty" property:"proxy-factory"`
 	Protocols      map[string]*ProtocolConfig `yaml:"protocols" json:"protocols,omitempty" property:"protocols"`
 	ProtocolConf   interface{}                `yaml:"protocol_conf" json:"protocol_conf,omitempty" property:"protocol_conf"`
 	FilterConf     interface{}                `yaml:"filter_conf" json:"filter_conf,omitempty" property:"filter_conf"`
 	ShutdownConfig *ShutdownConfig            `yaml:"shutdown_conf" json:"shutdown_conf,omitempty" property:"shutdown_conf"`
 	ConfigType     map[string]string          `yaml:"config_type" json:"config_type,omitempty" property:"config_type"`
+}
+
+func (c *ProviderConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(c)
+	return verify(c)
+}
 
-	Registry   *RegistryConfig            `yaml:"registry" json:"registry,omitempty" property:"registry"`
-	Registries map[string]*RegistryConfig `default:"{}" yaml:"registries" json:"registries" property:"registries"`
+func (c *ProviderConfig) Validate(r *RootConfig) {
+	ids := make([]string, 0)
+	for key := range r.Registries {
+		ids = append(ids, key)
+	}
+	c.Registry = removeDuplicateElement(ids)
+	for k, _ := range c.Services {
+		c.Services[k].Validate(r)
+	}
+	// todo set default application
 }
 
 // UnmarshalYAML unmarshals the ProviderConfig by @unmarshal function
@@ -57,48 +74,113 @@ func (c *ProviderConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
 	return unmarshal((*plain)(c))
 }
 
-// nolint
-func (*ProviderConfig) Prefix() string {
+// Prefix dubbo.provider
+func (c *ProviderConfig) Prefix() string {
 	return constant.ProviderConfigPrefix
 }
 
+func (c *ProviderConfig) Load() {
+	// todo Write the current configuration to cache file.
+	//if c.CacheFile != "" {
+	//	if data, err := yaml.MarshalYML(providerConfig); err != nil {
+	//		logger.Errorf("Marshal provider config err: %s", err.Error())
+	//	} else {
+	//		if err := ioutil.WriteFile(provider  CacheFile, data, 0666); err != nil {
+	//			logger.Errorf("Write provider config cache file err: %s", err.Error())
+	//		}
+	//	}
+	//}
+
+	for key, svs := range c.Services {
+		rpcService := GetProviderService(key)
+		if rpcService == nil {
+			logger.Warnf("%s does not exist!", key)
+			continue
+		}
+		svs.id = key
+		svs.Implement(rpcService)
+		if err := svs.Export(); err != nil {
+			panic(fmt.Sprintf("service %s export failed! err: %#v", key, err))
+		}
+	}
+}
+
 // SetProviderConfig sets provider config by @p
 func SetProviderConfig(p ProviderConfig) {
-	providerConfig = &p
+	rootConfig.Provider = &p
 }
 
-// ProviderInit loads config file to init provider config
-func ProviderInit(confProFile string) error {
-	if len(confProFile) == 0 {
-		return perrors.Errorf("application configure(provider) file name is nil")
-	}
-	providerConfig = &ProviderConfig{}
-	fileStream, err := yaml.UnmarshalYMLConfig(confProFile, providerConfig)
-	if err != nil {
-		return perrors.Errorf("unmarshalYmlConfig error %v", perrors.WithStack(err))
+//
+//// ProviderInit loads config file to init provider config
+//func ProviderInit(confProFile string) error {
+//	if len(confProFile) == 0 {
+//		return perrors.Errorf("applicationConfig configure(provider) file name is nil")
+//	}
+//	  providerConfig = &ProviderConfig{}
+//	fileStream, err := yaml.UnmarshalYMLConfig(confProFile,   providerConfig)
+//	if err != nil {
+//		return perrors.Errorf("unmarshalYmlConfig error %v", perrors.WithStack(err))
+//	}
+//
+//	  provider  fileStream = bytes.NewBuffer(fileStream)
+//	// set method interfaceId & interfaceName
+//	for k, v := range   provider  Services {
+//		// set id for reference
+//		for _, n := range   provider  Services[k].Methods {
+//			n.InterfaceName = v.InterfaceName
+//			n.InterfaceId = k
+//		}
+//	}
+//
+//	return nil
+//}
+//
+//func configCenterRefreshProvider() error {
+//	// fresh it
+//	if   provider  ConfigCenterConfig != nil {
+//		  provider  fatherConfig =   providerConfig
+//		if err :=   provider  startConfigCenter((*  providerConfig).BaseConfig); err != nil {
+//			return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
+//		}
+//		  provider  fresh()
+//	}
+//	return nil
+//}
+
+///////////////////////////////////// provider config api
+// ProviderConfigOpt is the
+type ProviderConfigOpt func(config *ProviderConfig) *ProviderConfig
+
+// NewEmptyProviderConfig returns ProviderConfig with default ApplicationConfig
+func NewEmptyProviderConfig() *ProviderConfig {
+	newProviderConfig := &ProviderConfig{
+		Services: make(map[string]*ServiceConfig),
+		Registry: make([]string, 8),
 	}
+	return newProviderConfig
+}
 
-	providerConfig.fileStream = bytes.NewBuffer(fileStream)
-	// set method interfaceId & interfaceName
-	for k, v := range providerConfig.Services {
-		// set id for reference
-		for _, n := range providerConfig.Services[k].Methods {
-			n.InterfaceName = v.InterfaceName
-			n.InterfaceId = k
-		}
+// NewProviderConfig returns ProviderConfig with given @opts
+func NewProviderConfig(opts ...ProviderConfigOpt) *ProviderConfig {
+	newConfig := NewEmptyProviderConfig()
+	for _, v := range opts {
+		v(newConfig)
 	}
+	return newConfig
+}
 
-	return nil
+// WithProviderServices returns ProviderConfig with given serviceNameKey @serviceName and @serviceConfig
+func WithProviderServices(serviceName string, serviceConfig *ServiceConfig) ProviderConfigOpt {
+	return func(config *ProviderConfig) *ProviderConfig {
+		config.Services[serviceName] = serviceConfig
+		return config
+	}
 }
 
-func configCenterRefreshProvider() error {
-	// fresh it
-	if providerConfig.ConfigCenterConfig != nil {
-		providerConfig.fatherConfig = providerConfig
-		if err := providerConfig.startConfigCenter((*providerConfig).BaseConfig); err != nil {
-			return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
-		}
-		providerConfig.fresh()
+// WithProviderRegistry returns ProviderConfigOpt with given @registryKey and registry @registryConfig
+func WithProviderRegistry(registryKey ...string) ProviderConfigOpt {
+	return func(config *ProviderConfig) *ProviderConfig {
+		config.Registry = append(config.Registry, registryKey...)
+		return config
 	}
-	return nil
 }
diff --git a/config/provider_config_test.go b/config/provider_config_test.go
index e8a9c1f..4427b0d 100644
--- a/config/provider_config_test.go
+++ b/config/provider_config_test.go
@@ -17,34 +17,36 @@
 
 package config
 
-import (
-	"path/filepath"
-	"testing"
-)
-
-import (
-	"github.com/stretchr/testify/assert"
-)
-
-func TestConsumerInit(t *testing.T) {
-	conPath, err := filepath.Abs("./testdata/consumer_config_with_configcenter.yml")
-	assert.NoError(t, err)
-	assert.NoError(t, ConsumerInit(conPath))
-	assert.Equal(t, "default", consumerConfig.ProxyFactory)
-	assert.Equal(t, "dubbo.properties", consumerConfig.ConfigCenterConfig.ConfigFile)
-	assert.Equal(t, "100ms", consumerConfig.Connect_Timeout)
-}
-
-func TestConsumerInitWithDefaultProtocol(t *testing.T) {
-	conPath, err := filepath.Abs("./testdata/consumer_config_withoutProtocol.yml")
-	assert.NoError(t, err)
-	assert.NoError(t, ConsumerInit(conPath))
-	assert.Equal(t, "dubbo", consumerConfig.References["UserProvider"].Protocol)
-}
-
-func TestProviderInitWithDefaultProtocol(t *testing.T) {
-	conPath, err := filepath.Abs("./testdata/provider_config_withoutProtocol.yml")
-	assert.NoError(t, err)
-	assert.NoError(t, ProviderInit(conPath))
-	assert.Equal(t, "dubbo", providerConfig.Services["UserProvider"].Protocol)
-}
+//import (
+//	"dubbo.apache.org/dubbo-go/v3/config"
+//	"dubbo.apache.org/dubbo-go/v3/config/consumer"
+//	"path/filepath"
+//	"testing"
+//)
+//
+//import (
+//	"github.com/stretchr/testify/assert"
+//)
+//
+//func TestConsumerInit(t *testing.T) {
+//	conPath, err := filepath.Abs("./testdata/consumer_config_with_configcenter.yml")
+//	assert.NoError(t, err)
+//	assert.NoError(t, consumer.ConsumerInit(conPath))
+//	assert.Equal(t, "default", config.consumerConfig.ProxyFactory)
+//	assert.Equal(t, "dubbo.properties", config.consumerConfig.ConfigCenterConfig.ConfigFile)
+//	assert.Equal(t, "100ms", config.consumerConfig.Connect_Timeout)
+//}
+//
+//func TestConsumerInitWithDefaultProtocol(t *testing.T) {
+//	conPath, err := filepath.Abs("./testdata/consumer_config_withoutProtocol.yml")
+//	assert.NoError(t, err)
+//	assert.NoError(t, consumer.ConsumerInit(conPath))
+//	assert.Equal(t, "dubbo", config.consumerConfig.References["UserProvider"].Protocol)
+//}
+//
+//func TestProviderInitWithDefaultProtocol(t *testing.T) {
+//	conPath, err := filepath.Abs("./testdata/provider_config_withoutProtocol.yml")
+//	assert.NoError(t, err)
+//	assert.NoError(t, ProviderInit(conPath))
+//	assert.Equal(t, "dubbo", config.providerConfig.Services["UserProvider"].Protocol)
+//}
diff --git a/config/reference_config.go b/config/reference_config.go
index ff5f6b6..0e911b1 100644
--- a/config/reference_config.go
+++ b/config/reference_config.go
@@ -18,25 +18,20 @@
 package config
 
 import (
-	"fmt"
-	"net/url"
-	"strconv"
-	"time"
-)
-
-import (
-	"github.com/creasty/defaults"
-	gxstrings "github.com/dubbogo/gost/strings"
-)
-
-import (
 	"dubbo.apache.org/dubbo-go/v3/cluster/directory"
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/proxy"
+	"dubbo.apache.org/dubbo-go/v3/config/generic"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 	"dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
+	"fmt"
+	"github.com/creasty/defaults"
+	gxstrings "github.com/dubbogo/gost/strings"
+	"net/url"
+	"strconv"
+	"time"
 )
 
 // ReferenceConfig is the configuration of service consumer
@@ -48,7 +43,7 @@ type ReferenceConfig struct {
 	URL            string            `yaml:"url"  json:"url,omitempty" property:"url"`
 	Filter         string            `yaml:"filter" json:"filter,omitempty" property:"filter"`
 	Protocol       string            `default:"dubbo"  yaml:"protocol"  json:"protocol,omitempty" property:"protocol"`
-	Registry       string            `yaml:"registry"  json:"registry,omitempty"  property:"registry"`
+	Registry       []string          `yaml:"registry"  json:"registry,omitempty"  property:"registry"`
 	Cluster        string            `yaml:"cluster"  json:"cluster,omitempty" property:"cluster"`
 	Loadbalance    string            `yaml:"loadbalance"  json:"loadbalance,omitempty" property:"loadbalance"`
 	Retries        string            `yaml:"retries"  json:"retries,omitempty" property:"retries"`
@@ -65,6 +60,8 @@ type ReferenceConfig struct {
 	Sticky         bool   `yaml:"sticky"   json:"sticky,omitempty" property:"sticky"`
 	RequestTimeout string `yaml:"timeout"  json:"timeout,omitempty" property:"timeout"`
 	ForceTag       bool   `yaml:"force.tag"  json:"force.tag,omitempty" property:"force.tag"`
+
+	rootConfig *RootConfig
 }
 
 // nolint
@@ -72,11 +69,6 @@ func (c *ReferenceConfig) Prefix() string {
 	return constant.ReferenceConfigPrefix + c.InterfaceName + "."
 }
 
-// NewReferenceConfig The only way to get a new ReferenceConfig
-func NewReferenceConfig(id string) *ReferenceConfig {
-	return &ReferenceConfig{id: id}
-}
-
 // UnmarshalYAML unmarshals the ReferenceConfig by @unmarshal function
 func (c *ReferenceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	type rf ReferenceConfig
@@ -89,6 +81,17 @@ func (c *ReferenceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
 	return defaults.Set(c)
 }
 
+func (c *ReferenceConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(c)
+	return verify(c)
+}
+
+func (c *ReferenceConfig) Validate(rootConfig *RootConfig) {
+	c.rootConfig = rootConfig
+	// todo set default application
+}
+
 // Refer ...
 func (c *ReferenceConfig) Refer(_ interface{}) {
 	cfgURL := common.NewURLWithOptions(
@@ -123,7 +126,7 @@ func (c *ReferenceConfig) Refer(_ interface{}) {
 		}
 	} else {
 		// 2. assemble SubURL from register center's configuration mode
-		c.urls = loadRegistries(c.Registry, consumerConfig.Registries, common.CONSUMER)
+		c.urls = loadRegistries(c.Registry, c.rootConfig.Registries, common.CONSUMER)
 
 		// set url to regURLs
 		for _, regURL := range c.urls {
@@ -201,9 +204,9 @@ func (c *ReferenceConfig) Refer(_ interface{}) {
 	// create proxy
 	if c.Async {
 		callback := GetCallback(c.id)
-		c.pxy = extension.GetProxyFactory(consumerConfig.ProxyFactory).GetAsyncProxy(c.invoker, callback, cfgURL)
+		c.pxy = extension.GetProxyFactory(c.rootConfig.Consumer.ProxyFactory).GetAsyncProxy(c.invoker, callback, cfgURL)
 	} else {
-		c.pxy = extension.GetProxyFactory(consumerConfig.ProxyFactory).GetProxy(c.invoker, cfgURL)
+		c.pxy = extension.GetProxyFactory(c.rootConfig.Consumer.ProxyFactory).GetProxy(c.invoker, cfgURL)
 	}
 }
 
@@ -251,21 +254,21 @@ func (c *ReferenceConfig) getURLMap() url.Values {
 	urlMap.Set(constant.ASYNC_KEY, strconv.FormatBool(c.Async))
 	urlMap.Set(constant.STICKY_KEY, strconv.FormatBool(c.Sticky))
 
-	// application info
-	urlMap.Set(constant.APPLICATION_KEY, consumerConfig.ApplicationConfig.Name)
-	urlMap.Set(constant.ORGANIZATION_KEY, consumerConfig.ApplicationConfig.Organization)
-	urlMap.Set(constant.NAME_KEY, consumerConfig.ApplicationConfig.Name)
-	urlMap.Set(constant.MODULE_KEY, consumerConfig.ApplicationConfig.Module)
-	urlMap.Set(constant.APP_VERSION_KEY, consumerConfig.ApplicationConfig.Version)
-	urlMap.Set(constant.OWNER_KEY, consumerConfig.ApplicationConfig.Owner)
-	urlMap.Set(constant.ENVIRONMENT_KEY, consumerConfig.ApplicationConfig.Environment)
+	// applicationConfig info
+	urlMap.Set(constant.APPLICATION_KEY, c.rootConfig.Application.Name)
+	urlMap.Set(constant.ORGANIZATION_KEY, c.rootConfig.Application.Organization)
+	urlMap.Set(constant.NAME_KEY, c.rootConfig.Application.Name)
+	urlMap.Set(constant.MODULE_KEY, c.rootConfig.Application.Module)
+	urlMap.Set(constant.APP_VERSION_KEY, c.rootConfig.Application.Version)
+	urlMap.Set(constant.OWNER_KEY, c.rootConfig.Application.Owner)
+	urlMap.Set(constant.ENVIRONMENT_KEY, c.rootConfig.Application.Environment)
 
 	// filter
 	defaultReferenceFilter := constant.DEFAULT_REFERENCE_FILTERS
 	if c.Generic {
 		defaultReferenceFilter = constant.GENERIC_REFERENCE_FILTERS + "," + defaultReferenceFilter
 	}
-	urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, c.Filter, defaultReferenceFilter))
+	//urlMap.Set(constant.REFERENCE_FILTER_KEY, config.mergeValue(config.consumerConfig.Filter, c.Filter, defaultReferenceFilter))
 
 	for _, v := range c.Methods {
 		urlMap.Set("methods."+v.Name+"."+constant.LOADBALANCE_KEY, v.LoadBalance)
@@ -281,7 +284,7 @@ func (c *ReferenceConfig) getURLMap() url.Values {
 
 // GenericLoad ...
 func (c *ReferenceConfig) GenericLoad(id string) {
-	genericService := NewGenericService(c.id)
+	genericService := generic.NewGenericService(c.id)
 	SetConsumerService(genericService)
 	c.id = id
 	c.Refer(genericService)
@@ -305,3 +308,74 @@ func (c *ReferenceConfig) postProcessConfig(url *common.URL) {
 		p.PostProcessReferenceConfig(url)
 	}
 }
+
+//////////////////////////////////// reference config api
+
+// ReferenceConfigOpt is consumer's reference config
+type ReferenceConfigOpt func(config *ReferenceConfig) *ReferenceConfig
+
+// NewReferenceConfig The only way to get a new ReferenceConfig
+func NewReferenceConfigWithID(id string) *ReferenceConfig {
+	return &ReferenceConfig{id: id}
+}
+
+// NewEmptyReferenceConfig returns empty ReferenceConfig
+func NewEmptyReferenceConfig() *ReferenceConfig {
+	newReferenceConfig := NewReferenceConfigWithID("")
+	newReferenceConfig.Methods = make([]*MethodConfig, 0, 8)
+	newReferenceConfig.Params = make(map[string]string, 8)
+	return newReferenceConfig
+}
+
+// NewReferenceConfig returns ReferenceConfig with given @opts
+func NewReferenceConfig(opts ...ReferenceConfigOpt) *ReferenceConfig {
+	newReferenceConfig := NewEmptyReferenceConfig()
+	for _, v := range opts {
+		v(newReferenceConfig)
+	}
+	return newReferenceConfig
+}
+
+// WithReferenceRegistry returns ReferenceConfigOpt with given registryKey: @registry
+func WithReferenceRegistry(registry ...string) ReferenceConfigOpt {
+	return func(config *ReferenceConfig) *ReferenceConfig {
+		config.Registry = registry
+		return config
+	}
+}
+
+// WithReferenceProtocol returns ReferenceConfigOpt with given protocolKey: @protocol
+func WithReferenceProtocol(protocol string) ReferenceConfigOpt {
+	return func(config *ReferenceConfig) *ReferenceConfig {
+		config.Protocol = protocol
+		return config
+	}
+}
+
+// WithReferenceInterface returns ReferenceConfigOpt with given @interfaceName
+func WithReferenceInterface(interfaceName string) ReferenceConfigOpt {
+	return func(config *ReferenceConfig) *ReferenceConfig {
+		config.InterfaceName = interfaceName
+		return config
+	}
+}
+
+// WithReferenceCluster returns ReferenceConfigOpt with given cluster name: @cluster
+func WithReferenceCluster(cluster string) ReferenceConfigOpt {
+	return func(config *ReferenceConfig) *ReferenceConfig {
+		config.Cluster = cluster
+		return config
+	}
+}
+
+// WithReferenceMethod returns ReferenceConfigOpt with given @method, @retries, and load balance: @lb
+func WithReferenceMethod(methodName, retries, lb string) ReferenceConfigOpt {
+	return func(config *ReferenceConfig) *ReferenceConfig {
+		config.Methods = append(config.Methods, &MethodConfig{
+			Name:        methodName,
+			Retries:     retries,
+			LoadBalance: lb,
+		})
+		return config
+	}
+}
diff --git a/config/reference_config_test.go b/config/reference_config_test.go
index fc76f1d..8458587 100644
--- a/config/reference_config_test.go
+++ b/config/reference_config_test.go
@@ -17,388 +17,395 @@
 
 package config
 
-import (
-	"context"
-	"sync"
-	"testing"
-)
-
-import (
-	"github.com/stretchr/testify/assert"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/cluster/cluster_impl"
-	"dubbo.apache.org/dubbo-go/v3/common"
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/extension"
-	"dubbo.apache.org/dubbo-go/v3/filter"
-	"dubbo.apache.org/dubbo-go/v3/protocol"
-	"dubbo.apache.org/dubbo-go/v3/registry"
-)
-
-var regProtocol protocol.Protocol
-
-func doInitConsumer() {
-	consumerConfig = &ConsumerConfig{
-		BaseConfig: BaseConfig{
-			ApplicationConfig: &ApplicationConfig{
-				Organization: "dubbo_org",
-				Name:         "dubbo",
-				Module:       "module",
-				Version:      "2.6.0",
-				Owner:        "dubbo",
-				Environment:  "test",
-			},
-		},
-
-		Registries: map[string]*RegistryConfig{
-			"shanghai_reg1": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "shanghai_idc",
-				Address:    "127.0.0.1:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-			"shanghai_reg2": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "shanghai_idc",
-				Address:    "127.0.0.2:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-			"hangzhou_reg1": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "hangzhou_idc",
-				Address:    "127.0.0.3:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-			"hangzhou_reg2": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "hangzhou_idc",
-				Address:    "127.0.0.4:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-		},
-
-		References: map[string]*ReferenceConfig{
-			"MockService": {
-				id: "MockProvider",
-				Params: map[string]string{
-					"serviceid": "soa.mock",
-					"forks":     "5",
-				},
-				Sticky:        false,
-				Registry:      "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2",
-				InterfaceName: "com.MockService",
-				Protocol:      "mock",
-				Cluster:       "failover",
-				Loadbalance:   "random",
-				Retries:       "3",
-				Group:         "huadong_idc",
-				Version:       "1.0.0",
-				Methods: []*MethodConfig{
-					{
-						Name:        "GetUser",
-						Retries:     "2",
-						LoadBalance: "random",
-					},
-					{
-						Name:        "GetUser1",
-						Retries:     "2",
-						LoadBalance: "random",
-						Sticky:      true,
-					},
-				},
-			},
-		},
-	}
-}
-
-var mockProvider = new(MockProvider)
-
-type MockProvider struct{}
-
-func (m *MockProvider) Reference() string {
-	return "MockProvider"
-}
-
-func (m *MockProvider) CallBack(res common.CallbackResponse) {
-	// CallBack is a mock function. to implement the interface
-}
-
-func doInitConsumerAsync() {
-	doInitConsumer()
-	SetConsumerService(mockProvider)
-	for _, v := range consumerConfig.References {
-		v.Async = true
-	}
-}
-
-func doInitConsumerWithSingleRegistry() {
-	consumerConfig = &ConsumerConfig{
-		BaseConfig: BaseConfig{
-			ApplicationConfig: &ApplicationConfig{
-				Organization: "dubbo_org",
-				Name:         "dubbo",
-				Module:       "module",
-				Version:      "2.6.0",
-				Owner:        "dubbo",
-				Environment:  "test",
-			},
-		},
-
-		Registry: &RegistryConfig{
-			Address:  "mock://27.0.0.1:2181",
-			Username: "user1",
-			Password: "pwd1",
-		},
-		Registries: map[string]*RegistryConfig{},
-
-		References: map[string]*ReferenceConfig{
-			"MockService": {
-				Params: map[string]string{
-					"serviceid": "soa.mock",
-					"forks":     "5",
-				},
-				InterfaceName: "com.MockService",
-				Protocol:      "mock",
-				Cluster:       "failover",
-				Loadbalance:   "random",
-				Retries:       "3",
-				Group:         "huadong_idc",
-				Version:       "1.0.0",
-				Methods: []*MethodConfig{
-					{
-						Name:        "GetUser",
-						Retries:     "2",
-						LoadBalance: "random",
-					},
-					{
-						Name:        "GetUser1",
-						Retries:     "2",
-						LoadBalance: "random",
-					},
-				},
-			},
-		},
-	}
-}
-
-func TestReferMultiReg(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("registry", GetProtocol)
-	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		assert.NotNil(t, reference.invoker)
-		assert.NotNil(t, reference.pxy)
-	}
-	consumerConfig = nil
-}
-
-func TestRefer(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("registry", GetProtocol)
-	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
-
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		assert.Equal(t, "soa.mock", reference.Params["serviceid"])
-		assert.NotNil(t, reference.invoker)
-		assert.NotNil(t, reference.pxy)
-	}
-	consumerConfig = nil
-}
-
-func TestReferAsync(t *testing.T) {
-	doInitConsumerAsync()
-	extension.SetProtocol("registry", GetProtocol)
-	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
-
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		assert.Equal(t, "soa.mock", reference.Params["serviceid"])
-		assert.NotNil(t, reference.invoker)
-		assert.NotNil(t, reference.pxy)
-		assert.NotNil(t, reference.pxy.GetCallback())
-	}
-	consumerConfig = nil
-}
-
-func TestReferP2P(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("dubbo", GetProtocol)
-	mockFilter()
-	m := consumerConfig.References["MockService"]
-	m.URL = "dubbo://127.0.0.1:20000"
-
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		assert.NotNil(t, reference.invoker)
-		assert.NotNil(t, reference.pxy)
-	}
-	consumerConfig = nil
-}
-
-func TestReferMultiP2P(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("dubbo", GetProtocol)
-	mockFilter()
-	m := consumerConfig.References["MockService"]
-	m.URL = "dubbo://127.0.0.1:20000;dubbo://127.0.0.2:20000"
-
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		assert.NotNil(t, reference.invoker)
-		assert.NotNil(t, reference.pxy)
-	}
-	consumerConfig = nil
-}
-
-func TestReferMultiP2PWithReg(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("dubbo", GetProtocol)
-	extension.SetProtocol("registry", GetProtocol)
-	mockFilter()
-	m := consumerConfig.References["MockService"]
-	m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
-
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		assert.NotNil(t, reference.invoker)
-		assert.NotNil(t, reference.pxy)
-	}
-	consumerConfig = nil
-}
-
-func TestImplement(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("registry", GetProtocol)
-	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		reference.Implement(&MockService{})
-		assert.NotNil(t, reference.GetRPCService())
-
-	}
-	consumerConfig = nil
-}
-
-func TestForking(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("dubbo", GetProtocol)
-	extension.SetProtocol("registry", GetProtocol)
-	mockFilter()
-	m := consumerConfig.References["MockService"]
-	m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
-
-	for _, reference := range consumerConfig.References {
-		reference.Refer(nil)
-		forks := int(reference.invoker.GetURL().GetParamInt(constant.FORKS_KEY, constant.DEFAULT_FORKS))
-		assert.Equal(t, 5, forks)
-		assert.NotNil(t, reference.pxy)
-		assert.NotNil(t, reference.Cluster)
-	}
-	consumerConfig = nil
-}
-
-func TestSticky(t *testing.T) {
-	doInitConsumer()
-	extension.SetProtocol("dubbo", GetProtocol)
-	extension.SetProtocol("registry", GetProtocol)
-	mockFilter()
-	m := consumerConfig.References["MockService"]
-	m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
-
-	reference := consumerConfig.References["MockService"]
-	reference.Refer(nil)
-	referenceSticky := reference.invoker.GetURL().GetParam(constant.STICKY_KEY, "false")
-	assert.Equal(t, "false", referenceSticky)
-
-	method0StickKey := reference.invoker.GetURL().GetMethodParam(reference.Methods[0].Name, constant.STICKY_KEY, "false")
-	assert.Equal(t, "false", method0StickKey)
-	method1StickKey := reference.invoker.GetURL().GetMethodParam(reference.Methods[1].Name, constant.STICKY_KEY, "false")
-	assert.Equal(t, "true", method1StickKey)
-}
-
-func GetProtocol() protocol.Protocol {
-	if regProtocol != nil {
-		return regProtocol
-	}
-	return newRegistryProtocol()
-}
-
-func newRegistryProtocol() protocol.Protocol {
-	return &mockRegistryProtocol{}
-}
-
-type mockRegistryProtocol struct {
-}
-
-func (*mockRegistryProtocol) Refer(url *common.URL) protocol.Invoker {
-	return protocol.NewBaseInvoker(url)
-}
-
-func (*mockRegistryProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
-	registryURL := getRegistryURL(invoker)
-	if registryURL.Protocol == "service-discovery" {
-		metaDataService, err := extension.GetLocalMetadataService("")
-		if err != nil {
-			panic(err)
-		}
-		ok, err := metaDataService.ExportURL(invoker.GetURL().SubURL.Clone())
-		if err != nil {
-			panic(err)
-		}
-		if !ok {
-			panic("The URL has been registry!")
-		}
-	}
-	return protocol.NewBaseExporter("test", invoker, &sync.Map{})
-}
-
-func (*mockRegistryProtocol) Destroy() {
-	// Destroy is a mock function
-}
-
-func getRegistryURL(invoker protocol.Invoker) *common.URL {
-	// here add * for return a new url
-	url := invoker.GetURL()
-	// if the protocol == registry ,set protocol the registry value in url.params
-	if url.Protocol == constant.REGISTRY_PROTOCOL {
-		protocol := url.GetParam(constant.REGISTRY_KEY, "")
-		url.Protocol = protocol
-	}
-	return url
-}
-
-func (p *mockRegistryProtocol) GetRegistries() []registry.Registry {
-	return []registry.Registry{&mockServiceDiscoveryRegistry{}}
-}
-
-func mockFilter() {
-	consumerFiler := &mockShutdownFilter{}
-	extension.SetFilter(constant.GracefulShutdownConsumerFilterKey, func() filter.Filter {
-		return consumerFiler
-	})
-}
-
-type mockShutdownFilter struct {
-}
-
-// Invoke adds the requests count and block the new requests if application is closing
-func (gf *mockShutdownFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
-	return invoker.Invoke(ctx, invocation)
-}
-
-// OnResponse reduces the number of active processes then return the process result
-func (gf *mockShutdownFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
-	return result
-}
+//import (
+//	"context"
+//	"dubbo.apache.org/dubbo-go/v3/config"
+//	"dubbo.apache.org/dubbo-go/v3/config/applicationConfig"
+//	"dubbo.apache.org/dubbo-go/v3/config/base"
+//	"dubbo.apache.org/dubbo-go/v3/config/consumer"
+//	"dubbo.apache.org/dubbo-go/v3/config/instance"
+//	"dubbo.apache.org/dubbo-go/v3/config/method"
+//	registry2 "dubbo.apache.org/dubbo-go/v3/config/registry"
+//	"sync"
+//	"testing"
+//)
+//
+//import (
+//	"github.com/stretchr/testify/assert"
+//)
+//
+//import (
+//	"dubbo.apache.org/dubbo-go/v3/cluster/cluster_impl"
+//	"dubbo.apache.org/dubbo-go/v3/common"
+//	"dubbo.apache.org/dubbo-go/v3/common/constant"
+//	"dubbo.apache.org/dubbo-go/v3/common/extension"
+//	"dubbo.apache.org/dubbo-go/v3/filter"
+//	"dubbo.apache.org/dubbo-go/v3/protocol"
+//	"dubbo.apache.org/dubbo-go/v3/registry"
+//)
+//
+//var regProtocol protocol.Protocol
+//
+//func doInitConsumer() {
+//	config.consumerConfig = &consumer.Config{
+//		BaseConfig: base.Config{
+//			applicationConfig.Config: &applicationConfig.Config{
+//				Organization: "dubbo_org",
+//				Name:         "dubbo",
+//				Module:       "module",
+//				Version:      "2.6.0",
+//				Owner:        "dubbo",
+//				Environment:  "test",
+//			},
+//		},
+//
+//		Registries: map[string]*registry2.RegistryConfig{
+//			"shanghai_reg1": {
+//				Protocol:   "mock",
+//				TimeoutStr: "2s",
+//				Group:      "shanghai_idc",
+//				Address:    "127.0.0.1:2181",
+//				Username:   "user1",
+//				Password:   "pwd1",
+//			},
+//			"shanghai_reg2": {
+//				Protocol:   "mock",
+//				TimeoutStr: "2s",
+//				Group:      "shanghai_idc",
+//				Address:    "127.0.0.2:2181",
+//				Username:   "user1",
+//				Password:   "pwd1",
+//			},
+//			"hangzhou_reg1": {
+//				Protocol:   "mock",
+//				TimeoutStr: "2s",
+//				Group:      "hangzhou_idc",
+//				Address:    "127.0.0.3:2181",
+//				Username:   "user1",
+//				Password:   "pwd1",
+//			},
+//			"hangzhou_reg2": {
+//				Protocol:   "mock",
+//				TimeoutStr: "2s",
+//				Group:      "hangzhou_idc",
+//				Address:    "127.0.0.4:2181",
+//				Username:   "user1",
+//				Password:   "pwd1",
+//			},
+//		},
+//
+//		References: map[string]*ReferenceConfig{
+//			"MockService": {
+//				id: "MockProvider",
+//				Params: map[string]string{
+//					"serviceid": "soa.mock",
+//					"forks":     "5",
+//				},
+//				Sticky:        false,
+//				Registry:      "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2",
+//				InterfaceName: "com.MockService",
+//				Protocol:      "mock",
+//				Cluster:       "failover",
+//				Loadbalance:   "random",
+//				Retries:       "3",
+//				Group:         "huadong_idc",
+//				Version:       "1.0.0",
+//				Methods: []*method.MethodConfig{
+//					{
+//						Name:        "GetUser",
+//						Retries:     "2",
+//						LoadBalance: "random",
+//					},
+//					{
+//						Name:        "GetUser1",
+//						Retries:     "2",
+//						LoadBalance: "random",
+//						Sticky:      true,
+//					},
+//				},
+//			},
+//		},
+//	}
+//}
+//
+//var mockProvider = new(MockProvider)
+//
+//type MockProvider struct{}
+//
+//func (m *MockProvider) Reference() string {
+//	return "MockProvider"
+//}
+//
+//func (m *MockProvider) CallBack(res common.CallbackResponse) {
+//	// CallBack is a mock function. to implement the interface
+//}
+//
+//func doInitConsumerAsync() {
+//	doInitConsumer()
+//	instance.SetConsumerService(mockProvider)
+//	for _, v := range config.consumerConfig.References {
+//		v.Async = true
+//	}
+//}
+//
+//func doInitConsumerWithSingleRegistry() {
+//	config.consumerConfig = &consumer.Config{
+//		BaseConfig: base.Config{
+//			applicationConfig.Config: &applicationConfig.Config{
+//				Organization: "dubbo_org",
+//				Name:         "dubbo",
+//				Module:       "module",
+//				Version:      "2.6.0",
+//				Owner:        "dubbo",
+//				Environment:  "test",
+//			},
+//		},
+//
+//		Registry: &registry2.RegistryConfig{
+//			Address:  "mock://27.0.0.1:2181",
+//			Username: "user1",
+//			Password: "pwd1",
+//		},
+//		Registries: map[string]*registry2.RegistryConfig{},
+//
+//		References: map[string]*ReferenceConfig{
+//			"MockService": {
+//				Params: map[string]string{
+//					"serviceid": "soa.mock",
+//					"forks":     "5",
+//				},
+//				InterfaceName: "com.MockService",
+//				Protocol:      "mock",
+//				Cluster:       "failover",
+//				Loadbalance:   "random",
+//				Retries:       "3",
+//				Group:         "huadong_idc",
+//				Version:       "1.0.0",
+//				Methods: []*method.MethodConfig{
+//					{
+//						Name:        "GetUser",
+//						Retries:     "2",
+//						LoadBalance: "random",
+//					},
+//					{
+//						Name:        "GetUser1",
+//						Retries:     "2",
+//						LoadBalance: "random",
+//					},
+//				},
+//			},
+//		},
+//	}
+//}
+//
+//func TestReferMultiReg(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("registry", GetProtocol)
+//	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		assert.NotNil(t, reference.invoker)
+//		assert.NotNil(t, reference.pxy)
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestRefer(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("registry", GetProtocol)
+//	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
+//
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		assert.Equal(t, "soa.mock", reference.Params["serviceid"])
+//		assert.NotNil(t, reference.invoker)
+//		assert.NotNil(t, reference.pxy)
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestReferAsync(t *testing.T) {
+//	doInitConsumerAsync()
+//	extension.SetProtocol("registry", GetProtocol)
+//	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
+//
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		assert.Equal(t, "soa.mock", reference.Params["serviceid"])
+//		assert.NotNil(t, reference.invoker)
+//		assert.NotNil(t, reference.pxy)
+//		assert.NotNil(t, reference.pxy.GetCallback())
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestReferP2P(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("dubbo", GetProtocol)
+//	mockFilter()
+//	m := config.consumerConfig.References["MockService"]
+//	m.URL = "dubbo://127.0.0.1:20000"
+//
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		assert.NotNil(t, reference.invoker)
+//		assert.NotNil(t, reference.pxy)
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestReferMultiP2P(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("dubbo", GetProtocol)
+//	mockFilter()
+//	m := config.consumerConfig.References["MockService"]
+//	m.URL = "dubbo://127.0.0.1:20000;dubbo://127.0.0.2:20000"
+//
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		assert.NotNil(t, reference.invoker)
+//		assert.NotNil(t, reference.pxy)
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestReferMultiP2PWithReg(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("dubbo", GetProtocol)
+//	extension.SetProtocol("registry", GetProtocol)
+//	mockFilter()
+//	m := config.consumerConfig.References["MockService"]
+//	m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
+//
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		assert.NotNil(t, reference.invoker)
+//		assert.NotNil(t, reference.pxy)
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestImplement(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("registry", GetProtocol)
+//	extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		reference.Implement(&config.MockService{})
+//		assert.NotNil(t, reference.GetRPCService())
+//
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestForking(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("dubbo", GetProtocol)
+//	extension.SetProtocol("registry", GetProtocol)
+//	mockFilter()
+//	m := config.consumerConfig.References["MockService"]
+//	m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
+//
+//	for _, reference := range config.consumerConfig.References {
+//		reference.Refer(nil)
+//		forks := int(reference.invoker.GetURL().GetParamInt(constant.FORKS_KEY, constant.DEFAULT_FORKS))
+//		assert.Equal(t, 5, forks)
+//		assert.NotNil(t, reference.pxy)
+//		assert.NotNil(t, reference.Cluster)
+//	}
+//	config.consumerConfig = nil
+//}
+//
+//func TestSticky(t *testing.T) {
+//	doInitConsumer()
+//	extension.SetProtocol("dubbo", GetProtocol)
+//	extension.SetProtocol("registry", GetProtocol)
+//	mockFilter()
+//	m := config.consumerConfig.References["MockService"]
+//	m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
+//
+//	reference := config.consumerConfig.References["MockService"]
+//	reference.Refer(nil)
+//	referenceSticky := reference.invoker.GetURL().GetParam(constant.STICKY_KEY, "false")
+//	assert.Equal(t, "false", referenceSticky)
+//
+//	method0StickKey := reference.invoker.GetURL().GetMethodParam(reference.Methods[0].Name, constant.STICKY_KEY, "false")
+//	assert.Equal(t, "false", method0StickKey)
+//	method1StickKey := reference.invoker.GetURL().GetMethodParam(reference.Methods[1].Name, constant.STICKY_KEY, "false")
+//	assert.Equal(t, "true", method1StickKey)
+//}
+//
+//func GetProtocol() protocol.Protocol {
+//	if regProtocol != nil {
+//		return regProtocol
+//	}
+//	return newRegistryProtocol()
+//}
+//
+//func newRegistryProtocol() protocol.Protocol {
+//	return &mockRegistryProtocol{}
+//}
+//
+//type mockRegistryProtocol struct {
+//}
+//
+//func (*mockRegistryProtocol) Refer(url *common.URL) protocol.Invoker {
+//	return protocol.NewBaseInvoker(url)
+//}
+//
+//func (*mockRegistryProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
+//	registryURL := getRegistryURL(invoker)
+//	if registryURL.Protocol == "service-discovery" {
+//		metaDataService, err := extension.GetLocalMetadataService("")
+//		if err != nil {
+//			panic(err)
+//		}
+//		ok, err := metaDataService.ExportURL(invoker.GetURL().SubURL.Clone())
+//		if err != nil {
+//			panic(err)
+//		}
+//		if !ok {
+//			panic("The URL has been registry!")
+//		}
+//	}
+//	return protocol.NewBaseExporter("test", invoker, &sync.Map{})
+//}
+//
+//func (*mockRegistryProtocol) Destroy() {
+//	// Destroy is a mock function
+//}
+//
+//func getRegistryURL(invoker protocol.Invoker) *common.URL {
+//	// here add * for return a new url
+//	url := invoker.GetURL()
+//	// if the protocol == registry ,set protocol the registry value in url.params
+//	if url.Protocol == constant.REGISTRY_PROTOCOL {
+//		protocol := url.GetParam(constant.REGISTRY_KEY, "")
+//		url.Protocol = protocol
+//	}
+//	return url
+//}
+//
+//func (p *mockRegistryProtocol) GetRegistries() []registry.Registry {
+//	return []registry.Registry{&config.mockServiceDiscoveryRegistry{}}
+//}
+//
+//func mockFilter() {
+//	consumerFiler := &mockShutdownFilter{}
+//	extension.SetFilter(constant.GracefulShutdownConsumerFilterKey, func() filter.Filter {
+//		return consumerFiler
+//	})
+//}
+//
+//type mockShutdownFilter struct {
+//}
+//
+//// Invoke adds the requests count and block the new requests if applicationConfig is closing
+//func (gf *mockShutdownFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+//	return invoker.Invoke(ctx, invocation)
+//}
+//
+//// OnResponse reduces the number of active processes then return the process result
+//func (gf *mockShutdownFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+//	return result
+//}
diff --git a/config/registry_config.go b/config/registry_config.go
index 92d92a6..9b01aec 100644
--- a/config/registry_config.go
+++ b/config/registry_config.go
@@ -35,26 +35,37 @@ import (
 
 // RegistryConfig is the configuration of the registry center
 type RegistryConfig struct {
-	Protocol   string `required:"true" yaml:"protocol"  json:"protocol,omitempty" property:"protocol"`
-	TimeoutStr string `yaml:"timeout" default:"5s" json:"timeout,omitempty" property:"timeout"` // unit: second
-	Group      string `yaml:"group" json:"group,omitempty" property:"group"`
-	TTL        string `yaml:"ttl" default:"10m" json:"ttl,omitempty" property:"ttl"` // unit: minute
+	Protocol string `validate:"required" yaml:"protocol"  json:"protocol,omitempty" property:"protocol"`
+	Timeout  string `default:"10s" validate:"required" yaml:"timeout" json:"timeout,omitempty" property:"timeout"` // unit: second
+	Group    string `yaml:"group" json:"group,omitempty" property:"group"`
+	TTL      string `default:"10m" yaml:"ttl" json:"ttl,omitempty" property:"ttl"` // unit: minute
 	// for registry
-	Address    string `yaml:"address" json:"address,omitempty" property:"address"`
+	Address    string `validate:"required" yaml:"address" json:"address,omitempty" property:"address"`
 	Username   string `yaml:"username" json:"username,omitempty" property:"username"`
 	Password   string `yaml:"password" json:"password,omitempty"  property:"password"`
 	Simplified bool   `yaml:"simplified" json:"simplified,omitempty"  property:"simplified"`
-	// Always use this registry first if set to true, useful when subscribe to multiple registries
+	// Always use this registry first if set to true, useful when subscribe to multiple registriesConfig
 	Preferred bool `yaml:"preferred" json:"preferred,omitempty" property:"preferred"`
 	// The region where the registry belongs, usually used to isolate traffics
 	Zone string `yaml:"zone" json:"zone,omitempty" property:"zone"`
-	// Affects traffic distribution among registries,
-	// useful when subscribe to multiple registries Take effect only when no preferred registry is specified.
+	// Affects traffic distribution among registriesConfig,
+	// useful when subscribe to multiple registriesConfig Take effect only when no preferred registry is specified.
 	Weight int64             `yaml:"weight" json:"weight,omitempty" property:"weight"`
 	Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
 }
 
-// UnmarshalYAML unmarshals the RegistryConfig by @unmarshal function
+func (c *RegistryConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(c)
+	c.translateRegistryAddress()
+	return verify(c)
+}
+
+func (c *RegistryConfig) Validate() {
+	// todo set default application
+}
+
+// UnmarshalYAML unmarshal the RegistryConfig by @unmarshal function
 func (c *RegistryConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	if err := defaults.Set(c); err != nil {
 		return err
@@ -63,57 +74,9 @@ func (c *RegistryConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
 	return unmarshal((*plain)(c))
 }
 
-// nolint
-func (*RegistryConfig) Prefix() string {
-	return constant.RegistryConfigPrefix + "|" + constant.SingleRegistryConfigPrefix
-}
-
-func loadRegistries(targetRegistries string, registries map[string]*RegistryConfig, roleType common.RoleType) []*common.URL {
-	var urls []*common.URL
-	trSlice := strings.Split(targetRegistries, ",")
-
-	for k, registryConf := range registries {
-		target := false
-
-		// if user not config targetRegistries, default load all
-		// Notice: in func "func Split(s, sep string) []string" comment:
-		// if s does not contain sep and sep is not empty, SplitAfter returns
-		// a slice of length 1 whose only element is s. So we have to add the
-		// condition when targetRegistries string is not set (it will be "" when not set)
-		if len(trSlice) == 0 || (len(trSlice) == 1 && trSlice[0] == "") {
-			target = true
-		} else {
-			// else if user config targetRegistries
-			for _, tr := range trSlice {
-				if tr == k {
-					target = true
-					break
-				}
-			}
-		}
-
-		if target {
-			addresses := strings.Split(registryConf.Address, ",")
-			address := addresses[0]
-			address = translateRegistryConf(address, registryConf)
-			url, err := common.NewURL(constant.REGISTRY_PROTOCOL+"://"+address,
-				common.WithParams(registryConf.getUrlMap(roleType)),
-				common.WithParamsValue("simplified", strconv.FormatBool(registryConf.Simplified)),
-				common.WithUsername(registryConf.Username),
-				common.WithPassword(registryConf.Password),
-				common.WithLocation(registryConf.Address),
-			)
-
-			if err != nil {
-				logger.Errorf("The registry id: %s url is invalid, error: %#v", k, err)
-				panic(err)
-			} else {
-				urls = append(urls, url)
-			}
-		}
-	}
-
-	return urls
+// Prefix dubbo.registriesConfig
+func (RegistryConfig) Prefix() string {
+	return constant.RegistryConfigPrefix
 }
 
 func (c *RegistryConfig) getUrlMap(roleType common.RoleType) url.Values {
@@ -121,7 +84,7 @@ func (c *RegistryConfig) getUrlMap(roleType common.RoleType) url.Values {
 	urlMap.Set(constant.GROUP_KEY, c.Group)
 	urlMap.Set(constant.ROLE_KEY, strconv.Itoa(int(roleType)))
 	urlMap.Set(constant.REGISTRY_KEY, c.Protocol)
-	urlMap.Set(constant.REGISTRY_TIMEOUT_KEY, c.TimeoutStr)
+	urlMap.Set(constant.REGISTRY_TIMEOUT_KEY, c.Timeout)
 	// multi registry invoker weight label for load balance
 	urlMap.Set(constant.REGISTRY_KEY+"."+constant.REGISTRY_LABEL_KEY, strconv.FormatBool(true))
 	urlMap.Set(constant.REGISTRY_KEY+"."+constant.PREFERRED_KEY, strconv.FormatBool(c.Preferred))
@@ -134,16 +97,17 @@ func (c *RegistryConfig) getUrlMap(roleType common.RoleType) url.Values {
 	return urlMap
 }
 
-func translateRegistryConf(address string, registryConf *RegistryConfig) string {
-	if strings.Contains(address, "://") {
-		translatedUrl, err := url.Parse(address)
+//translateRegistryAddress translate registry address
+//  eg:address=nacos://127.0.0.1:8848 will return 127.0.0.1:8848 and protocol will set nacos
+func (c *RegistryConfig) translateRegistryAddress() string {
+	if strings.Contains(c.Address, "://") {
+		translatedUrl, err := url.Parse(c.Address)
 		if err != nil {
 			logger.Errorf("The registry url is invalid, error: %#v", err)
 			panic(err)
 		}
-		address = translatedUrl.Host
-		registryConf.Protocol = translatedUrl.Scheme
-		registryConf.Address = strings.Replace(registryConf.Address, translatedUrl.Scheme+"://", "", -1)
+		c.Protocol = translatedUrl.Scheme
+		c.Address = strings.Replace(c.Address, translatedUrl.Scheme+"://", "", -1)
 	}
-	return address
+	return c.Address
 }
diff --git a/config/registry_config_test.go b/config/registry_config_test.go
index 1ec85ca..f1f4716 100644
--- a/config/registry_config_test.go
+++ b/config/registry_config_test.go
@@ -29,16 +29,16 @@ import (
 )
 
 func TestLoadRegistries(t *testing.T) {
-	target := "shanghai1"
+	target := []string{"shanghai1"}
 	regs := map[string]*RegistryConfig{
 
 		"shanghai1": {
-			Protocol:   "mock",
-			TimeoutStr: "2s",
-			Group:      "shanghai_idc",
-			Address:    "127.0.0.2:2181,128.0.0.1:2181",
-			Username:   "user1",
-			Password:   "pwd1",
+			Protocol: "mock",
+			Timeout:  "2s",
+			Group:    "shanghai_idc",
+			Address:  "127.0.0.2:2181,128.0.0.1:2181",
+			Username: "user1",
+			Password: "pwd1",
 		},
 	}
 	urls := loadRegistries(target, regs, common.CONSUMER)
@@ -47,19 +47,29 @@ func TestLoadRegistries(t *testing.T) {
 }
 
 func TestLoadRegistries1(t *testing.T) {
-	target := "shanghai1"
+	target := []string{"shanghai1"}
 	regs := map[string]*RegistryConfig{
 
 		"shanghai1": {
-			Protocol:   "mock",
-			TimeoutStr: "2s",
-			Group:      "shanghai_idc",
-			Address:    "127.0.0.2:2181",
-			Username:   "user1",
-			Password:   "pwd1",
+			Protocol: "mock",
+			Timeout:  "2s",
+			Group:    "shanghai_idc",
+			Address:  "127.0.0.2:2181",
+			Username: "user1",
+			Password: "pwd1",
 		},
 	}
 	urls := loadRegistries(target, regs, common.CONSUMER)
 	t.Logf("loadRegistries() = urls:%v", urls)
 	assert.Equal(t, "127.0.0.2:2181", urls[0].Location)
 }
+
+func TestTranslateRegistryAddress(t *testing.T) {
+	reg := new(RegistryConfig)
+	reg.Address = "nacos://127.0.0.1:8848"
+
+	address := reg.translateRegistryAddress()
+
+	assert.Equal(t, "nacos", reg.Protocol)
+	assert.Equal(t, "127.0.0.1:8848", address)
+}
diff --git a/config/root_config.go b/config/root_config.go
new file mode 100644
index 0000000..e86f6b9
--- /dev/null
+++ b/config/root_config.go
@@ -0,0 +1,255 @@
+package config
+
+import (
+	"bytes"
+	"dubbo.apache.org/dubbo-go/v3/common/constant"
+	"github.com/creasty/defaults"
+)
+
+// RootConfig is the root config
+type RootConfig struct {
+	ConfigCenter *CenterConfig `yaml:"config-center" json:"config-center,omitempty"`
+
+	// since 1.5.0 version
+	Remotes map[string]*RemoteConfig `yaml:"remote" json:"remote,omitempty" property:"remote"`
+
+	ServiceDiscoveries map[string]*ServiceDiscoveryConfig `yaml:"service-discovery" json:"service-discovery,omitempty" property:"service-discovery"`
+
+	MetadataReportConfig *MetadataReportConfig `yaml:"metadata_report" json:"metadata-report,omitempty" property:"metadata-report"`
+
+	// Application applicationConfig config
+	Application *ApplicationConfig `validate:"required" yaml:"application" json:"application,omitempty" property:"application"`
+
+	// Registries registry config
+	Registries map[string]*RegistryConfig `yaml:"registries" json:"registries" property:"registries"`
+
+	Protocols map[string]*ProtocolConfig `validate:"required" yaml:"protocols" json:"protocols" property:"protocols"`
+
+	// provider config
+	Provider *ProviderConfig `yaml:"provider" json:"provider" property:"provider"`
+
+	// consumer config
+	Consumer *ConsumerConfig `yaml:"consumer" json:"consumer" property:"consumer"`
+
+	// prefix              string
+	fatherConfig        interface{}
+	EventDispatcherType string        `default:"direct" yaml:"event_dispatcher_type" json:"event_dispatcher_type,omitempty"`
+	MetricConfig        *MetricConfig `yaml:"metrics" json:"metrics,omitempty"`
+	fileStream          *bytes.Buffer
+
+	// cache file used to store the current used configurations.
+	CacheFile string `yaml:"cache_file" json:"cache_file,omitempty" property:"cache_file"`
+}
+
+func init() {
+	rootConfig = NewRootConfig()
+}
+
+func SetRootConfig(r RootConfig) {
+	rootConfig = &r
+}
+
+func NewRootConfig() *RootConfig {
+	return &RootConfig{
+		ConfigCenter:         &CenterConfig{},
+		ServiceDiscoveries:   make(map[string]*ServiceDiscoveryConfig),
+		MetadataReportConfig: &MetadataReportConfig{},
+		Application:          &ApplicationConfig{},
+		Registries:           make(map[string]*RegistryConfig),
+		Protocols:            make(map[string]*ProtocolConfig),
+		Provider:             NewProviderConfig(),
+		Consumer:             NewConsumerConfig(),
+		MetricConfig:         &MetricConfig{},
+	}
+}
+
+// Prefix dubbo
+func (RootConfig) Prefix() string {
+	return constant.DUBBO
+}
+
+func (rc *RootConfig) CheckConfig() error {
+	defaults.MustSet(rc)
+
+	if err := rc.Application.CheckConfig(); err != nil {
+		return err
+	}
+
+	for k, _ := range rc.Registries {
+		if err := rc.Registries[k].CheckConfig(); err != nil {
+			return err
+		}
+	}
+
+	for k, _ := range rc.Protocols {
+		if err := rc.Protocols[k].CheckConfig(); err != nil {
+			return err
+		}
+	}
+
+	if err := rc.ConfigCenter.CheckConfig(); err != nil {
+		return err
+	}
+
+	if err := rc.MetadataReportConfig.CheckConfig(); err != nil {
+		return err
+	}
+
+	if err := rc.Provider.CheckConfig(); err != nil {
+		return err
+	}
+
+	if err := rc.Consumer.CheckConfig(); err != nil {
+		return err
+	}
+
+	return verify(rootConfig)
+}
+
+func (rc *RootConfig) Validate() {
+	// 2. validate config
+	rc.Application.Validate()
+
+	for k, _ := range rc.Registries {
+		rc.Registries[k].Validate()
+	}
+
+	for k, _ := range rc.Protocols {
+		rc.Protocols[k].Validate()
+	}
+
+	for k, _ := range rc.Registries {
+		rc.Registries[k].Validate()
+	}
+
+	rc.ConfigCenter.Validate()
+	rc.MetadataReportConfig.Validate()
+	rc.Provider.Validate(rc)
+	rc.Consumer.Validate(rc)
+}
+
+//GetApplicationConfig get applicationConfig config
+func GetApplicationConfig() *ApplicationConfig {
+	if err := check(); err != nil {
+		return NewApplicationConfig()
+	}
+	if rootConfig.Application != nil {
+		return rootConfig.Application
+	}
+	return NewApplicationConfig()
+}
+
+func GetRootConfig() *RootConfig {
+	return rootConfig
+}
+
+func GetProviderConfig() *ProviderConfig {
+	if err := check(); err != nil {
+		return NewProviderConfig()
+	}
+	if rootConfig.Provider != nil {
+		return rootConfig.Provider
+	}
+	return NewProviderConfig()
+}
+
+func GetConsumerConfig() *ConsumerConfig {
+	if err := check(); err != nil {
+		return NewConsumerConfig()
+	}
+	if rootConfig.Consumer != nil {
+		return rootConfig.Consumer
+	}
+	return NewConsumerConfig()
+}
+
+// GetConfigCenterConfig get config center config
+//func GetConfigCenterConfig() (*CenterConfig, error) {
+//	if err := check(); err != nil {
+//		return nil, err
+//	}
+//	conf := rootConfig.ConfigCenter
+//	if conf == nil {
+//		return nil, errors.New("config center config is null")
+//	}
+//	if err := defaults.Set(conf); err != nil {
+//		return nil, err
+//	}
+//	conf.translateConfigAddress()
+//	if err := verify(conf); err != nil {
+//		return nil, err
+//	}
+//	return conf, nil
+//}
+
+// GetRegistriesConfig get registry config default zookeeper registry
+//func GetRegistriesConfig() (map[string]*RegistryConfig, error) {
+//	if err := check(); err != nil {
+//		return nil, err
+//	}
+//
+//	if registriesConfig != nil {
+//		return registriesConfig, nil
+//	}
+//	registriesConfig = getRegistriesConfig(rootConfig.Registries)
+//	for _, reg := range registriesConfig {
+//		if err := defaults.Set(reg); err != nil {
+//			return nil, err
+//		}
+//		reg.translateRegistryAddress()
+//		if err := verify(reg); err != nil {
+//			return nil, err
+//		}
+//	}
+//
+//	return registriesConfig, nil
+//}
+
+// GetProtocolsConfig get protocols config default dubbo protocol
+//func GetProtocolsConfig() (map[string]*ProtocolConfig, error) {
+//	if err := check(); err != nil {
+//		return nil, err
+//	}
+//
+//	protocols := getProtocolsConfig(rootConfig.Protocols)
+//	for _, protocol := range protocols {
+//		if err := defaults.Set(protocol); err != nil {
+//			return nil, err
+//		}
+//		if err := verify(protocol); err != nil {
+//			return nil, err
+//		}
+//	}
+//	return protocols, nil
+//}
+
+// GetProviderConfig get provider config
+//func GetProviderConfig() (*ProviderConfig, error) {
+//	if err := check(); err != nil {
+//		return nil, err
+//	}
+//
+//	if providerConfig != nil {
+//		return providerConfig, nil
+//	}
+//	provider := getProviderConfig(rootConfig.Provider)
+//	if err := defaults.Set(provider); err != nil {
+//		return nil, err
+//	}
+//	if err := verify(provider); err != nil {
+//		return nil, err
+//	}
+//
+//	provider.Services = getRegistryServices(common.PROVIDER, provider.Services, provider.Registry)
+//	providerConfig = provider
+//	return provider, nil
+//}
+
+//// getRegistryIds get registry keys
+//func getRegistryIds() []string {
+//	ids := make([]string, 0)
+//	for key := range rootConfig.Registries {
+//		ids = append(ids, key)
+//	}
+//	return removeDuplicateElement(ids)
+//}
diff --git a/config/service.go b/config/service.go
index 12cc91e..3aa524d 100644
--- a/config/service.go
+++ b/config/service.go
@@ -51,6 +51,11 @@ func GetAllProviderService() map[string]common.RPCService {
 	return proServices
 }
 
+// GetAllConsumerService gets all ConsumerService
+func GetAllConsumerService() map[string]common.RPCService {
+	return conServices
+}
+
 // GetCallback gets CallbackResponse by @name
 func GetCallback(name string) func(response common.CallbackResponse) {
 	service := GetConsumerService(name)
diff --git a/config/service_config.go b/config/service_config.go
index ebcac9a..16dc30b 100644
--- a/config/service_config.go
+++ b/config/service_config.go
@@ -19,6 +19,7 @@ package config
 
 import (
 	"container/list"
+	"dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
 	"fmt"
 	"net/url"
 	"strconv"
@@ -40,16 +41,15 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
-	"dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
 )
 
 // ServiceConfig is the configuration of the service provider
 type ServiceConfig struct {
 	id                          string
 	Filter                      string            `yaml:"filter" json:"filter,omitempty" property:"filter"`
-	Protocol                    string            `default:"dubbo"  required:"true"  yaml:"protocol"  json:"protocol,omitempty" property:"protocol"` // multi protocol support, split by ','
-	InterfaceName               string            `required:"true"  yaml:"interface"  json:"interface,omitempty" property:"interface"`
-	Registry                    string            `yaml:"registry"  json:"registry,omitempty"  property:"registry"`
+	Protocol                    []string          `default:"[\"dubbo\"]"  validate:"required"  yaml:"protocol"  json:"protocol,omitempty" property:"protocol"` // multi protocol support, split by ','
+	Interface                   string            `validate:"required"  yaml:"interface"  json:"interface,omitempty" property:"interface"`
+	Registry                    []string          `yaml:"registry"  json:"registry,omitempty"  property:"registry"`
 	Cluster                     string            `default:"failover" yaml:"cluster"  json:"cluster,omitempty" property:"cluster"`
 	Loadbalance                 string            `default:"random" yaml:"loadbalance"  json:"loadbalance,omitempty"  property:"loadbalance"`
 	Group                       string            `yaml:"group"  json:"group,omitempty" property:"group"`
@@ -83,14 +83,16 @@ type ServiceConfig struct {
 
 	exportersLock sync.Mutex
 	exporters     []protocol.Exporter
+
+	rootConfig *RootConfig
 }
 
-// Prefix returns dubbo.service.${interface}.
+// Prefix returns dubbo.service.${InterfaceName}.
 func (c *ServiceConfig) Prefix() string {
-	return constant.ServiceConfigPrefix + c.InterfaceName + "."
+	return constant.ServiceConfigPrefix + c.id
 }
 
-// UnmarshalYAML unmarshals the ServiceConfig by @unmarshal function
+// UnmarshalYAML unmarshal the ServiceConfig by @unmarshal function
 func (c *ServiceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	if err := defaults.Set(c); err != nil {
 		return err
@@ -105,14 +107,54 @@ func (c *ServiceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	return nil
 }
 
-// NewServiceConfig The only way to get a new ServiceConfig
-func NewServiceConfig(id string) *ServiceConfig {
-	return &ServiceConfig{
-		id:         id,
-		unexported: atomic.NewBool(false),
-		exported:   atomic.NewBool(false),
-		export:     true,
+func (c *ServiceConfig) CheckConfig() error {
+	// todo check
+	defaults.MustSet(c)
+	return verify(c)
+}
+
+func (c *ServiceConfig) Validate(rootConfig *RootConfig) {
+	c.rootConfig = rootConfig
+	c.exported = atomic.NewBool(false)
+	c.unexported = atomic.NewBool(false)
+	c.export = true
+	// todo set default application
+}
+
+//getRegistryServices get registry services
+func getRegistryServices(side int, services map[string]*ServiceConfig, registryIds []string) map[string]*ServiceConfig {
+	var (
+		svc              *ServiceConfig
+		exist            bool
+		initService      map[string]common.RPCService
+		registryServices map[string]*ServiceConfig
+	)
+	if side == common.PROVIDER {
+		initService = proServices
+	} else if side == common.CONSUMER {
+		initService = conServices
 	}
+	registryServices = make(map[string]*ServiceConfig, len(initService))
+	for key := range initService {
+		//存在配置了使用用户的配置
+		if svc, exist = services[key]; !exist {
+			svc = new(ServiceConfig)
+		}
+		defaults.MustSet(svc)
+		if len(svc.Registry) <= 0 {
+			svc.Registry = registryIds
+		}
+		svc.id = key
+		svc.export = true
+		svc.unexported = atomic.NewBool(false)
+		svc.exported = atomic.NewBool(false)
+		svc.Registry = translateRegistryIds(svc.Registry)
+		if err := verify(svc); err != nil {
+			return nil
+		}
+		registryServices[key] = svc
+	}
+	return registryServices
 }
 
 // InitExported will set exported as false atom bool
@@ -149,32 +191,32 @@ func (c *ServiceConfig) Export() error {
 
 	// TODO: delay export
 	if c.unexported != nil && c.unexported.Load() {
-		err := perrors.Errorf("The service %v has already unexported!", c.InterfaceName)
+		err := perrors.Errorf("The service %v has already unexported!", c.Interface)
 		logger.Errorf(err.Error())
 		return err
 	}
 	if c.unexported != nil && c.exported.Load() {
-		logger.Warnf("The service %v has already exported!", c.InterfaceName)
+		logger.Warnf("The service %v has already exported!", c.Interface)
 		return nil
 	}
 
-	regUrls := loadRegistries(c.Registry, providerConfig.Registries, common.PROVIDER)
+	regUrls := loadRegistries(c.Registry, c.rootConfig.Registries, common.PROVIDER)
 	urlMap := c.getUrlMap()
-	protocolConfigs := loadProtocol(c.Protocol, c.Protocols)
+	protocolConfigs := loadProtocol(c.Protocol, c.rootConfig.Protocols)
 	if len(protocolConfigs) == 0 {
-		logger.Warnf("The service %v's '%v' protocols don't has right protocolConfigs", c.InterfaceName, c.Protocol)
+		logger.Warnf("The service %v's '%v' protocols don't has right protocolConfigs", c.Interface, c.Protocol)
 		return nil
 	}
 
 	ports := getRandomPort(protocolConfigs)
 	nextPort := ports.Front()
-	proxyFactory := extension.GetProxyFactory(providerConfig.ProxyFactory)
+	proxyFactory := extension.GetProxyFactory(c.rootConfig.Provider.ProxyFactory)
 	for _, proto := range protocolConfigs {
 		// registry the service reflect
-		methods, err := common.ServiceMap.Register(c.InterfaceName, proto.Name, c.Group, c.Version, c.rpcService)
+		methods, err := common.ServiceMap.Register(c.Interface, proto.Name, c.Group, c.Version, c.rpcService)
 		if err != nil {
 			formatErr := perrors.Errorf("The service %v export the protocol %v error! Error message is %v.",
-				c.InterfaceName, proto.Name, err.Error())
+				c.Interface, proto.Name, err.Error())
 			logger.Errorf(formatErr.Error())
 			return formatErr
 		}
@@ -185,13 +227,13 @@ func (c *ServiceConfig) Export() error {
 			nextPort = nextPort.Next()
 		}
 		ivkURL := common.NewURLWithOptions(
-			common.WithPath(c.InterfaceName),
+			common.WithPath(c.Interface),
 			common.WithProtocol(proto.Name),
 			common.WithIp(proto.Ip),
 			common.WithPort(port),
 			common.WithParams(urlMap),
 			common.WithParamsValue(constant.BEAN_NAME_KEY, c.id),
-			common.WithParamsValue(constant.SSL_ENABLED_KEY, strconv.FormatBool(GetSslEnabled())),
+			//common.WithParamsValue(constant.SSL_ENABLED_KEY, strconv.FormatBool(config.GetSslEnabled())),
 			common.WithMethods(strings.Split(methods, ",")),
 			common.WithToken(c.Token),
 		)
@@ -244,6 +286,67 @@ func (c *ServiceConfig) Export() error {
 	return nil
 }
 
+//loadProtocol filter protocols by ids
+func loadProtocol(protocolIds []string, protocols map[string]*ProtocolConfig) []*ProtocolConfig {
+	returnProtocols := make([]*ProtocolConfig, 0, len(protocols))
+	for _, v := range protocolIds {
+		for k, protocol := range protocols {
+			if v == k {
+				returnProtocols = append(returnProtocols, protocol)
+			}
+		}
+	}
+	return returnProtocols
+}
+
+func loadRegistries(registryIds []string, registries map[string]*RegistryConfig, roleType common.RoleType) []*common.URL {
+	var urls []*common.URL
+	//trSlice := strings.Split(targetRegistries, ",")
+
+	for k, registryConf := range registries {
+		target := false
+
+		// if user not config targetRegistries, default load all
+		// Notice: in func "func Split(s, sep string) []string" comment:
+		// if s does not contain sep and sep is not empty, SplitAfter returns
+		// a slice of length 1 whose only element is s. So we have to add the
+		// condition when targetRegistries string is not set (it will be "" when not set)
+		if len(registryIds) == 0 || (len(registryIds) == 1 && registryIds[0] == "") {
+			target = true
+		} else {
+			// else if user config targetRegistries
+			for _, tr := range registryIds {
+				if tr == k {
+					target = true
+					break
+				}
+			}
+		}
+
+		if target {
+			addresses := strings.Split(registryConf.Address, ",")
+			address := addresses[0]
+			address = registryConf.translateRegistryAddress()
+			url, err := common.NewURL(constant.REGISTRY_PROTOCOL+"://"+address,
+				common.WithParams(registryConf.getUrlMap(roleType)),
+				common.WithParamsValue("simplified", strconv.FormatBool(registryConf.Simplified)),
+				common.WithUsername(registryConf.Username),
+				common.WithPassword(registryConf.Password),
+				common.WithLocation(registryConf.Address),
+			)
+
+			if err != nil {
+				logger.Errorf("The registry id: %s url is invalid, error: %#v", k, err)
+				panic(err)
+			} else {
+				urls = append(urls, url)
+			}
+		}
+	}
+
+	return urls
+}
+
 // Unexport will call unexport of all exporters service config exported
 func (c *ServiceConfig) Unexport() {
 	if !c.exported.Load() {
@@ -277,7 +380,7 @@ func (c *ServiceConfig) getUrlMap() url.Values {
 	for k, v := range c.Params {
 		urlMap.Set(k, v)
 	}
-	urlMap.Set(constant.INTERFACE_KEY, c.InterfaceName)
+	urlMap.Set(constant.INTERFACE_KEY, c.Interface)
 	urlMap.Set(constant.TIMESTAMP_KEY, strconv.FormatInt(time.Now().Unix(), 10))
 	urlMap.Set(constant.CLUSTER_KEY, c.Cluster)
 	urlMap.Set(constant.LOADBALANCE_KEY, c.Loadbalance)
@@ -291,17 +394,17 @@ func (c *ServiceConfig) getUrlMap() url.Values {
 	urlMap.Set(constant.MESSAGE_SIZE_KEY, strconv.Itoa(c.GrpcMaxMessageSize))
 	// todo: move
 	urlMap.Set(constant.SERIALIZATION_KEY, c.Serialization)
-	// application info
-	urlMap.Set(constant.APPLICATION_KEY, providerConfig.ApplicationConfig.Name)
-	urlMap.Set(constant.ORGANIZATION_KEY, providerConfig.ApplicationConfig.Organization)
-	urlMap.Set(constant.NAME_KEY, providerConfig.ApplicationConfig.Name)
-	urlMap.Set(constant.MODULE_KEY, providerConfig.ApplicationConfig.Module)
-	urlMap.Set(constant.APP_VERSION_KEY, providerConfig.ApplicationConfig.Version)
-	urlMap.Set(constant.OWNER_KEY, providerConfig.ApplicationConfig.Owner)
-	urlMap.Set(constant.ENVIRONMENT_KEY, providerConfig.ApplicationConfig.Environment)
+	// application config info
+	//urlMap.Set(constant.APPLICATION_KEY, applicationConfig.Name)
+	//urlMap.Set(constant.ORGANIZATION_KEY, applicationConfig.Organization)
+	//urlMap.Set(constant.NAME_KEY, applicationConfig.Name)
+	//urlMap.Set(constant.MODULE_KEY, applicationConfig.Module)
+	//urlMap.Set(constant.APP_VERSION_KEY, applicationConfig.Version)
+	//urlMap.Set(constant.OWNER_KEY, applicationConfig.Owner)
+	//urlMap.Set(constant.ENVIRONMENT_KEY, applicationConfig.Environment)
 
 	// filter
-	urlMap.Set(constant.SERVICE_FILTER_KEY, mergeValue(providerConfig.Filter, c.Filter, constant.DEFAULT_SERVICE_FILTERS))
+	urlMap.Set(constant.SERVICE_FILTER_KEY, mergeValue(c.rootConfig.Provider.Filter, c.Filter, constant.DEFAULT_SERVICE_FILTERS))
 
 	// filter special config
 	urlMap.Set(constant.AccessLogFilterKey, c.AccessLog)
@@ -365,3 +468,94 @@ func (c *ServiceConfig) postProcessConfig(url *common.URL) {
 		p.PostProcessServiceConfig(url)
 	}
 }
+
+// NewServiceConfig The only way to get a new ServiceConfig
+func NewServiceConfig(id string) *ServiceConfig {
+	return &ServiceConfig{
+		id:         id,
+		unexported: atomic.NewBool(false),
+		exported:   atomic.NewBool(false),
+		export:     true,
+	}
+}
+
+// ServiceConfigOpt is the option to init ServiceConfig
+type ServiceConfigOpt func(config *ServiceConfig) *ServiceConfig
+
+// NewDefaultServiceConfig returns default ServiceConfig
+func NewDefaultServiceConfig() *ServiceConfig {
+	newServiceConfig := NewServiceConfig("")
+	newServiceConfig.Params = make(map[string]string)
+	newServiceConfig.Methods = make([]*MethodConfig, 0, 8)
+	return newServiceConfig
+}
+
+// NewServiceConfigByAPI is named as api, because there is NewServiceConfig func already declared
+// NewServiceConfigByAPI returns ServiceConfig with given @opts
+func NewServiceConfigByAPI(opts ...ServiceConfigOpt) *ServiceConfig {
+	defaultServiceConfig := NewDefaultServiceConfig()
+	for _, v := range opts {
+		v(defaultServiceConfig)
+	}
+	return defaultServiceConfig
+}
+
+// WithServiceRegistry returns ServiceConfigOpt with given registryKey @registry
+func WithServiceRegistry(registry string) ServiceConfigOpt {
+	return func(config *ServiceConfig) *ServiceConfig {
+		config.Registry = append(config.Registry, registry)
+		return config
+	}
+}
+
+// WithServiceProtocol returns ServiceConfigOpt with given protocolKey @protocol
+func WithServiceProtocol(protocol string) ServiceConfigOpt {
+	return func(config *ServiceConfig) *ServiceConfig {
+		config.Protocol = append(config.Protocol, protocol)
+		return config
+	}
+}
+
+// WithServiceInterface returns ServiceConfigOpt with given @interfaceName
+func WithServiceInterface(interfaceName string) ServiceConfigOpt {
+	return func(config *ServiceConfig) *ServiceConfig {
+		config.Interface = interfaceName
+		return config
+	}
+}
+
+// WithServiceLoadBalance returns ServiceConfigOpt with given load balance @lb
+func WithServiceLoadBalance(lb string) ServiceConfigOpt {
+	return func(config *ServiceConfig) *ServiceConfig {
+		config.Loadbalance = lb
+		return config
+	}
+}
+
+// WithServiceWarmUpTime returns ServiceConfigOpt with given @warmUp time
+func WithServiceWarmUpTime(warmUp string) ServiceConfigOpt {
+	return func(config *ServiceConfig) *ServiceConfig {
+		config.Warmup = warmUp
+		return config
+	}
+}
+
+// WithServiceCluster returns ServiceConfigOpt with given cluster name @cluster
+func WithServiceCluster(cluster string) ServiceConfigOpt {
+	return func(config *ServiceConfig) *ServiceConfig {
+		config.Cluster = cluster
+		return config
+	}
+}
+
+// WithServiceMethod returns ServiceConfigOpt with given @name, @retries and load balance @lb
+func WithServiceMethod(name, retries, lb string) ServiceConfigOpt {
+	return func(config *ServiceConfig) *ServiceConfig {
+		config.Methods = append(config.Methods, &MethodConfig{
+			Name:        name,
+			Retries:     retries,
+			LoadBalance: lb,
+		})
+		return config
+	}
+}
diff --git a/config/service_config_test.go b/config/service_config_test.go
deleted file mode 100644
index 4c64c70..0000000
--- a/config/service_config_test.go
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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 config
-
-import (
-	"testing"
-)
-
-import (
-	"github.com/stretchr/testify/assert"
-	"go.uber.org/atomic"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common"
-	"dubbo.apache.org/dubbo-go/v3/common/extension"
-)
-
-func doInitProvider() {
-	providerConfig = &ProviderConfig{
-		BaseConfig: BaseConfig{
-			ApplicationConfig: &ApplicationConfig{
-				Organization: "dubbo_org",
-				Name:         "dubbo",
-				Module:       "module",
-				Version:      "2.6.0",
-				Owner:        "dubbo",
-				Environment:  "test",
-			},
-			Remotes: map[string]*RemoteConfig{
-				"test1": {
-					Address:    "127.0.0.5:2181",
-					TimeoutStr: "5s",
-					Username:   "user1",
-					Password:   "pwd1",
-					Params:     nil,
-				},
-			},
-			ServiceDiscoveries: map[string]*ServiceDiscoveryConfig{
-				"mock_servicediscovery": {
-					Protocol:  "mock",
-					RemoteRef: "test1",
-				},
-			},
-			MetadataReportConfig: &MetadataReportConfig{
-				Protocol:  "mock",
-				RemoteRef: "test1",
-			},
-		},
-		Services: map[string]*ServiceConfig{
-			"MockService": {
-				InterfaceName: "com.MockService",
-				Protocol:      "mock",
-				Registry:      "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2,hangzhou_service_discovery_reg",
-				Cluster:       "failover",
-				Loadbalance:   "random",
-				Retries:       "3",
-				Group:         "huadong_idc",
-				Version:       "1.0.0",
-				Methods: []*MethodConfig{
-					{
-						Name:        "GetUser",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-					{
-						Name:        "GetUser1",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-				},
-				exported: new(atomic.Bool),
-			},
-			"MockServiceNoRightProtocol": {
-				InterfaceName: "com.MockService",
-				Protocol:      "mock1",
-				Registry:      "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2,hangzhou_service_discovery_reg",
-				Cluster:       "failover",
-				Loadbalance:   "random",
-				Retries:       "3",
-				Group:         "huadong_idc",
-				Version:       "1.0.0",
-				Methods: []*MethodConfig{
-					{
-						Name:        "GetUser",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-					{
-						Name:        "GetUser1",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-				},
-				exported: new(atomic.Bool),
-			},
-		},
-
-		Registries: map[string]*RegistryConfig{
-			"shanghai_reg1": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "shanghai_idc",
-				Address:    "127.0.0.1:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-			"shanghai_reg2": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "shanghai_idc",
-				Address:    "127.0.0.2:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-			"hangzhou_reg1": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "hangzhou_idc",
-				Address:    "127.0.0.3:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-			"hangzhou_reg2": {
-				Protocol:   "mock",
-				TimeoutStr: "2s",
-				Group:      "hangzhou_idc",
-				Address:    "127.0.0.4:2181",
-				Username:   "user1",
-				Password:   "pwd1",
-			},
-			"hangzhou_service_discovery_reg": {
-				Protocol: "service-discovery",
-				Params: map[string]string{
-					"service_discovery": "mock_servicediscovery",
-					"name_mapping":      "in-memory",
-					"metadata":          "default",
-				},
-			},
-		},
-
-		Protocols: map[string]*ProtocolConfig{
-			"mock": {
-				Name: "mock",
-				Ip:   "127.0.0.1",
-				Port: "20000",
-			},
-		},
-	}
-}
-
-func TestExport(t *testing.T) {
-	doInitProvider()
-	extension.SetProtocol("registry", GetProtocol)
-
-	for i := range providerConfig.Services {
-		service := providerConfig.Services[i]
-		service.Implement(&MockService{})
-		service.Protocols = providerConfig.Protocols
-		err := service.Export()
-		assert.Nil(t, err)
-	}
-	providerConfig = nil
-}
-
-func TestGetRandomPort(t *testing.T) {
-	protocolConfigs := make([]*ProtocolConfig, 0, 3)
-
-	ip := common.GetLocalIp()
-	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
-		Ip: ip,
-	})
-	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
-		Ip: ip,
-	})
-	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
-		Ip: ip,
-	})
-	// assert.NoError(t, err)
-	ports := getRandomPort(protocolConfigs)
-
-	assert.Equal(t, ports.Len(), len(protocolConfigs))
-
-	front := ports.Front()
-	for {
-		if front == nil {
-			break
-		}
-		t.Logf("port:%v", front.Value)
-		front = front.Next()
-	}
-
-	protocolConfigs = make([]*ProtocolConfig, 0, 3)
-	ports = getRandomPort(protocolConfigs)
-	assert.Equal(t, ports.Len(), len(protocolConfigs))
-}
diff --git a/config/service_discovery_config.go b/config/service_discovery_config.go
index 4362dd6..b08a16a 100644
--- a/config/service_discovery_config.go
+++ b/config/service_discovery_config.go
@@ -31,6 +31,6 @@ type ServiceDiscoveryConfig struct {
 	RemoteRef string `yaml:"remote_ref" json:"remote_ref,omitempty" property:"remote_ref"`
 }
 
-func (c *ServiceDiscoveryConfig) Prefix() string {
+func (ServiceDiscoveryConfig) Prefix() string {
 	return constant.ServiceDiscPrefix
 }
diff --git a/config/testdata/application.yaml b/config/testdata/application.yaml
new file mode 100644
index 0000000..f0876a1
--- /dev/null
+++ b/config/testdata/application.yaml
@@ -0,0 +1,35 @@
+dubbo:
+  application:
+    name: dubbo-go
+    module: local
+    version: 1.0.0
+    owner: zhaoyunxing
+  config-center:
+    address: nacos://127.0.0.1:8848
+    cluster: dev
+    namespace: dubbo
+    log-dir: ./logs
+  protocols:
+    dubbo:
+      name: dubbo
+      ip: 127.0.0.1
+      port: 20000
+  registries:
+    nacos:
+      timeout: 5s
+      group: dev
+      address: nacos://127.0.0.1:8848
+    zk:
+      protocol: zookeeper
+      group: dev
+      address: 127.0.0.1:2181
+  services:
+    helloService:
+      interface: org.dubbo.service.HelloService
+      registry: nacos,zk
+    orderService:
+      interface: org.dubbo.service.OrderService
+      registry: nacos
+  provider:
+    register: true
+    services:
\ No newline at end of file
diff --git a/config/testdata/config/app/application.yaml b/config/testdata/config/app/application.yaml
new file mode 100644
index 0000000..9c7e6c8
--- /dev/null
+++ b/config/testdata/config/app/application.yaml
@@ -0,0 +1,6 @@
+dubbo:
+  application:
+    name: dubbo-go
+    module: local
+    version: 1.0.0
+    owner: zhaoyunxing
\ No newline at end of file
diff --git a/config/testdata/config/center/conf-application.yaml b/config/testdata/config/center/conf-application.yaml
new file mode 100644
index 0000000..bc0a93f
--- /dev/null
+++ b/config/testdata/config/center/conf-application.yaml
@@ -0,0 +1,13 @@
+dubbo:
+  registries:
+    nacos:
+      timeout: 5s
+      group: dev
+      address: nacos://127.0.0.1:8848
+  config-center:
+    address: nacos://127.0.0.1:8848
+    cluster: dev
+    namespace: dubbo
+    log-dir: ./logs
+    config-file: dubbo.yaml
+    app-id: dubbo
\ No newline at end of file
diff --git a/config/testdata/config/protocol/application.yaml b/config/testdata/config/protocol/application.yaml
new file mode 100644
index 0000000..0288dac
--- /dev/null
+++ b/config/testdata/config/protocol/application.yaml
@@ -0,0 +1,6 @@
+dubbo:
+  protocols:
+    dubbo:
+      name: dubbo
+      ip: 127.0.0.1
+      port: 20000
\ No newline at end of file
diff --git a/config/testdata/config/protocol/empty_application.yaml b/config/testdata/config/protocol/empty_application.yaml
new file mode 100644
index 0000000..bc0aecb
--- /dev/null
+++ b/config/testdata/config/protocol/empty_application.yaml
@@ -0,0 +1,2 @@
+dubbo:
+  protocols:
\ No newline at end of file
diff --git a/config/testdata/config/provider/application.yaml b/config/testdata/config/provider/application.yaml
new file mode 100644
index 0000000..45e7231
--- /dev/null
+++ b/config/testdata/config/provider/application.yaml
@@ -0,0 +1,12 @@
+dubbo:
+  provider:
+    register: true
+    registry:
+     - nacos
+     - zk
+    services:
+      helloService:
+        interface: org.dubbo.service.HelloService
+        registry: nacos,zk
+      orderService:
+        interface: org.dubbo.service.OrderService
\ No newline at end of file
diff --git a/config/testdata/config/provider/empty_registry_application.yaml b/config/testdata/config/provider/empty_registry_application.yaml
new file mode 100644
index 0000000..c171c86
--- /dev/null
+++ b/config/testdata/config/provider/empty_registry_application.yaml
@@ -0,0 +1,8 @@
+dubbo:
+  registries:
+    nacos:
+      timeout: 5s
+      group: dev
+      address: nacos://127.0.0.1:8848
+  provider:
+    register: true
\ No newline at end of file
diff --git a/config/testdata/config/provider/registry_application.yaml b/config/testdata/config/provider/registry_application.yaml
new file mode 100644
index 0000000..f5b04de
--- /dev/null
+++ b/config/testdata/config/provider/registry_application.yaml
@@ -0,0 +1,10 @@
+dubbo:
+  provider:
+    register: true
+    registry: nacos,zk
+    services:
+      helloService:
+        interface: org.dubbo.service.HelloService
+        registry: nacos,zk
+      orderService:
+        interface: org.dubbo.service.OrderService
\ No newline at end of file
diff --git a/config/testdata/config/registry/application.yaml b/config/testdata/config/registry/application.yaml
new file mode 100644
index 0000000..8443538
--- /dev/null
+++ b/config/testdata/config/registry/application.yaml
@@ -0,0 +1,10 @@
+dubbo:
+  registries:
+    nacos:
+      timeout: 5s
+      group: dev
+      address: nacos://127.0.0.1:8848
+    zk:
+      protocol: zookeeper
+      group: test
+      address: 127.0.0.1:2181
\ No newline at end of file
diff --git a/config/testdata/config/registry/empty_application.yaml b/config/testdata/config/registry/empty_application.yaml
new file mode 100644
index 0000000..9e7a20a
--- /dev/null
+++ b/config/testdata/config/registry/empty_application.yaml
@@ -0,0 +1,2 @@
+dubbo:
+  registries:
\ No newline at end of file
diff --git a/config/testdata/config/service/hello_service.go b/config/testdata/config/service/hello_service.go
new file mode 100644
index 0000000..ff0726c
--- /dev/null
+++ b/config/testdata/config/service/hello_service.go
@@ -0,0 +1,18 @@
+package service
+
+import (
+	"context"
+)
+
+type HelloService struct {
+	// say hello
+	Say func(ctx context.Context, req []interface{}) error
+}
+
+func (HelloService) Name() string {
+	return "helloService"
+}
+
+func (HelloService) Reference() string {
+	return "org.github.dubbo.HelloService"
+}
diff --git a/config/testdata/config/service/order_service.go b/config/testdata/config/service/order_service.go
new file mode 100644
index 0000000..07a256b
--- /dev/null
+++ b/config/testdata/config/service/order_service.go
@@ -0,0 +1,18 @@
+package service
+
+import (
+	"context"
+)
+
+type OrderService struct {
+	// GetOrders
+	GetOrders func(ctx context.Context, req []interface{}) error
+}
+
+func (OrderService) Name() string {
+	return "orderService"
+}
+
+func (OrderService) Reference() string {
+	return "org.github.dubbo.OrderService"
+}
diff --git a/config_center/apollo/impl.go b/config_center/apollo/impl.go
index 8a0a28d..95c754e 100644
--- a/config_center/apollo/impl.go
+++ b/config_center/apollo/impl.go
@@ -132,7 +132,7 @@ func (c *apolloConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet
 
 func (c *apolloConfiguration) GetProperties(key string, opts ...cc.Option) (string, error) {
 	/**
-	 * when group is not null, we are getting startup configs(config file) from Config Center, for example:
+	 * when group is not null, we are getting startup configs(config file) from ShutdownConfig Center, for example:
 	 * key=dubbo.propertie
 	 */
 	tmpConfig := agollo.GetConfig(key)
diff --git a/config_center/apollo/impl_test.go b/config_center/apollo/impl_test.go
index 3392868..02cc547 100644
--- a/config_center/apollo/impl_test.go
+++ b/config_center/apollo/impl_test.go
@@ -17,6 +17,7 @@
 package apollo
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"fmt"
 	"net/http"
 	"net/http/httptest"
@@ -33,7 +34,6 @@ import (
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/common"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 	"dubbo.apache.org/dubbo-go/v3/config_center/parser"
 	"dubbo.apache.org/dubbo-go/v3/remoting"
@@ -184,7 +184,7 @@ func TestGetConfigItem(t *testing.T) {
 }
 
 func initMockApollo(t *testing.T) *apolloConfiguration {
-	c := &config.BaseConfig{ConfigCenterConfig: &config.ConfigCenterConfig{
+	c := &config.RootConfig{ConfigCenter: &config.CenterConfig{
 		Protocol:  "apollo",
 		Address:   "106.12.25.204:8080",
 		AppID:     "testApplication_yang",
@@ -193,7 +193,7 @@ func initMockApollo(t *testing.T) *apolloConfiguration {
 	}}
 	apollo := initApollo()
 	apolloUrl := strings.ReplaceAll(apollo.URL, "http", "apollo")
-	url, err := common.NewURL(apolloUrl, common.WithParams(c.ConfigCenterConfig.GetUrlMap()))
+	url, err := common.NewURL(apolloUrl, common.WithParams(c.ConfigCenter.GetUrlMap()))
 	assert.NoError(t, err)
 	configuration, err := newApolloConfiguration(url)
 	assert.NoError(t, err)
diff --git a/filter/hystrix/filter.go b/filter/hystrix/filter.go
index 8dbdae9..39e0670 100644
--- a/filter/hystrix/filter.go
+++ b/filter/hystrix/filter.go
@@ -199,7 +199,7 @@ func newFilterConsumer() filter.Filter {
 	// When first called, load the config in
 	consumerConfigOnce.Do(func() {
 		if err := initConfigConsumer(); err != nil {
-			logger.Warnf("[Hystrix Filter]Config load failed for consumer, error is: %v , will use default", err)
+			logger.Warnf("[Hystrix Filter]ShutdownConfig load failed for consumer, error is: %v , will use default", err)
 		}
 	})
 	return &Filter{COrP: true}
@@ -209,7 +209,7 @@ func newFilterConsumer() filter.Filter {
 func newFilterProvider() filter.Filter {
 	providerConfigOnce.Do(func() {
 		if err := initConfigProvider(); err != nil {
-			logger.Warnf("[Hystrix Filter]Config load failed for provider, error is: %v , will use default", err)
+			logger.Warnf("[Hystrix Filter]ShutdownConfig load failed for provider, error is: %v , will use default", err)
 		}
 	})
 	return &Filter{COrP: false}
@@ -300,7 +300,7 @@ type CommandConfigWithError struct {
 	Error                  []string `yaml:"error_whitelist"`
 }
 
-//Config:
+//ShutdownConfig:
 //- Timeout: how long to wait for command to complete, in milliseconds
 //- MaxConcurrentRequests: how many commands of the same type can run at the same time
 //- RequestVolumeThreshold: the minimum number of requests needed before a circuit can be tripped due to health
diff --git a/go.mod b/go.mod
index c1861c2..1fa9062 100644
--- a/go.mod
+++ b/go.mod
@@ -18,12 +18,14 @@ require (
 	github.com/fsnotify/fsnotify v1.4.9
 	github.com/ghodss/yaml v1.0.0
 	github.com/go-co-op/gocron v0.1.1
+	github.com/go-playground/validator/v10 v10.7.0
 	github.com/go-resty/resty/v2 v2.3.0
 	github.com/golang/mock v1.4.4
 	github.com/golang/protobuf v1.5.2
 	github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
 	github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267
 	github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
+	github.com/knadh/koanf v1.1.1
 	github.com/magiconair/properties v1.8.5
 	github.com/mitchellh/mapstructure v1.4.1
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
diff --git a/go.sum b/go.sum
index 120647f..5411fce 100644
--- a/go.sum
+++ b/go.sum
@@ -51,8 +51,6 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDH
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/apache/dubbo-getty v1.4.3 h1:PCKpryDasKOxwT5MBC6MIMO+0NLOaHF6Xco9YXQw7HI=
 github.com/apache/dubbo-getty v1.4.3/go.mod h1:ansXgKxxyhCOiQL29nO5ce1MDcEKmCyZuNR9oMs3hek=
-github.com/apache/dubbo-getty v1.4.4 h1:pthYQaCXyjHJ6/SjVwKkX5NhdAqSpUrRL1Z9GowrLdE=
-github.com/apache/dubbo-getty v1.4.4/go.mod h1:mcDyiu7M/TVrYDyL8TxDemQkOdvEqqHSQ4jOuYejY1w=
 github.com/apache/dubbo-go-hessian2 v1.9.1/go.mod h1:xQUjE7F8PX49nm80kChFvepA/AvqAZ0oh/UaB6+6pBE=
 github.com/apache/dubbo-go-hessian2 v1.9.2 h1:XuI8KvENSfKiAhiCBS4RNihmQDoPNmGWKT3gTui0p9A=
 github.com/apache/dubbo-go-hessian2 v1.9.2/go.mod h1:xQUjE7F8PX49nm80kChFvepA/AvqAZ0oh/UaB6+6pBE=
@@ -130,7 +128,6 @@ github.com/dubbogo/go-zookeeper v1.0.3 h1:UkuY+rBsxdT7Bs63QAzp9z7XqQ53W1j8E5rwl8
 github.com/dubbogo/go-zookeeper v1.0.3/go.mod h1:fn6n2CAEer3novYgk9ULLwAjuV8/g4DdC2ENwRb6E+c=
 github.com/dubbogo/gost v1.9.0/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
 github.com/dubbogo/gost v1.10.1/go.mod h1:+mQGS51XQEUWZP2JeGZTxJwipjRKtJO7Tr+FOg+72rI=
-github.com/dubbogo/gost v1.11.12/go.mod h1:vIcP9rqz2KsXHPjsAwIUtfJIJjppQLQDcYaZTy/61jI=
 github.com/dubbogo/gost v1.11.13 h1:sWvK1QbHpPBMmRQJV9qIH3syLegQBQa4xAPof3/Kv5c=
 github.com/dubbogo/gost v1.11.13/go.mod h1:vIcP9rqz2KsXHPjsAwIUtfJIJjppQLQDcYaZTy/61jI=
 github.com/dubbogo/jsonparser v1.0.1/go.mod h1:tYAtpctvSP/tWw4MeelsowSPgXQRVHHWbqL6ynps8jU=
@@ -191,6 +188,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
+github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
 github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@@ -202,6 +200,14 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+
 github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
 github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
 github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.7.0 h1:gLi5ajTBBheLNt0ctewgq7eolXoDALQd5/y90Hh9ZgM=
+github.com/go-playground/validator/v10 v10.7.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
 github.com/go-redis/redis v6.15.5+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=
 github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU=
@@ -306,6 +312,7 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
 github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
 github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
 github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
+github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
 github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
 github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
@@ -313,7 +320,9 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP
 github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
 github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
 github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
+github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
 github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
 github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
 github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
 github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
@@ -332,9 +341,12 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
 github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
 github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
+github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
 github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 h1:e1ok06zGrWJW91rzRroyl5nRNqraaBe4d5hiKcVZuHM=
 github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
+github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
@@ -347,6 +359,8 @@ github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXT
 github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
 github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
@@ -372,6 +386,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/knadh/koanf v1.1.1 h1:doO5UBvSXcmngdr/u54HKe+Uz4ZZw0/YHVzSsnE3vD4=
+github.com/knadh/koanf v1.1.1/go.mod h1:xpPTwMhsA/aaQLAilyCCqfpEiY1gpa160AiCuWHJUjY=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -382,6 +398,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
 github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 h1:0iQektZGS248WXmGIYOwRXSQhD4qn3icjMpuxwO7qlo=
 github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570/go.mod h1:BLt8L9ld7wVsvEWQbuLrUZnCMnUmLZ+CGDzKtclrTlE=
 github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f h1:sgUSP4zdTUZYZgAGGtN5Lxk92rK+JUFOwf+FT99EEI4=
@@ -411,6 +429,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
+github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -423,6 +443,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
 github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
 github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -430,7 +452,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
 github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
 github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
@@ -478,8 +499,9 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
-github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
+github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
@@ -534,6 +556,7 @@ github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULU
 github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
 github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -780,6 +803,7 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -793,6 +817,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -854,6 +879,7 @@ google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3
 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -901,6 +927,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
 google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -917,6 +944,7 @@ gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
diff --git a/metadata/mapping/dynamic/service_name_mapping.go b/metadata/mapping/dynamic/service_name_mapping.go
index b81423d..e1dbb7d 100644
--- a/metadata/mapping/dynamic/service_name_mapping.go
+++ b/metadata/mapping/dynamic/service_name_mapping.go
@@ -18,6 +18,7 @@
 package dynamic
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"strconv"
 	"sync"
 	"time"
@@ -33,7 +34,6 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 	"dubbo.apache.org/dubbo-go/v3/metadata/mapping"
 )
diff --git a/metadata/mapping/dynamic/service_name_mapping_test.go b/metadata/mapping/dynamic/service_name_mapping_test.go
index 1f5940c..75aa80b 100644
--- a/metadata/mapping/dynamic/service_name_mapping_test.go
+++ b/metadata/mapping/dynamic/service_name_mapping_test.go
@@ -18,6 +18,7 @@
 package dynamic
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -28,7 +29,6 @@ import (
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 )
 
diff --git a/metadata/mapping/memory/service_name_mapping.go b/metadata/mapping/memory/service_name_mapping.go
index cc10439..3175a50 100644
--- a/metadata/mapping/memory/service_name_mapping.go
+++ b/metadata/mapping/memory/service_name_mapping.go
@@ -18,6 +18,7 @@
 package memory
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"sync"
 )
 
@@ -27,7 +28,6 @@ import (
 
 import (
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/metadata/mapping"
 )
 
diff --git a/metadata/service/exporter/configurable/exporter.go b/metadata/service/exporter/configurable/exporter.go
index f3f2858..d6b4ebe 100644
--- a/metadata/service/exporter/configurable/exporter.go
+++ b/metadata/service/exporter/configurable/exporter.go
@@ -18,6 +18,7 @@
 package configurable
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"errors"
 	"sync"
 )
@@ -26,7 +27,6 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/metadata/service"
 	"dubbo.apache.org/dubbo-go/v3/metadata/service/exporter"
 )
@@ -49,7 +49,7 @@ func NewMetadataServiceExporter(metadataService service.MetadataService) exporte
 func (exporter *MetadataServiceExporter) Export(url *common.URL) error {
 	if !exporter.IsExported() {
 		serviceConfig := config.NewServiceConfig(constant.SIMPLE_METADATA_SERVICE_NAME)
-		serviceConfig.Protocol = constant.DEFAULT_PROTOCOL
+		serviceConfig.Protocol = []string{constant.DEFAULT_PROTOCOL}
 		if url == nil || url.SubURL == nil {
 			return errors.New("metadata server url is nil, pls check your configuration")
 		}
@@ -59,8 +59,8 @@ func (exporter *MetadataServiceExporter) Export(url *common.URL) error {
 				Port: url.SubURL.Port,
 			},
 		}
-		serviceConfig.Registry = "N/A"
-		serviceConfig.InterfaceName = constant.METADATA_SERVICE_NAME
+		serviceConfig.Registry = []string{"N/A"}
+		serviceConfig.Interface = constant.METADATA_SERVICE_NAME
 		// identify this is a golang server
 		serviceConfig.Params = map[string]string{}
 
diff --git a/metadata/service/exporter/configurable/exporter_test.go b/metadata/service/exporter/configurable/exporter_test.go
index 3ae6750..f94aa12 100644
--- a/metadata/service/exporter/configurable/exporter_test.go
+++ b/metadata/service/exporter/configurable/exporter_test.go
@@ -18,6 +18,7 @@
 package configurable
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"testing"
 )
 
@@ -28,7 +29,6 @@ import (
 import (
 	"dubbo.apache.org/dubbo-go/v3/common"
 	_ "dubbo.apache.org/dubbo-go/v3/common/proxy/proxy_factory"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	_ "dubbo.apache.org/dubbo-go/v3/filter/filter_impl"
 	"dubbo.apache.org/dubbo-go/v3/metadata/service/local"
 	_ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo"
@@ -78,49 +78,22 @@ func TestConfigurableExporter(t *testing.T) {
 
 // mockInitProviderWithSingleRegistry will init a mocked providerConfig
 func mockInitProviderWithSingleRegistry() {
-	providerConfig := &config.ProviderConfig{
-
-		BaseConfig: config.BaseConfig{
-			ApplicationConfig: &config.ApplicationConfig{
-				Organization: "dubbo_org",
-				Name:         "dubbo",
-				Module:       "module",
-				Version:      "1.0.0",
-				Owner:        "dubbo",
-				Environment:  "test",
-			},
-		},
-
-		Registry: &config.RegistryConfig{
-			Address:  "mock://127.0.0.1:2181",
-			Username: "user1",
-			Password: "pwd1",
+	providerConfig := &config.ProviderConfig{}
+	providerConfig.Services["MockService"].InitExported()
+	config.SetRootConfig(config.RootConfig{
+		Application: &config.ApplicationConfig{
+			Organization: "dubbo_org",
+			Name:         "dubbo",
+			Module:       "module",
+			Version:      "1.0.0",
+			Owner:        "dubbo",
+			Environment:  "test",
 		},
-		Registries: map[string]*config.RegistryConfig{},
-
-		Services: map[string]*config.ServiceConfig{
-			"MockService": {
-				InterfaceName: "com.MockService",
-				Protocol:      "mock",
-				Cluster:       "failover",
-				Loadbalance:   "random",
-				Retries:       "3",
-				Group:         "huadong_idc",
-				Version:       "1.0.0",
-				Methods: []*config.MethodConfig{
-					{
-						Name:        "GetUser",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-					{
-						Name:        "GetUser1",
-						Retries:     "2",
-						LoadBalance: "random",
-						Weight:      200,
-					},
-				},
+		Registries: map[string]*config.RegistryConfig{
+			"mock": {
+				Address:  "mock://127.0.0.1:2181",
+				Username: "user1",
+				Password: "pwd1",
 			},
 		},
 		Protocols: map[string]*config.ProtocolConfig{
@@ -130,7 +103,33 @@ func mockInitProviderWithSingleRegistry() {
 				Port: "20000",
 			},
 		},
-	}
-	providerConfig.Services["MockService"].InitExported()
-	config.SetProviderConfig(*providerConfig)
+
+		Provider: &config.ProviderConfig{
+			Services: map[string]*config.ServiceConfig{
+				"MockService": {
+					Interface:   "com.MockService",
+					Protocol:    []string{"mock"},
+					Cluster:     "failover",
+					Loadbalance: "random",
+					Retries:     "3",
+					Group:       "huadong_idc",
+					Version:     "1.0.0",
+					Methods: []*config.MethodConfig{
+						{
+							Name:        "GetUser",
+							Retries:     "2",
+							LoadBalance: "random",
+							Weight:      200,
+						},
+						{
+							Name:        "GetUser1",
+							Retries:     "2",
+							LoadBalance: "random",
+							Weight:      200,
+						},
+					},
+				},
+			},
+		},
+	})
 }
diff --git a/metadata/service/local/service.go b/metadata/service/local/service.go
index 794d463..2d92095 100644
--- a/metadata/service/local/service.go
+++ b/metadata/service/local/service.go
@@ -17,6 +17,7 @@
 package local
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"sort"
 	"sync"
 )
@@ -30,7 +31,6 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/metadata/definition"
 	"dubbo.apache.org/dubbo-go/v3/metadata/service"
 )
diff --git a/protocol/dubbo3/common_test.go b/protocol/dubbo3/common_test.go
index f137e84..27150db 100644
--- a/protocol/dubbo3/common_test.go
+++ b/protocol/dubbo3/common_test.go
@@ -19,6 +19,7 @@ package dubbo3
 
 import (
 	"context"
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"fmt"
 )
 
@@ -27,7 +28,6 @@ import (
 )
 
 import (
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 	"dubbo.apache.org/dubbo-go/v3/protocol/dubbo3/internal"
 	"dubbo.apache.org/dubbo-go/v3/protocol/invocation"
diff --git a/protocol/dubbo3/dubbo3_protocol.go b/protocol/dubbo3/dubbo3_protocol.go
index 25ca875..df90c3b 100644
--- a/protocol/dubbo3/dubbo3_protocol.go
+++ b/protocol/dubbo3/dubbo3_protocol.go
@@ -18,6 +18,7 @@ package dubbo3
 
 import (
 	"context"
+	"dubbo.apache.org/dubbo-go/v3/config"
 	"fmt"
 	"reflect"
 	"sync"
@@ -35,7 +36,6 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 	"dubbo.apache.org/dubbo-go/v3/protocol/invocation"
 )
diff --git a/protocol/dubbo3/internal/client.go b/protocol/dubbo3/internal/client.go
index 2b1d8e0..d85662c 100644
--- a/protocol/dubbo3/internal/client.go
+++ b/protocol/dubbo3/internal/client.go
@@ -19,16 +19,13 @@ package internal
 
 import (
 	"context"
+	"dubbo.apache.org/dubbo-go/v3/config"
 )
 
 import (
 	"github.com/dubbogo/triple/pkg/triple"
 )
 
-import (
-	"dubbo.apache.org/dubbo-go/v3/config"
-)
-
 func init() {
 	config.SetConsumerService(&GrpcGreeterImpl{})
 }
diff --git a/protocol/grpc/client.go b/protocol/grpc/client.go
index 66208c8..84d812d 100644
--- a/protocol/grpc/client.go
+++ b/protocol/grpc/client.go
@@ -39,8 +39,8 @@ import (
 var clientConf *ClientConfig
 
 func init() {
-	// load clientconfig from consumer_config
-	consumerConfig := config.GetConsumerConfig()
+	// load rootConfig from runtime
+	rootConfig := config.GetRootConfig()
 
 	clientConfig := GetClientConfig()
 	clientConf = &clientConfig
@@ -56,7 +56,7 @@ func init() {
 		}
 	}()
 
-	if consumerConfig.ApplicationConfig == nil {
+	if rootConfig.Application == nil {
 		return
 	}
 	protocolConf := config.GetConsumerConfig().ProtocolConf
diff --git a/protocol/grpc/grpc_protocol_test.go b/protocol/grpc/grpc_protocol_test.go
... 772 lines suppressed ...