diff --git a/config/base_config.go b/config/base_config.go
index f58138d2e58a1b3da06894d3afa4728ea2ecf8fb..de0f9e7f8e9b7e8e01cab00a86d80ee3f6840cea 100644
--- a/config/base_config.go
+++ b/config/base_config.go
@@ -42,7 +42,11 @@ type multiConfiger interface {
 
 // BaseConfig is the common configuration for provider and consumer
 type BaseConfig struct {
-	ConfigCenterConfig  *ConfigCenterConfig `yaml:"config_center" json:"config_center,omitempty"`
+	ConfigCenterConfig *ConfigCenterConfig      `yaml:"config_center" json:"config_center,omitempty"`
+	Remotes            map[string]*RemoteConfig `yaml:"remotes" json:"remotes,omitempty"`
+	// application
+	ApplicationConfig *ApplicationConfig `yaml:"application" json:"application,omitempty" property:"application"`
+
 	configCenterUrl     *common.URL
 	prefix              string
 	fatherConfig        interface{}
@@ -51,6 +55,12 @@ type BaseConfig struct {
 	fileStream          *bytes.Buffer
 }
 
+// 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
+}
+
 // startConfigCenter will start the config center.
 // it will prepare the environment
 func (c *BaseConfig) startConfigCenter() error {
@@ -63,7 +73,7 @@ func (c *BaseConfig) startConfigCenter() error {
 	if c.prepareEnvironment() != nil {
 		return perrors.WithMessagef(err, "start config center error!")
 	}
-	//c.fresh()
+	// c.fresh()
 	return err
 }
 
@@ -101,14 +111,14 @@ func (c *BaseConfig) prepareEnvironment() error {
 			return perrors.WithStack(err)
 		}
 	}
-	//global config file
+	// global config file
 	mapContent, err := dynamicConfig.Parser().Parse(content)
 	if err != nil {
 		return perrors.WithStack(err)
 	}
 	config.GetEnvInstance().UpdateExternalConfigMap(mapContent)
 
-	//appGroup config file
+	// appGroup config file
 	if len(appContent) != 0 {
 		appMapConent, err := dynamicConfig.Parser().Parse(appContent)
 		if err != nil {
@@ -264,7 +274,7 @@ func setFieldValue(val reflect.Value, id reflect.Value, config *config.InmemoryC
 				if f.Kind() == reflect.Map {
 
 					if f.Type().Elem().Kind() == reflect.Ptr {
-						//initiate config
+						// initiate config
 						s := reflect.New(f.Type().Elem().Elem())
 						prefix := s.MethodByName("Prefix").Call(nil)[0].String()
 						for _, pfx := range strings.Split(prefix, "|") {
@@ -279,7 +289,7 @@ func setFieldValue(val reflect.Value, id reflect.Value, config *config.InmemoryC
 
 					}
 
-					//iter := f.MapRange()
+					// iter := f.MapRange()
 
 					for _, k := range f.MapKeys() {
 						v := f.MapIndex(k)
@@ -314,7 +324,7 @@ func (c *BaseConfig) fresh() {
 }
 
 func (c *BaseConfig) freshInternalConfig(config *config.InmemoryConfiguration) {
-	//reflect to init struct
+	// reflect to init struct
 	tp := reflect.ValueOf(c.fatherConfig).Elem().Type()
 	initializeStruct(tp, reflect.ValueOf(c.fatherConfig).Elem())
 
diff --git a/config/base_config_test.go b/config/base_config_test.go
index 60eccfb1836dccbec0e8dc593a0954005117c28e..9c4b4f903dc7dac6aca60fd6ceb1eb1af0fd6c69 100644
--- a/config/base_config_test.go
+++ b/config/base_config_test.go
@@ -45,13 +45,15 @@ func Test_refresh(t *testing.T) {
 
 	father := &ConsumerConfig{
 		Check: &[]bool{true}[0],
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		BaseConfig: BaseConfig{
+			ApplicationConfig: &ApplicationConfig{
+				Organization: "dubbo_org",
+				Name:         "dubbo",
+				Module:       "module",
+				Version:      "2.6.0",
+				Owner:        "dubbo",
+				Environment:  "test"},
+		},
 		Registries: map[string]*RegistryConfig{
 			"shanghai_reg2": {
 				Protocol:   "mock",
@@ -139,13 +141,15 @@ func Test_appExternal_refresh(t *testing.T) {
 	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
 	father := &ConsumerConfig{
 		Check: &[]bool{true}[0],
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		BaseConfig: BaseConfig{
+			ApplicationConfig: &ApplicationConfig{
+				Organization: "dubbo_org",
+				Name:         "dubbo",
+				Module:       "module",
+				Version:      "2.6.0",
+				Owner:        "dubbo",
+				Environment:  "test"},
+		},
 		Registries: map[string]*RegistryConfig{
 			"shanghai_reg2": {
 				Protocol:   "mock",
@@ -225,13 +229,15 @@ func Test_appExternalWithoutId_refresh(t *testing.T) {
 	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
 	father := &ConsumerConfig{
 		Check: &[]bool{true}[0],
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		BaseConfig: BaseConfig{
+			ApplicationConfig: &ApplicationConfig{
+				Organization: "dubbo_org",
+				Name:         "dubbo",
+				Module:       "module",
+				Version:      "2.6.0",
+				Owner:        "dubbo",
+				Environment:  "test"},
+		},
 		Registries: map[string]*RegistryConfig{
 			"shanghai_reg2": {
 				Protocol:   "mock",
@@ -310,13 +316,15 @@ func Test_refresh_singleRegistry(t *testing.T) {
 
 	father := &ConsumerConfig{
 		Check: &[]bool{true}[0],
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		BaseConfig: BaseConfig{
+			ApplicationConfig: &ApplicationConfig{
+				Organization: "dubbo_org",
+				Name:         "dubbo",
+				Module:       "module",
+				Version:      "2.6.0",
+				Owner:        "dubbo",
+				Environment:  "test"},
+		},
 		Registries: map[string]*RegistryConfig{},
 		Registry:   &RegistryConfig{},
 		References: map[string]*ReferenceConfig{
@@ -373,13 +381,15 @@ func Test_refreshProvider(t *testing.T) {
 	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
 
 	father := &ProviderConfig{
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		BaseConfig: BaseConfig{
+			ApplicationConfig: &ApplicationConfig{
+				Organization: "dubbo_org",
+				Name:         "dubbo",
+				Module:       "module",
+				Version:      "2.6.0",
+				Owner:        "dubbo",
+				Environment:  "test"},
+		},
 		Registries: map[string]*RegistryConfig{
 			"shanghai_reg2": {
 				Protocol:   "mock",
diff --git a/config/config_loader.go b/config/config_loader.go
index 1ed43ededdf9c8bfeb30c0c8f62b8c9a414246e6..8552caef89bc33210d29e2cfea0cc3715883d83d 100644
--- a/config/config_loader.go
+++ b/config/config_loader.go
@@ -21,6 +21,7 @@ import (
 	"fmt"
 	"log"
 	"os"
+	"sync"
 	"time"
 )
 
@@ -37,12 +38,19 @@ import (
 )
 
 var (
-	consumerConfig    *ConsumerConfig
-	providerConfig    *ProviderConfig
-	metricConfig      *MetricConfig
-	applicationConfig *ApplicationConfig
-	maxWait           = 3
-	confRouterFile    string
+	consumerConfig *ConsumerConfig
+	providerConfig *ProviderConfig
+	// baseConfig = providerConfig.BaseConfig or consumerConfig
+	baseConfig *BaseConfig
+	// baseConfigOnce is used to make sure that we only create it once.
+	baseConfigOnce sync.Once
+
+	// configAccessMutex is used to make sure that BaseConfig.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
 )
 
 // loaded consumer & provider config from xxx.yml, and log config from xxx.xml
@@ -100,12 +108,6 @@ func loadConsumerConfig() {
 		}
 	}
 
-	metricConfig = consumerConfig.MetricConfig
-	applicationConfig = consumerConfig.ApplicationConfig
-	extension.SetAndInitGlobalDispatcher(consumerConfig.eventDispatcherType)
-
-	extension.SetAndInitGlobalDispatcher(consumerConfig.eventDispatcherType)
-
 	checkApplicationName(consumerConfig.ApplicationConfig)
 	if err := configCenterRefreshConsumer(); err != nil {
 		logger.Errorf("[consumer config center refresh] %#v", err)
@@ -126,14 +128,14 @@ func loadConsumerConfig() {
 		ref.Implement(rpcService)
 	}
 
-	//wait for invoker is available, if wait over default 3s, then panic
+	// wait for invoker is available, if wait over default 3s, then panic
 	var count int
 	checkok := true
 	for {
 		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
+				(refconfig.Check == nil && consumerConfig.Check == nil) { // default to true
 
 				if refconfig.invoker != nil &&
 					!refconfig.invoker.IsAvailable() {
@@ -178,13 +180,6 @@ func loadProviderConfig() {
 		}
 	}
 
-	// so, you should know that the consumer's config will be override
-	metricConfig = providerConfig.MetricConfig
-	applicationConfig = providerConfig.ApplicationConfig
-	extension.SetAndInitGlobalDispatcher(providerConfig.eventDispatcherType)
-
-	extension.SetAndInitGlobalDispatcher(consumerConfig.eventDispatcherType)
-
 	checkApplicationName(providerConfig.ApplicationConfig)
 	if err := configCenterRefreshProvider(); err != nil {
 		logger.Errorf("[provider config center refresh] %#v", err)
@@ -225,6 +220,9 @@ func Load() {
 	// service config
 	loadProviderConfig()
 
+	// common part
+	extension.SetAndInitGlobalDispatcher(providerConfig.eventDispatcherType)
+
 	// init the shutdown callback
 	GracefulShutdownInit()
 }
@@ -241,39 +239,83 @@ func RPCService(service common.RPCService) {
 
 // GetMetricConfig find the MetricConfig
 // if it is nil, create a 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 GetMetricConfig() *MetricConfig {
-	if metricConfig == nil {
-		metricConfig = &MetricConfig{}
+	if GetBaseConfig().MetricConfig == nil {
+		configAccessMutex.Lock()
+		defer configAccessMutex.Unlock()
+		if GetBaseConfig().MetricConfig == nil {
+			GetBaseConfig().MetricConfig = &MetricConfig{}
+		}
 	}
-	return metricConfig
+	return GetBaseConfig().MetricConfig
 }
 
 // GetApplicationConfig find the application 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 applicationConfig == nil {
-		applicationConfig = &ApplicationConfig{}
+	if GetBaseConfig().ApplicationConfig == nil {
+		configAccessMutex.Lock()
+		defer configAccessMutex.Unlock()
+		if GetBaseConfig().ApplicationConfig == nil {
+			GetBaseConfig().ApplicationConfig = &ApplicationConfig{}
+		}
 	}
-	return applicationConfig
+	return GetBaseConfig().ApplicationConfig
 }
 
 // GetProviderConfig find the provider 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 GetProviderConfig() ProviderConfig {
 	if providerConfig == nil {
-		logger.Warnf("providerConfig is nil!")
-		return ProviderConfig{}
+		logger.Warnf("providerConfig is nil! we will try to create one")
+		configAccessMutex.Lock()
+		defer configAccessMutex.Unlock()
+		if providerConfig == nil {
+			logger.Warnf("creating empty provider config. You should see this log only once.")
+			providerConfig = &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 {
-		logger.Warnf("consumerConfig is nil!")
-		return ConsumerConfig{}
+		logger.Warnf("consumerConfig is nil! we will try to create one")
+		configAccessMutex.Lock()
+		defer configAccessMutex.Unlock()
+		if consumerConfig == nil {
+			logger.Warnf("creating empty consumer config. You should see this log only once.")
+			consumerConfig = &ConsumerConfig{}
+		}
 	}
 	return *consumerConfig
 }
+
+func GetBaseConfig() *BaseConfig {
+	if baseConfig == nil {
+		baseConfigOnce.Do(func() {
+			baseConfig = &BaseConfig{
+				MetricConfig:       &MetricConfig{},
+				ConfigCenterConfig: &ConfigCenterConfig{},
+				Remotes:            make(map[string]*RemoteConfig, 0),
+				ApplicationConfig:  &ApplicationConfig{},
+			}
+		})
+	}
+	return baseConfig
+}
diff --git a/config/config_loader_test.go b/config/config_loader_test.go
index 0192b4c8a06263266cb80b344a0792ea2f6af8c8..f653f5e7598756514fd1e50dd2077329cbb3c9c0 100644
--- a/config/config_loader_test.go
+++ b/config/config_loader_test.go
@@ -235,16 +235,25 @@ func TestConfigLoaderWithConfigCenterSingleRegistry(t *testing.T) {
 
 }
 
+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{
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "1.0.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		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",
diff --git a/config/consumer_config.go b/config/consumer_config.go
index debcd79fa281c40e5526f60f5c5cdb66688688f4..76476511fbf74a5e973d59e560f65cab978d4527 100644
--- a/config/consumer_config.go
+++ b/config/consumer_config.go
@@ -42,9 +42,6 @@ import (
 type ConsumerConfig struct {
 	BaseConfig `yaml:",inline"`
 	Filter     string `yaml:"filter" json:"filter,omitempty" property:"filter"`
-	// application
-	ApplicationConfig *ApplicationConfig `yaml:"application" json:"application,omitempty" property:"application"`
-
 	// client
 	Connect_Timeout string `default:"100ms"  yaml:"connect_timeout" json:"connect_timeout,omitempty" property:"connect_timeout"`
 	ConnectTimeout  time.Duration
diff --git a/config/provider_config.go b/config/provider_config.go
index 79569917455773653750d1d5921a722daf079b0a..bdb9bd2f96eecfc0e9d3fc0e1f72ad95879e264a 100644
--- a/config/provider_config.go
+++ b/config/provider_config.go
@@ -43,8 +43,6 @@ type ProviderConfig struct {
 	ProxyFactory string `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty" property:"proxy_factory"`
 	// metadata-report
 	MetadataReportConfig *MetadataReportConfig `yaml:"metadata_report" json:"metadata_report,omitempty" property:"metadata_report"`
-
-	ApplicationConfig *ApplicationConfig         `yaml:"application" json:"application,omitempty" property:"application"`
 	Registry          *RegistryConfig            `yaml:"registry" json:"registry,omitempty" property:"registry"`
 	Registries        map[string]*RegistryConfig `yaml:"registries" json:"registries,omitempty" property:"registries"`
 	Services          map[string]*ServiceConfig  `yaml:"services" json:"services,omitempty" property:"services"`
diff --git a/config/reference_config_test.go b/config/reference_config_test.go
index 7a65e55f09c997cb49b83f1f185faf9338cf0f5a..faaa461a75a5c887f6fa1cc568d7e809c42a6ac4 100644
--- a/config/reference_config_test.go
+++ b/config/reference_config_test.go
@@ -38,13 +38,15 @@ var regProtocol protocol.Protocol
 
 func doInitConsumer() {
 	consumerConfig = &ConsumerConfig{
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		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",
@@ -135,13 +137,15 @@ func doInitConsumerAsync() {
 
 func doInitConsumerWithSingleRegistry() {
 	consumerConfig = &ConsumerConfig{
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		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",
diff --git a/config/remote_config.go b/config/remote_config.go
new file mode 100644
index 0000000000000000000000000000000000000000..f126afc90f1147ab323460104b53308e30a0d1df
--- /dev/null
+++ b/config/remote_config.go
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package config
+
+type RemoteConfig struct {
+	Address string `yaml:"address" json:"address,omitempty"`
+	Params map[string]string `yaml:"params" json:"address,omitempty"`
+}
+
+
diff --git a/config/service_config_test.go b/config/service_config_test.go
index 387e3ced7ad00d9d2240ca5833a36994f707720d..eff9735b3de2c4bae340cecf8ec601b57bf3b303 100644
--- a/config/service_config_test.go
+++ b/config/service_config_test.go
@@ -33,13 +33,15 @@ import (
 
 func doInitProvider() {
 	providerConfig = &ProviderConfig{
-		ApplicationConfig: &ApplicationConfig{
-			Organization: "dubbo_org",
-			Name:         "dubbo",
-			Module:       "module",
-			Version:      "2.6.0",
-			Owner:        "dubbo",
-			Environment:  "test"},
+		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",
diff --git a/registry/nacos/registry.go b/registry/nacos/registry.go
index a436b85064829b9f42c9dcc45545e5bf2fd2fefe..a8d4916c6ebf990dc951963f05fe80ee2320add2 100644
--- a/registry/nacos/registry.go
+++ b/registry/nacos/registry.go
@@ -140,7 +140,7 @@ func (nr *nacosRegistry) subscribe(conf *common.URL) (registry.Listener, error)
 	return NewNacosListener(*conf, nr.namingClient)
 }
 
-//subscribe from registry
+// subscribe from registry
 func (nr *nacosRegistry) Subscribe(url *common.URL, notifyListener registry.NotifyListener) {
 	for {
 		if !nr.IsAvailable() {
@@ -179,6 +179,7 @@ func (nr *nacosRegistry) GetUrl() common.URL {
 }
 
 func (nr *nacosRegistry) IsAvailable() bool {
+	// TODO
 	return true
 }