You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/09/24 05:19:51 UTC

[dubbo-go] branch config-enhance updated: Fix the name mapping incompatibility (#1465)

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

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


The following commit(s) were added to refs/heads/config-enhance by this push:
     new ecd6529  Fix the name mapping incompatibility (#1465)
ecd6529 is described below

commit ecd652963ea8163b43a923acba4ef71c7b2d185b
Author: alchemy-lee <27...@qq.com>
AuthorDate: Fri Sep 24 13:19:45 2021 +0800

    Fix the name mapping incompatibility (#1465)
    
    * fix metadata bug
    
    * fix metadata bug
    
    * fix metadata bug
    
    * fix name mapping bug for zk
    
    * modify comment
    
    * fix path incompatible
    
    * fix ci failure
    
    * fix ci failure
    
    * fix ci failure
    
    * fix name mapping bug for nacos
    
    * feat: etcd fit service name mapping uncoupling
    
    * fix name mapping bug for etcd
    
    * fix ci failure
    
    Co-authored-by: MasterKenway <zk...@ikenway.net>
---
 common/constant/key.go                             |  1 +
 common/metadata_info.go                            |  2 +-
 config/instance/metadata_report_test.go            | 13 ++++-
 imports/imports.go                                 |  2 +-
 .../mapping/dynamic/service_name_mapping_test.go   | 62 ----------------------
 metadata/mapping/memory/service_name_mapping.go    |  5 +-
 .../{dynamic => metadata}/service_name_mapping.go  | 42 +++++++--------
 metadata/mapping/mock_service_name_mapping.go      |  8 ++-
 metadata/mapping/service_name_mapping.go           |  8 ++-
 metadata/report/etcd/report.go                     | 33 ++++++++++++
 metadata/report/etcd/report_test.go                | 30 +++++++++++
 metadata/report/nacos/report.go                    | 45 ++++++++++++++++
 metadata/report/report.go                          | 10 ++++
 metadata/report/zookeeper/report.go                | 35 +++++++++++-
 metadata/service/exporter/configurable/exporter.go |  2 +-
 metadata/service/remote/service_test.go            | 13 ++++-
 ... => event_publishing_service_discovery_test.go} |  0
 registry/event/service_name_mapping_listener.go    | 10 ++--
 .../servicediscovery/service_discovery_registry.go | 14 ++---
 19 files changed, 217 insertions(+), 118 deletions(-)

diff --git a/common/constant/key.go b/common/constant/key.go
index 5a5f9d6..80d2fe7 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -49,6 +49,7 @@ const (
 	PORT_KEY                 = "port"
 	PROTOCOL_KEY             = "protocol"
 	PATH_SEPARATOR           = "/"
+	COMMA_SEPARATOR          = ","
 	// DUBBO_KEY                = "dubbo"
 	SSL_ENABLED_KEY = "ssl-enabled"
 	// PARAMS_TYPE_Key key used in pass through invoker factory, to define param type
diff --git a/common/metadata_info.go b/common/metadata_info.go
index e64e72a..9c43f69 100644
--- a/common/metadata_info.go
+++ b/common/metadata_info.go
@@ -187,7 +187,7 @@ func NewServiceInfo(name, group, version, protocol, path string, params map[stri
 		Group:      group,
 		Version:    version,
 		Protocol:   protocol,
-		Path:       path,
+		Path:       strings.TrimPrefix(path, "/"),
 		Params:     params,
 		ServiceKey: serviceKey,
 		MatchKey:   matchKey,
diff --git a/config/instance/metadata_report_test.go b/config/instance/metadata_report_test.go
index d665f61..e57f75c 100644
--- a/config/instance/metadata_report_test.go
+++ b/config/instance/metadata_report_test.go
@@ -22,6 +22,7 @@ import (
 )
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -50,11 +51,19 @@ func (m *mockMetadataReportFactory) CreateMetadataReport(*common.URL) report.Met
 
 type mockMetadataReport struct{}
 
-func (m mockMetadataReport) GetAppMetadata(metadataIdentifier *identifier.SubscriberMetadataIdentifier) (*common.MetadataInfo, error) {
+func (m mockMetadataReport) RegisterServiceAppMapping(string, string, string) error {
 	panic("implement me")
 }
 
-func (m mockMetadataReport) PublishAppMetadata(metadataIdentifier *identifier.SubscriberMetadataIdentifier, info *common.MetadataInfo) error {
+func (m mockMetadataReport) GetServiceAppMapping(string, string) (*gxset.HashSet, error) {
+	panic("implement me")
+}
+
+func (m mockMetadataReport) GetAppMetadata(*identifier.SubscriberMetadataIdentifier) (*common.MetadataInfo, error) {
+	panic("implement me")
+}
+
+func (m mockMetadataReport) PublishAppMetadata(*identifier.SubscriberMetadataIdentifier, *common.MetadataInfo) error {
 	panic("implement me")
 }
 
diff --git a/imports/imports.go b/imports/imports.go
index cd346e4..60f238e 100644
--- a/imports/imports.go
+++ b/imports/imports.go
@@ -25,7 +25,7 @@ import (
 	_ "dubbo.apache.org/dubbo-go/v3/config_center/nacos"
 	_ "dubbo.apache.org/dubbo-go/v3/config_center/zookeeper"
 	_ "dubbo.apache.org/dubbo-go/v3/filter/filter_impl"
-	_ "dubbo.apache.org/dubbo-go/v3/metadata/mapping/dynamic"
+	_ "dubbo.apache.org/dubbo-go/v3/metadata/mapping/metadata"
 	_ "dubbo.apache.org/dubbo-go/v3/metadata/report/etcd"
 	_ "dubbo.apache.org/dubbo-go/v3/metadata/report/nacos"
 	_ "dubbo.apache.org/dubbo-go/v3/metadata/report/zookeeper"
diff --git a/metadata/mapping/dynamic/service_name_mapping_test.go b/metadata/mapping/dynamic/service_name_mapping_test.go
deleted file mode 100644
index 5124b30..0000000
--- a/metadata/mapping/dynamic/service_name_mapping_test.go
+++ /dev/null
@@ -1,62 +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 dynamic
-
-import (
-	"testing"
-)
-
-import (
-	gxset "github.com/dubbogo/gost/container/set"
-
-	"github.com/stretchr/testify/assert"
-)
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/config"
-	"dubbo.apache.org/dubbo-go/v3/config_center"
-)
-
-func TestDynamicConfigurationServiceNameMapping(t *testing.T) {
-	// mock data
-	appName := "myApp"
-	dc, err := (&config_center.MockDynamicConfigurationFactory{
-		Content: appName,
-	}).GetDynamicConfiguration(nil)
-	assert.NoError(t, err)
-	config.GetApplicationConfig().Name = appName
-
-	mapping := &DynamicConfigurationServiceNameMapping{dc: dc}
-	intf := constant.METADATA_SERVICE_NAME
-	group := "myGroup"
-	version := "myVersion"
-	protocol := "myProtocol"
-
-	err = mapping.Map(intf, group, version, protocol)
-	assert.Nil(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/mapping/memory/service_name_mapping.go b/metadata/mapping/memory/service_name_mapping.go
index cc10439..73b0603 100644
--- a/metadata/mapping/memory/service_name_mapping.go
+++ b/metadata/mapping/memory/service_name_mapping.go
@@ -26,6 +26,7 @@ import (
 )
 
 import (
+	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/metadata/mapping"
@@ -37,11 +38,11 @@ func init() {
 
 type InMemoryServiceNameMapping struct{}
 
-func (i *InMemoryServiceNameMapping) Map(serviceInterface string, group string, version string, protocol string) error {
+func (i *InMemoryServiceNameMapping) Map(url *common.URL) error {
 	return nil
 }
 
-func (i *InMemoryServiceNameMapping) Get(serviceInterface string, group string, version string, protocol string) (*gxset.HashSet, error) {
+func (i *InMemoryServiceNameMapping) Get(url *common.URL) (*gxset.HashSet, error) {
 	return gxset.NewSet(config.GetApplicationConfig().Name), nil
 }
 
diff --git a/metadata/mapping/dynamic/service_name_mapping.go b/metadata/mapping/metadata/service_name_mapping.go
similarity index 63%
rename from metadata/mapping/dynamic/service_name_mapping.go
rename to metadata/mapping/metadata/service_name_mapping.go
index 7839e07..572dda8 100644
--- a/metadata/mapping/dynamic/service_name_mapping.go
+++ b/metadata/mapping/metadata/service_name_mapping.go
@@ -15,27 +15,24 @@
  * limitations under the License.
  */
 
-package dynamic
+package metadata
 
 import (
-	"strconv"
 	"sync"
-	"time"
 )
 
 import (
-	"github.com/dubbogo/gost/container/set"
-
+	gxset "github.com/dubbogo/gost/container/set"
 	perrors "github.com/pkg/errors"
 )
 
 import (
-	commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
+	"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/config"
-	"dubbo.apache.org/dubbo-go/v3/config_center"
+	"dubbo.apache.org/dubbo-go/v3/config/instance"
 	"dubbo.apache.org/dubbo-go/v3/metadata/mapping"
 )
 
@@ -48,14 +45,14 @@ func init() {
 	extension.SetGlobalServiceNameMapping(GetNameMappingInstance)
 }
 
-// DynamicConfigurationServiceNameMapping is the implementation based on config center
+// MetadataServiceNameMapping is the implementation based on metadata report
 // it's a singleton
-type DynamicConfigurationServiceNameMapping struct {
-	dc config_center.DynamicConfiguration
+type MetadataServiceNameMapping struct {
 }
 
 // Map will map the service to this application-level service
-func (d *DynamicConfigurationServiceNameMapping) Map(serviceInterface string, group string, version string, protocol string) error {
+func (d *MetadataServiceNameMapping) Map(url *common.URL) error {
+	serviceInterface := url.GetParam(constant.INTERFACE_KEY, "")
 	// metadata service is admin service, should not be mapped
 	if constant.METADATA_SERVICE_NAME == serviceInterface {
 		logger.Info("try to map the metadata service, will be ignored")
@@ -63,11 +60,8 @@ func (d *DynamicConfigurationServiceNameMapping) Map(serviceInterface string, gr
 	}
 
 	appName := config.GetApplicationConfig().Name
-	value := time.Now().UnixNano()
-
-	err := d.dc.PublishConfig(appName,
-		d.buildGroup(serviceInterface),
-		strconv.FormatInt(value, 10))
+	metadataReport := instance.GetMetadataReportInstance()
+	err := metadataReport.RegisterServiceAppMapping(serviceInterface, defaultGroup, appName)
 	if err != nil {
 		return perrors.WithStack(err)
 	}
@@ -75,28 +69,28 @@ func (d *DynamicConfigurationServiceNameMapping) Map(serviceInterface string, gr
 }
 
 // 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))
+func (d *MetadataServiceNameMapping) Get(url *common.URL) (*gxset.HashSet, error) {
+	serviceInterface := url.GetParam(constant.INTERFACE_KEY, "")
+	metadataReport := instance.GetMetadataReportInstance()
+	return metadataReport.GetServiceAppMapping(serviceInterface, defaultGroup)
 }
 
-// buildGroup will return group, now it looks like defaultGroup/serviceInterface
-func (d *DynamicConfigurationServiceNameMapping) buildGroup(serviceInterface string) string {
+// buildMappingKey will return mapping key, it looks like defaultGroup/serviceInterface
+func (d *MetadataServiceNameMapping) buildMappingKey(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
 }
 
 var (
-	serviceNameMappingInstance *DynamicConfigurationServiceNameMapping
+	serviceNameMappingInstance *MetadataServiceNameMapping
 	serviceNameMappingOnce     sync.Once
 )
 
 // GetNameMappingInstance return an instance, if not found, it creates one
 func GetNameMappingInstance() mapping.ServiceNameMapping {
 	serviceNameMappingOnce.Do(func() {
-		dc := commonCfg.GetEnvInstance().GetDynamicConfiguration()
-		serviceNameMappingInstance = &DynamicConfigurationServiceNameMapping{dc: dc}
+		serviceNameMappingInstance = &MetadataServiceNameMapping{}
 	})
 	return serviceNameMappingInstance
 }
diff --git a/metadata/mapping/mock_service_name_mapping.go b/metadata/mapping/mock_service_name_mapping.go
index 14ee000..c3aae3d 100644
--- a/metadata/mapping/mock_service_name_mapping.go
+++ b/metadata/mapping/mock_service_name_mapping.go
@@ -21,16 +21,20 @@ import (
 	gxset "github.com/dubbogo/gost/container/set"
 )
 
+import (
+	"dubbo.apache.org/dubbo-go/v3/common"
+)
+
 type MockServiceNameMapping struct{}
 
 func NewMockServiceNameMapping() *MockServiceNameMapping {
 	return &MockServiceNameMapping{}
 }
 
-func (m *MockServiceNameMapping) Map(string, string, string, string) error {
+func (m *MockServiceNameMapping) Map(*common.URL) error {
 	return nil
 }
 
-func (m *MockServiceNameMapping) Get(string, string, string, string) (*gxset.HashSet, error) {
+func (m *MockServiceNameMapping) Get(*common.URL) (*gxset.HashSet, error) {
 	panic("implement me")
 }
diff --git a/metadata/mapping/service_name_mapping.go b/metadata/mapping/service_name_mapping.go
index 6caed9f..75b216f 100644
--- a/metadata/mapping/service_name_mapping.go
+++ b/metadata/mapping/service_name_mapping.go
@@ -21,12 +21,16 @@ import (
 	gxset "github.com/dubbogo/gost/container/set"
 )
 
+import (
+	"dubbo.apache.org/dubbo-go/v3/common"
+)
+
 // 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
+	Map(url *common.URL) error
 
 	// Get will return the application-level services
-	Get(serviceInterface string, group string, version string, protocol string) (*gxset.HashSet, error)
+	Get(url *common.URL) (*gxset.HashSet, error)
 }
diff --git a/metadata/report/etcd/report.go b/metadata/report/etcd/report.go
index 2d83fa3..7741e4b 100644
--- a/metadata/report/etcd/report.go
+++ b/metadata/report/etcd/report.go
@@ -23,7 +23,9 @@ import (
 )
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
 	gxetcd "github.com/dubbogo/gost/database/kv/etcd/v3"
+	perrors "github.com/pkg/errors"
 )
 
 import (
@@ -141,6 +143,37 @@ func (e *etcdMetadataReport) GetServiceDefinition(metadataIdentifier *identifier
 	return content, nil
 }
 
+// RegisterServiceAppMapping map the specified Dubbo service interface to current Dubbo app name
+func (e *etcdMetadataReport) RegisterServiceAppMapping(key string, group string, value string) error {
+	path := e.root + constant.PATH_SEPARATOR + group + constant.PATH_SEPARATOR + key
+	oldVal, err := e.client.Get(path)
+	if perrors.Cause(err) == gxetcd.ErrKVPairNotFound {
+		return e.client.Put(path, value)
+	} else if err != nil {
+		return err
+	}
+	if strings.Contains(oldVal, value) {
+		return nil
+	}
+	value = oldVal + constant.COMMA_SEPARATOR + value
+	return e.client.Put(path, value)
+}
+
+// GetServiceAppMapping get the app names from the specified Dubbo service interface
+func (e *etcdMetadataReport) GetServiceAppMapping(key string, group string) (*gxset.HashSet, error) {
+	path := e.root + constant.PATH_SEPARATOR + group + constant.PATH_SEPARATOR + key
+	v, err := e.client.Get(path)
+	if err != nil {
+		return nil, err
+	}
+	appNames := strings.Split(v, constant.COMMA_SEPARATOR)
+	set := gxset.NewSet()
+	for _, app := range appNames {
+		set.Add(app)
+	}
+	return set, nil
+}
+
 type etcdMetadataReportFactory struct{}
 
 // CreateMetadataReport get the MetadataReport instance of etcd
diff --git a/metadata/report/etcd/report_test.go b/metadata/report/etcd/report_test.go
index 81eece0..aed380b 100644
--- a/metadata/report/etcd/report_test.go
+++ b/metadata/report/etcd/report_test.go
@@ -114,6 +114,36 @@ func TestEtcdMetadataReport_CRUD(t *testing.T) {
 	e.Close()
 }
 
+func TestEtcdMetadataReport_ServiceAppMapping(t *testing.T) {
+	e := initEtcd(t)
+	url, err := common.NewURL("registry://127.0.0.1:2379", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER)))
+	if err != nil {
+		t.Fatal(err)
+	}
+	metadataReportFactory := &etcdMetadataReportFactory{}
+	metadataReport := metadataReportFactory.CreateMetadataReport(url)
+	assert.NotNil(t, metadataReport)
+
+	_, err = metadataReport.GetServiceAppMapping("com.apache.dubbo.sample.basic.IGreeter", "mapping")
+	assert.NotNil(t, err)
+
+	err = metadataReport.RegisterServiceAppMapping("com.apache.dubbo.sample.basic.IGreeter", "mapping", "demo_provider")
+	assert.Nil(t, err)
+	set, err := metadataReport.GetServiceAppMapping("com.apache.dubbo.sample.basic.IGreeter", "mapping")
+	assert.Nil(t, err)
+	assert.Equal(t, 1, set.Size())
+
+	err = metadataReport.RegisterServiceAppMapping("com.apache.dubbo.sample.basic.IGreeter", "mapping", "demo_provider2")
+	assert.Nil(t, err)
+	err = metadataReport.RegisterServiceAppMapping("com.apache.dubbo.sample.basic.IGreeter", "mapping", "demo_provider")
+	assert.Nil(t, err)
+	set, err = metadataReport.GetServiceAppMapping("com.apache.dubbo.sample.basic.IGreeter", "mapping")
+	assert.Nil(t, err)
+	assert.Equal(t, 2, set.Size())
+
+	e.Close()
+}
+
 func newSubscribeMetadataIdentifier() *identifier.SubscriberMetadataIdentifier {
 	return &identifier.SubscriberMetadataIdentifier{
 		Revision: "subscribe",
diff --git a/metadata/report/nacos/report.go b/metadata/report/nacos/report.go
index 30f68b8..37e17d2 100644
--- a/metadata/report/nacos/report.go
+++ b/metadata/report/nacos/report.go
@@ -20,9 +20,11 @@ package nacos
 import (
 	"encoding/json"
 	"net/url"
+	"strings"
 )
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
 	nacosClient "github.com/dubbogo/gost/database/kv/nacos"
 
 	"github.com/nacos-group/nacos-sdk-go/vo"
@@ -32,6 +34,7 @@ import (
 
 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/metadata/identifier"
@@ -206,6 +209,48 @@ func (n *nacosMetadataReport) getConfig(param vo.ConfigParam) (string, error) {
 	return cfg, nil
 }
 
+// RegisterServiceAppMapping map the specified Dubbo service interface to current Dubbo app name
+func (n *nacosMetadataReport) RegisterServiceAppMapping(key string, group string, value string) error {
+	oldVal, err := n.getConfig(vo.ConfigParam{
+		DataId: key,
+		Group:  group,
+	})
+	if err != nil {
+		return err
+	}
+	if strings.Contains(oldVal, value) {
+		return nil
+	}
+	if oldVal != "" {
+		value = oldVal + constant.COMMA_SEPARATOR + value
+	}
+	return n.storeMetadata(vo.ConfigParam{
+		DataId:  key,
+		Group:   group,
+		Content: value,
+	})
+}
+
+// GetServiceAppMapping get the app names from the specified Dubbo service interface
+func (n *nacosMetadataReport) GetServiceAppMapping(key string, group string) (*gxset.HashSet, error) {
+	v, err := n.getConfig(vo.ConfigParam{
+		DataId: key,
+		Group:  group,
+	})
+	if err != nil {
+		return nil, err
+	}
+	if v == "" {
+		return nil, perrors.New("There is no service app mapping data.")
+	}
+	appNames := strings.Split(v, constant.COMMA_SEPARATOR)
+	set := gxset.NewSet()
+	for _, e := range appNames {
+		set.Add(e)
+	}
+	return set, nil
+}
+
 type nacosMetadataReportFactory struct{}
 
 // nolint
diff --git a/metadata/report/report.go b/metadata/report/report.go
index 09c393e..ea748d2 100644
--- a/metadata/report/report.go
+++ b/metadata/report/report.go
@@ -18,6 +18,10 @@
 package report
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
+)
+
+import (
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/metadata/identifier"
 )
@@ -63,4 +67,10 @@ type MetadataReport interface {
 
 	// PublishAppMetadata publish metadata info to reportss
 	PublishAppMetadata(*identifier.SubscriberMetadataIdentifier, *common.MetadataInfo) error
+
+	// RegisterServiceAppMapping map the specified Dubbo service interface to current Dubbo app name
+	RegisterServiceAppMapping(string, string, string) error
+
+	// GetServiceAppMapping get the app names from the specified Dubbo service interface
+	GetServiceAppMapping(string, string) (*gxset.HashSet, error)
 }
diff --git a/metadata/report/zookeeper/report.go b/metadata/report/zookeeper/report.go
index 68220c5..0e08a19 100644
--- a/metadata/report/zookeeper/report.go
+++ b/metadata/report/zookeeper/report.go
@@ -25,7 +25,7 @@ import (
 
 import (
 	"github.com/dubbogo/go-zookeeper/zk"
-
+	gxset "github.com/dubbogo/gost/container/set"
 	gxzookeeper "github.com/dubbogo/gost/database/kv/zk"
 )
 
@@ -142,6 +142,39 @@ func (m *zookeeperMetadataReport) GetServiceDefinition(metadataIdentifier *ident
 	return string(v), err
 }
 
+// RegisterServiceAppMapping map the specified Dubbo service interface to current Dubbo app name
+func (m *zookeeperMetadataReport) RegisterServiceAppMapping(key string, group string, value string) error {
+	path := m.rootDir + group + constant.PATH_SEPARATOR + key
+	v, state, err := m.client.GetContent(path)
+	if err == zk.ErrNoNode {
+		return m.client.CreateWithValue(path, []byte(value))
+	} else if err != nil {
+		return err
+	}
+	oldValue := string(v)
+	if strings.Contains(oldValue, value) {
+		return nil
+	}
+	value = oldValue + constant.COMMA_SEPARATOR + value
+	_, err = m.client.SetContent(path, []byte(value), state.Version)
+	return err
+}
+
+// GetServiceAppMapping get the app names from the specified Dubbo service interface
+func (m *zookeeperMetadataReport) GetServiceAppMapping(key string, group string) (*gxset.HashSet, error) {
+	path := m.rootDir + group + constant.PATH_SEPARATOR + key
+	v, _, err := m.client.GetContent(path)
+	if err != nil {
+		return nil, err
+	}
+	appNames := strings.Split(string(v), constant.COMMA_SEPARATOR)
+	set := gxset.NewSet()
+	for _, e := range appNames {
+		set.Add(e)
+	}
+	return set, nil
+}
+
 type zookeeperMetadataReportFactory struct{}
 
 // nolint
diff --git a/metadata/service/exporter/configurable/exporter.go b/metadata/service/exporter/configurable/exporter.go
index 50d0485..feee948 100644
--- a/metadata/service/exporter/configurable/exporter.go
+++ b/metadata/service/exporter/configurable/exporter.go
@@ -31,7 +31,7 @@ import (
 	"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/mapping/dynamic"
+	_ "dubbo.apache.org/dubbo-go/v3/metadata/mapping/metadata"
 	"dubbo.apache.org/dubbo-go/v3/metadata/service"
 	"dubbo.apache.org/dubbo-go/v3/metadata/service/exporter"
 	_ "dubbo.apache.org/dubbo-go/v3/metadata/service/remote"
diff --git a/metadata/service/remote/service_test.go b/metadata/service/remote/service_test.go
index 938a860..fc46367 100644
--- a/metadata/service/remote/service_test.go
+++ b/metadata/service/remote/service_test.go
@@ -23,6 +23,7 @@ import (
 )
 
 import (
+	gxset "github.com/dubbogo/gost/container/set"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -55,11 +56,19 @@ func (mrf *metadataReportFactory) CreateMetadataReport(*common.URL) report.Metad
 
 type metadataReport struct{}
 
-func (mr metadataReport) GetAppMetadata(metadataIdentifier *identifier.SubscriberMetadataIdentifier) (*common.MetadataInfo, error) {
+func (mr metadataReport) RegisterServiceAppMapping(string, string, string) error {
 	panic("implement me")
 }
 
-func (mr metadataReport) PublishAppMetadata(metadataIdentifier *identifier.SubscriberMetadataIdentifier, info *common.MetadataInfo) error {
+func (mr metadataReport) GetServiceAppMapping(string, string) (*gxset.HashSet, error) {
+	panic("implement me")
+}
+
+func (mr metadataReport) GetAppMetadata(*identifier.SubscriberMetadataIdentifier) (*common.MetadataInfo, error) {
+	panic("implement me")
+}
+
+func (mr metadataReport) PublishAppMetadata(*identifier.SubscriberMetadataIdentifier, *common.MetadataInfo) error {
 	panic("implement me")
 }
 
diff --git a/registry/event/event_publishing_service_deiscovery_test.go b/registry/event/event_publishing_service_discovery_test.go
similarity index 100%
rename from registry/event/event_publishing_service_deiscovery_test.go
rename to registry/event/event_publishing_service_discovery_test.go
diff --git a/registry/event/service_name_mapping_listener.go b/registry/event/service_name_mapping_listener.go
index e7d979a..f2dfaf9 100644
--- a/registry/event/service_name_mapping_listener.go
+++ b/registry/event/service_name_mapping_listener.go
@@ -27,7 +27,6 @@ import (
 )
 
 import (
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/observer"
 	"dubbo.apache.org/dubbo-go/v3/metadata/mapping"
@@ -55,13 +54,10 @@ func (s *serviceNameMappingListener) OnEvent(e observer.Event) error {
 		sc := ex.ServiceConfig
 		urls := sc.GetExportedUrls()
 
-		for _, u := range urls {
-			err := s.nameMapping.Map(u.GetParam(constant.INTERFACE_KEY, ""),
-				u.GetParam(constant.GROUP_KEY, ""),
-				u.GetParam(constant.Version, ""),
-				u.Protocol)
+		for _, url := range urls {
+			err := s.nameMapping.Map(url)
 			if err != nil {
-				return perrors.WithMessage(err, "could not map the service: "+u.String())
+				return perrors.WithMessage(err, "could not map the service: "+url.String())
 			}
 		}
 	}
diff --git a/registry/servicediscovery/service_discovery_registry.go b/registry/servicediscovery/service_discovery_registry.go
index 655c8a1..ba66a3f 100644
--- a/registry/servicediscovery/service_discovery_registry.go
+++ b/registry/servicediscovery/service_discovery_registry.go
@@ -181,10 +181,7 @@ func (s *serviceDiscoveryRegistry) Register(url *common.URL) error {
 		logger.Warnf("The URL[%s] has been registry!", url.String())
 	}
 
-	return s.serviceNameMapping.Map(url.GetParam(constant.INTERFACE_KEY, ""),
-		url.GetParam(constant.GROUP_KEY, ""),
-		url.GetParam(constant.Version, ""),
-		url.Protocol)
+	return s.serviceNameMapping.Map(url)
 }
 
 func shouldRegister(url *common.URL) bool {
@@ -303,14 +300,9 @@ func (s *serviceDiscoveryRegistry) getServices(url *common.URL) *gxset.HashSet {
 }
 
 func (s *serviceDiscoveryRegistry) findMappedServices(url *common.URL) *gxset.HashSet {
-	serviceInterface := url.GetParam(constant.INTERFACE_KEY, url.Path)
-	group := url.GetParam(constant.GROUP_KEY, "")
-	version := url.GetParam(constant.VERSION_KEY, "")
-	protocol := url.Protocol
-	serviceNames, err := s.serviceNameMapping.Get(serviceInterface, group, version, protocol)
+	serviceNames, err := s.serviceNameMapping.Get(url)
 	if err != nil {
-		logger.Errorf("get serviceInterface:[%s] group:[%s] version:[%s] protocol:[%s] from "+
-			"serviceNameMap error:%s", err.Error())
+		logger.Errorf("get service names catch error, url:%s, err:%s ", url.String(), err.Error())
 		return gxset.NewSet()
 	}
 	return serviceNames