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 07:44:51 UTC

[dubbo-go] branch config-enhance created (now 1ecc7eb)

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

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


      at 1ecc7eb  Config refactor (#1358)

This branch includes the following new commits:

     new 1ecc7eb  Config refactor (#1358)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[dubbo-go] 01/01: Config refactor (#1358)

Posted by la...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

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
index 0570e47..d5ac9ff 100644
--- a/protocol/grpc/grpc_protocol_test.go
+++ b/protocol/grpc/grpc_protocol_test.go
@@ -18,6 +18,7 @@
... 768 lines suppressed ...