diff --git a/common/constant/key.go b/common/constant/key.go
index 5769ccfe6c8d2e296de190259d85821dd92dd8f4..27b77879b35b2d85c572853949cb26f40a2325ca 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -215,6 +215,9 @@ const (
 	KEY_SEPARATOR      = ":"
 	DEFAULT_PATH_TAG   = "metadata"
 	KEY_REVISON_PREFIX = "revision"
+
+	// metadata service
+	METADATA_SERVICE_NAME = "org.apache.dubbo.metadata.MetadataService"
 )
 
 // HealthCheck Router
diff --git a/config_center/apollo/impl.go b/config_center/apollo/impl.go
index bc8538f2e745874f357d6444704cb7e9c3711ef5..9045c2864933fcfc79d5be32d160324805605595 100644
--- a/config_center/apollo/impl.go
+++ b/config_center/apollo/impl.go
@@ -25,6 +25,7 @@ import (
 )
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
 	perrors "github.com/pkg/errors"
 	"github.com/zouyx/agollo"
 )
@@ -133,6 +134,11 @@ func (c *apolloConfiguration) PublishConfig(string, string, string) error {
 	return perrors.New("unsupport operation")
 }
 
+// GetConfigKeysByGroup will return all keys with the group
+func (c *apolloConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
+	return nil, perrors.New("unsupport operation")
+}
+
 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:
diff --git a/config_center/dynamic_configuration.go b/config_center/dynamic_configuration.go
index e643e011fb0dfabef163153745b71afba31d5a7c..9013d7140e757520f2e8f048ce53a5ac2a13f982 100644
--- a/config_center/dynamic_configuration.go
+++ b/config_center/dynamic_configuration.go
@@ -21,14 +21,18 @@ import (
 	"time"
 )
 
+import (
+	gxset "github.com/dubbogo/gost/container/set"
+)
+
 import (
 	"github.com/apache/dubbo-go/common"
 	"github.com/apache/dubbo-go/config_center/parser"
 )
 
-//////////////////////////////////////////
+// ////////////////////////////////////////
 // DynamicConfiguration
-//////////////////////////////////////////
+// ////////////////////////////////////////
 const (
 	// DEFAULT_GROUP: default group
 	DEFAULT_GROUP = "dubbo"
@@ -42,17 +46,20 @@ type DynamicConfiguration interface {
 	SetParser(parser.ConfigurationParser)
 	AddListener(string, ConfigurationListener, ...Option)
 	RemoveListener(string, ConfigurationListener, ...Option)
-	//GetProperties get properties file
+	// GetProperties get properties file
 	GetProperties(string, ...Option) (string, error)
 
-	//GetRule get Router rule properties file
+	// GetRule get Router rule properties file
 	GetRule(string, ...Option) (string, error)
 
-	//GetInternalProperty get value by key in Default properties file(dubbo.properties)
+	// GetInternalProperty get value by key in Default properties file(dubbo.properties)
 	GetInternalProperty(string, ...Option) (string, error)
 
 	// PublishConfig will publish the config with the (key, group, value) pair
 	PublishConfig(string, string, string) error
+
+	// GetConfigKeysByGroup will return all keys with the group
+	GetConfigKeysByGroup(group string) (*gxset.HashSet, error)
 }
 
 // Options ...
@@ -78,7 +85,7 @@ func WithTimeout(time time.Duration) Option {
 	}
 }
 
-//GetRuleKey The format is '{interfaceName}:[version]:[group]'
+// GetRuleKey The format is '{interfaceName}:[version]:[group]'
 func GetRuleKey(url common.URL) string {
 	return url.ColonSeparatedKey()
 }
diff --git a/config_center/mock_dynamic_config.go b/config_center/mock_dynamic_config.go
index 9f5bbe934c2a7c2a8a30ba42d024cacedc92d084..59c788b65bce2a4773975ea1a96a314649781832 100644
--- a/config_center/mock_dynamic_config.go
+++ b/config_center/mock_dynamic_config.go
@@ -22,6 +22,7 @@ import (
 )
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
 	"gopkg.in/yaml.v2"
 )
 
@@ -81,10 +82,16 @@ func (f *MockDynamicConfigurationFactory) GetDynamicConfiguration(_ *common.URL)
 
 }
 
+// PublishConfig will publish the config with the (key, group, value) pair
 func (c *MockDynamicConfiguration) PublishConfig(string, string, string) error {
 	return nil
 }
 
+// GetConfigKeysByGroup will return all keys with the group
+func (c *MockDynamicConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
+	return gxset.NewSet(c.content), nil
+}
+
 // MockDynamicConfiguration ...
 type MockDynamicConfiguration struct {
 	parser   parser.ConfigurationParser
diff --git a/config_center/nacos/impl.go b/config_center/nacos/impl.go
index 54523cae711ec59f97577f6ea4ab501e17884743..007b8be142274b63ceb56dd00399cdaf29c3746d 100644
--- a/config_center/nacos/impl.go
+++ b/config_center/nacos/impl.go
@@ -23,6 +23,7 @@ import (
 )
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
 	"github.com/nacos-group/nacos-sdk-go/vo"
 	perrors "github.com/pkg/errors"
 )
@@ -105,6 +106,13 @@ func (n *nacosDynamicConfiguration) PublishConfig(key string, group string, valu
 	return nil
 }
 
+// GetConfigKeysByGroup will return all keys with the group
+func (n *nacosDynamicConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
+	// TODO (the golang client of nacos does not support batch API)
+	// we should build a issue and then think about how to resolve this problem
+	return nil, perrors.New("unsupport operation, wait for implement")
+}
+
 // GetRule Get router rule
 func (n *nacosDynamicConfiguration) GetRule(key string, opts ...config_center.Option) (string, error) {
 	tmpOpts := &config_center.Options{}
diff --git a/config_center/zookeeper/impl.go b/config_center/zookeeper/impl.go
index fc87eaee5faac8a510bf19f072a53baebeb377a4..937c56eef0b29f6fee52717f7a43c37ec35c7e95 100644
--- a/config_center/zookeeper/impl.go
+++ b/config_center/zookeeper/impl.go
@@ -25,6 +25,7 @@ import (
 
 import (
 	"github.com/dubbogo/go-zookeeper/zk"
+	gxset "github.com/dubbogo/gost/container/set"
 	perrors "github.com/pkg/errors"
 )
 
@@ -39,7 +40,7 @@ import (
 
 const (
 	// ZkClient
-	//zookeeper client name
+	// zookeeper client name
 	ZkClient      = "zk config_center"
 	pathSeparator = "/"
 )
@@ -159,6 +160,24 @@ func (c *zookeeperDynamicConfiguration) PublishConfig(key string, group string,
 	return nil
 }
 
+// GetConfigKeysByGroup will return all keys with the group
+func (c *zookeeperDynamicConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
+	path := c.getPath("", group)
+	result, err := c.client.GetChildren(path)
+	if err != nil {
+		return nil, perrors.WithStack(err)
+	}
+
+	if len(result) == 0 {
+		return nil, perrors.New("could not find keys with group: " + group)
+	}
+	set := gxset.NewSet()
+	for _, e := range result {
+		set.Add(e)
+	}
+	return set, nil
+}
+
 func (c *zookeeperDynamicConfiguration) GetRule(key string, opts ...config_center.Option) (string, error) {
 	return c.GetProperties(key, opts...)
 }
@@ -234,7 +253,7 @@ func (c *zookeeperDynamicConfiguration) getPath(key string, group string) string
 }
 
 func (c *zookeeperDynamicConfiguration) buildPath(group string) string {
-	if len(group) <= 0 {
+	if len(group) == 0 {
 		group = config_center.DEFAULT_GROUP
 	}
 	return c.rootPath + pathSeparator + group
diff --git a/config_center/zookeeper/impl_test.go b/config_center/zookeeper/impl_test.go
index e6349d4c3de4614aef4ebdefcb76f773d9418eb2..30389122a3a06ee260f2ed8b21057523137995d5 100644
--- a/config_center/zookeeper/impl_test.go
+++ b/config_center/zookeeper/impl_test.go
@@ -24,6 +24,7 @@ import (
 
 import (
 	"github.com/dubbogo/go-zookeeper/zk"
+	gxset "github.com/dubbogo/gost/container/set"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -159,13 +160,21 @@ func Test_RemoveListener(t *testing.T) {
 func TestZookeeperDynamicConfiguration_PublishConfig(t *testing.T) {
 	value := "Test Data"
 	customGroup := "Custom Group"
+	key := "myKey"
 	ts, zk := initZkData(config_center.DEFAULT_GROUP, t)
 	defer ts.Stop()
-	err := zk.PublishConfig("myKey", customGroup, value)
+	err := zk.PublishConfig(key, customGroup, value)
 	assert.Nil(t, err)
 	result, err := zk.GetInternalProperty("myKey", config_center.WithGroup(customGroup))
 	assert.Nil(t, err)
 	assert.Equal(t, value, result)
+
+	var keys *gxset.HashSet
+	keys, err = zk.GetConfigKeysByGroup(customGroup)
+	assert.Nil(t, err)
+	assert.Equal(t, 1, keys.Size())
+	assert.True(t, keys.Contains(key))
+
 }
 
 type mockDataListener struct {
diff --git a/metadata/namemapping/dynamic/service_name_mapping.go b/metadata/namemapping/dynamic/service_name_mapping.go
new file mode 100644
index 0000000000000000000000000000000000000000..e93c256fe093b4a3e3c431e1d012038b2bb7976b
--- /dev/null
+++ b/metadata/namemapping/dynamic/service_name_mapping.go
@@ -0,0 +1,82 @@
+/*
+ * 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 dynamic
+
+import (
+	"strconv"
+	"time"
+)
+
+import (
+	"github.com/dubbogo/gost/container/set"
+	perrors "github.com/pkg/errors"
+)
+
+import (
+	"github.com/apache/dubbo-go/common/constant"
+	"github.com/apache/dubbo-go/config"
+	"github.com/apache/dubbo-go/config_center"
+	"github.com/apache/dubbo-go/metadata"
+)
+
+const (
+	defaultGroup = config_center.DEFAULT_GROUP
+	slash        = "/"
+)
+
+// DynamicConfigurationServiceNameMapping is the implementation based on config center
+type DynamicConfigurationServiceNameMapping struct {
+	dc config_center.DynamicConfiguration
+}
+
+// Map will map the service to this application-level service
+func (d *DynamicConfigurationServiceNameMapping) Map(serviceInterface string, group string, version string, protocol string) error {
+	// metadata service is admin service, should not be mapped
+	if constant.METADATA_SERVICE_NAME == serviceInterface {
+		return perrors.New("try to map the metadata service, will be ignored")
+	}
+
+	appName := config.GetApplicationConfig().Name
+	value := time.Now().UnixNano()
+
+	err := d.dc.PublishConfig(appName,
+		d.buildGroup(serviceInterface),
+		strconv.FormatInt(value, 10))
+	if err != nil {
+		return perrors.WithStack(err)
+	}
+	return nil
+}
+
+// Get will return the application-level services. If not found, the empty set will be returned.
+// if the dynamic configuration got error, the error will return
+func (d *DynamicConfigurationServiceNameMapping) Get(serviceInterface string, group string, version string, protocol string) (*gxset.HashSet, error) {
+	return d.dc.GetConfigKeysByGroup(d.buildGroup(serviceInterface))
+}
+
+// buildGroup will return group, now it looks like defaultGroup/serviceInterface
+func (d *DynamicConfigurationServiceNameMapping) buildGroup(serviceInterface string) string {
+	// the issue : https://github.com/apache/dubbo/issues/4671
+	// so other params are ignored and remove, including group string, version string, protocol string
+	return defaultGroup + slash + serviceInterface
+}
+
+// NewServiceNameMapping will create an instance of DynamicConfigurationServiceNameMapping
+func NewServiceNameMapping(dc config_center.DynamicConfiguration) metadata.ServiceNameMapping {
+	return &DynamicConfigurationServiceNameMapping{dc: dc}
+}
diff --git a/metadata/namemapping/dynamic/service_name_mapping_test.go b/metadata/namemapping/dynamic/service_name_mapping_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..e3d620cd738421c256d8fd232b1afcfd425ca989
--- /dev/null
+++ b/metadata/namemapping/dynamic/service_name_mapping_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 dynamic
+
+import (
+	"testing"
+)
+
+import (
+	gxset "github.com/dubbogo/gost/container/set"
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"github.com/apache/dubbo-go/common/constant"
+	"github.com/apache/dubbo-go/config"
+	"github.com/apache/dubbo-go/config_center"
+)
+
+func TestDynamicConfigurationServiceNameMapping(t *testing.T) {
+
+	// mock data
+	appName := "myApp"
+	dc, err := (&config_center.MockDynamicConfigurationFactory{
+		Content: appName,
+	}).GetDynamicConfiguration(nil)
+	config.GetApplicationConfig().Name = appName
+
+	mapping := NewServiceNameMapping(dc)
+	intf := constant.METADATA_SERVICE_NAME
+	group := "myGroup"
+	version := "myVersion"
+	protocol := "myProtocol"
+
+	err = mapping.Map(intf, group, version, protocol)
+	assert.NotNil(t, err)
+	intf = "MyService"
+	err = mapping.Map(intf, group, version, protocol)
+	assert.Nil(t, err)
+
+	var result *gxset.HashSet
+	result, err = mapping.Get(intf, group, version, protocol)
+	assert.Nil(t, err)
+	assert.Equal(t, 1, result.Size())
+	assert.True(t, result.Contains(appName))
+}
diff --git a/metadata/namemapping/memory/service_name_mapping.go b/metadata/namemapping/memory/service_name_mapping.go
new file mode 100644
index 0000000000000000000000000000000000000000..8a891491bdb97808b77422092a1043c1c0ffafbf
--- /dev/null
+++ b/metadata/namemapping/memory/service_name_mapping.go
@@ -0,0 +1,36 @@
+/*
+ * 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 memory
+
+import (
+	gxset "github.com/dubbogo/gost/container/set"
+)
+
+import (
+	"github.com/apache/dubbo-go/config"
+)
+
+type InMemoryServiceNameMapping struct{}
+
+func (i InMemoryServiceNameMapping) Map(serviceInterface string, group string, version string, protocol string) error {
+	return nil
+}
+
+func (i InMemoryServiceNameMapping) Get(serviceInterface string, group string, version string, protocol string) (*gxset.HashSet, error) {
+	return gxset.NewSet(config.GetApplicationConfig().Name), nil
+}
diff --git a/metadata/service_name_mapping.go b/metadata/service_name_mapping.go
new file mode 100644
index 0000000000000000000000000000000000000000..c14e8ce2e7c40d1573897dfd6ba64c16e18acac7
--- /dev/null
+++ b/metadata/service_name_mapping.go
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package metadata
+
+import (
+	gxset "github.com/dubbogo/gost/container/set"
+)
+
+// ServiceNameMapping try to build the mapping between application-level service and interface-level service.
+type ServiceNameMapping interface {
+
+	// Map will map the service to this application-level service
+	Map(serviceInterface string, group string, version string, protocol string) error
+
+	// Get will return the application-level services
+	Get(serviceInterface string, group string, version string, protocol string) (*gxset.HashSet, error)
+}