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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new 1e872372f Enhancements: Make 'group' and 'version' flag of app level 
works. (#1880)
1e872372f is described below

commit 1e872372f844e5833cfda51e2aa3c89dfd5d2a90
Author: Laurence <[email protected]>
AuthorDate: Thu May 26 21:36:25 2022 +0800

    Enhancements: Make 'group' and 'version' flag of app level works. (#1880)
    
    * Fix: reflection and auto config service
    
    * fix: add xds sniffing logs
    
    * fix: add xds timeout to 10s
    
    * fix: add debug info
    
    * Fix: large xds timeout
    
    * fix: add xds logs
    
    * Fix: add xds wrapper client api
    
    * fix: update get metadata logic
    
    * Fix: enhance xds client api
    
    * Fix: add license
    
    * fix: typo
    
    * Fix: not register yaml tag
    
    * Fix: add default protocol
    
    * fix: logs
---
 common/constant/key.go                             |   6 +
 config/application_config.go                       |   5 +-
 config/config_utils.go                             |   4 +-
 config/consumer_config.go                          |  41 ++++---
 config/custom_config_test.go                       |   2 +-
 config/provider_config.go                          |  54 ++++++---
 config/reference_config.go                         |  15 ++-
 config/service.go                                  |  10 ++
 config/service_config.go                           |  25 ++++-
 config_center/nacos/impl_test.go                   |  10 +-
 .../triple_reflection_v1alpha/reflection.pb.go     |   8 +-
 .../reflection_triple.pb.go                        |  19 +++-
 registry/xds/registry.go                           |  19 +++-
 remoting/xds/client.go                             |  63 +++++++++--
 remoting/xds/client_test.go                        |  57 ++++++++--
 remoting/xds/{error.go => config.go}               |  17 ++-
 remoting/xds/error.go                              |   4 +-
 remoting/xds/mapping/handler.go                    |  31 +++++-
 remoting/xds/mapping/handler_test.go               |   6 +-
 remoting/xds/mapping/mocks/InterfaceMapHandler.go  |  21 ++++
 remoting/xds/mocks/client.go                       |   5 +
 test/xds/main.go                                   | 121 ---------------------
 22 files changed, 326 insertions(+), 217 deletions(-)

diff --git a/common/constant/key.go b/common/constant/key.go
index 6bb6365df..7cea915e7 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -367,3 +367,9 @@ const (
        AdaptiveServiceEnabledKey   = "adaptive-service.enabled"
        AdaptiveServiceIsEnabled    = "1"
 )
+
+// reflection service
+const (
+       ReflectionServiceTypeName  = "XXX_serverReflectionServer"
+       ReflectionServiceInterface = "grpc.reflection.v1alpha.ServerReflection"
+)
diff --git a/config/application_config.go b/config/application_config.go
index 1520e8e4f..13e00d5d1 100644
--- a/config/application_config.go
+++ b/config/application_config.go
@@ -32,9 +32,10 @@ type ApplicationConfig struct {
        Organization string `default:"dubbo-go" 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:"3.0.0" yaml:"version" 
json:"version,omitempty" property:"version"`
+       Group        string `yaml:"group" json:"group,omitempty" 
property:"module"`
+       Version      string `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"`
+       Environment  string `yaml:"environment" json:"environment,omitempty" 
property:"environment"`
        // the metadata type. remote or local
        MetadataType string `default:"local" yaml:"metadata-type" 
json:"metadataType,omitempty" property:"metadataType"`
 }
diff --git a/config/config_utils.go b/config/config_utils.go
index be1cf9be5..f08d1b901 100644
--- a/config/config_utils.go
+++ b/config/config_utils.go
@@ -90,8 +90,8 @@ func removeDuplicateElement(items []string) []string {
        return result
 }
 
-// translateRegistryIds string "nacos,zk" => ["nacos","zk"]
-func translateRegistryIds(registryIds []string) []string {
+// translateIds string "nacos,zk" => ["nacos","zk"]
+func translateIds(registryIds []string) []string {
        ids := make([]string, 0)
        for _, id := range registryIds {
 
diff --git a/config/consumer_config.go b/config/consumer_config.go
index 4badfcd25..af04775d7 100644
--- a/config/consumer_config.go
+++ b/config/consumer_config.go
@@ -24,13 +24,14 @@ import (
 
 import (
        "github.com/creasty/defaults"
+
+       tripleConstant "github.com/dubbogo/triple/pkg/common/constant"
 )
 
 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/generic"
 )
 
 const (
@@ -41,6 +42,7 @@ const (
 type ConsumerConfig struct {
        Filter                         string                      
`yaml:"filter" json:"filter,omitempty" property:"filter"`
        RegistryIDs                    []string                    
`yaml:"registry-ids" json:"registry-ids,omitempty" property:"registry-ids"`
+       Protocol                       string                      
`yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
        RequestTimeout                 string                      
`default:"3s" yaml:"request-timeout" json:"request-timeout,omitempty" 
property:"request-timeout"`
        ProxyFactory                   string                      
`default:"default" yaml:"proxy" json:"proxy,omitempty" property:"proxy"`
        Check                          bool                        
`yaml:"check" json:"check,omitempty" property:"check"`
@@ -61,7 +63,7 @@ func (cc *ConsumerConfig) Init(rc *RootConfig) error {
        if cc == nil {
                return nil
        }
-       cc.RegistryIDs = translateRegistryIds(cc.RegistryIDs)
+       cc.RegistryIDs = translateIds(cc.RegistryIDs)
        if len(cc.RegistryIDs) <= 0 {
                cc.RegistryIDs = rc.getRegistryIds()
        }
@@ -103,19 +105,30 @@ func (cc *ConsumerConfig) Init(rc *RootConfig) error {
 }
 
 func (cc *ConsumerConfig) Load() {
-       for key, ref := range cc.References {
-               if ref.Generic != "" {
-                       genericService := generic.NewGenericService(key)
-                       SetConsumerService(genericService)
-               }
-               rpcService := GetConsumerService(key)
-               if rpcService == nil {
-                       logger.Warnf("%s does not exist!", key)
-                       continue
+       for registeredTypeName, refRPCService := range GetConsumerServiceMap() {
+               refConfig, ok := cc.References[registeredTypeName]
+               if !ok {
+                       // not found configuration, now new a configuration 
with default.
+                       refConfig = 
NewReferenceConfigBuilder().SetProtocol(tripleConstant.TRIPLE).Build()
+                       triplePBService, ok := 
refRPCService.(common.TriplePBService)
+                       if !ok {
+                               logger.Errorf("Dubbo-go cannot get interface 
name with registeredTypeName = %s."+
+                                       "Please run the command 'go install 
github.com/dubbogo/tools/cmd/protoc-gen-go-triple@latest' to get the latest "+
+                                       "protoc-gen-go-triple,  and then 
re-generate your pb file again by this tool."+
+                                       "If you are not using pb serialization, 
please set 'interfaceName' field in reference config to let dubbogo get the 
interface name.", registeredTypeName)
+                               continue
+                       } else {
+                               // use interface name defined by pb
+                               refConfig.InterfaceName = 
triplePBService.XXX_InterfaceName()
+                       }
+                       if err := refConfig.Init(rootConfig); err != nil {
+                               logger.Errorf(fmt.Sprintf("reference with 
registeredTypeName = %s init failed! err: %#v", registeredTypeName, err))
+                               continue
+                       }
                }
-               ref.id = key
-               ref.Refer(rpcService)
-               ref.Implement(rpcService)
+               refConfig.id = registeredTypeName
+               refConfig.Refer(refRPCService)
+               refConfig.Implement(refRPCService)
        }
 
        var maxWait int
diff --git a/config/custom_config_test.go b/config/custom_config_test.go
index 72193a244..ccf3c58eb 100644
--- a/config/custom_config_test.go
+++ b/config/custom_config_test.go
@@ -79,7 +79,7 @@ func TestConfigUtils(t *testing.T) {
 
        assert.Equal(t, id, 
strings.Join([]string{constant.RegistryConfigPrefix, "nacos", 
"127.0.0.1:8848"}, "-"))
 
-       ids := translateRegistryIds([]string{"nacos,zk"})
+       ids := translateIds([]string{"nacos,zk"})
        assert.Equal(t, ids[0], "nacos")
        assert.Equal(t, ids[1], "zk")
 
diff --git a/config/provider_config.go b/config/provider_config.go
index cc7212042..0c024947c 100644
--- a/config/provider_config.go
+++ b/config/provider_config.go
@@ -43,6 +43,8 @@ type ProviderConfig struct {
        Register bool `yaml:"register" json:"register" property:"register"`
        // RegistryIDs is registry ids list
        RegistryIDs []string `yaml:"registry-ids" json:"registry-ids" 
property:"registry-ids"`
+       // protocol
+       ProtocolIDs []string `yaml:"protocol-ids" json:"protocol-ids" 
property:"protocol-ids"`
        // TracingKey is tracing ids list
        TracingKey string `yaml:"tracing-key" json:"tracing-key" 
property:"tracing-key"`
        // Services services
@@ -72,10 +74,12 @@ func (c *ProviderConfig) Init(rc *RootConfig) error {
        if c == nil {
                return nil
        }
-       c.RegistryIDs = translateRegistryIds(c.RegistryIDs)
+       c.RegistryIDs = translateIds(c.RegistryIDs)
        if len(c.RegistryIDs) <= 0 {
                c.RegistryIDs = rc.getRegistryIds()
        }
+       c.ProtocolIDs = translateIds(c.ProtocolIDs)
+
        if c.TracingKey == "" && len(rc.Tracing) > 0 {
                for k, _ := range rc.Tracing {
                        c.TracingKey = k
@@ -107,14 +111,16 @@ func (c *ProviderConfig) Init(rc *RootConfig) error {
 
        for k, v := range rc.Protocols {
                if v.Name == tripleConstant.TRIPLE {
+                       // Auto create reflection service configure only when 
provider with triple service is configured.
                        tripleReflectionService := NewServiceConfigBuilder().
                                SetProtocolIDs(k).
-                               
SetInterface("grpc.reflection.v1alpha.ServerReflection").
+                               SetNotRegister(true).
+                               
SetInterface(constant.ReflectionServiceInterface).
                                Build()
                        if err := tripleReflectionService.Init(rc); err != nil {
                                return err
                        }
-                       c.Services["XXX_serverReflectionServer"] = 
tripleReflectionService
+                       c.Services[constant.ReflectionServiceTypeName] = 
tripleReflectionService
                }
        }
 
@@ -135,21 +141,38 @@ func (c *ProviderConfig) Init(rc *RootConfig) error {
 }
 
 func (c *ProviderConfig) Load() {
-       for key, svs := range c.Services {
-               rpcService := GetProviderService(key)
-               if rpcService == nil {
-                       logger.Warnf("Service reference key %s does not exist, 
please check if this key "+
-                               "matches your provider struct type name, or 
matches the returned valued of your provider struct's Reference() function."+
-                               "View 
https://www.yuque.com/u772707/eqpff0/pqfgz3#zxdw0 for details", key)
-                       continue
+       for registeredTypeName, service := range GetProviderServiceMap() {
+               serviceConfig, ok := c.Services[registeredTypeName]
+               if !ok {
+                       if registeredTypeName == 
constant.ReflectionServiceTypeName {
+                               // do not auto generate reflection server's 
configuration.
+                               continue
+                       }
+                       // service doesn't config in config file, create one 
with default
+                       logger.Warnf("Dubbogo can not find service with 
registeredTypeName %s in configuration. Use the default configuration 
instead.", registeredTypeName)
+                       supportPBPackagerNameSerivce, ok := 
service.(common.TriplePBService)
+                       serviceConfig = NewServiceConfigBuilder().Build()
+                       if !ok {
+                               logger.Errorf("Dubbogo do not read service 
interface name with registeredTypeName = %s."+
+                                       "Please run go install 
github.com/dubbogo/tools/cmd/protoc-gen-go-triple@latest to update your "+
+                                       "protoc-gen-go-triple and re-generate 
your pb file again."+
+                                       "If you are not using pb serialization, 
please set 'interface' field in service config.", registeredTypeName)
+                               continue
+                       } else {
+                               // use interface name defined by pb
+                               serviceConfig.Interface = 
supportPBPackagerNameSerivce.XXX_InterfaceName()
+                       }
+                       if err := serviceConfig.Init(rootConfig); err != nil {
+                               logger.Errorf("Service with refKey = %s init 
failed with error = %s")
+                       }
+                       serviceConfig.adaptiveService = c.AdaptiveService
                }
-               svs.id = key
-               svs.Implement(rpcService)
-               if err := svs.Export(); err != nil {
-                       logger.Errorf(fmt.Sprintf("service %s export failed! 
err: %#v", key, err))
+               serviceConfig.id = registeredTypeName
+               serviceConfig.Implement(service)
+               if err := serviceConfig.Export(); err != nil {
+                       logger.Errorf(fmt.Sprintf("service with 
registeredTypeName = %s export failed! err: %#v", registeredTypeName, err))
                }
        }
-
 }
 
 // newEmptyProviderConfig returns ProviderConfig with default ApplicationConfig
@@ -157,6 +180,7 @@ func newEmptyProviderConfig() *ProviderConfig {
        newProviderConfig := &ProviderConfig{
                Services:    make(map[string]*ServiceConfig),
                RegistryIDs: make([]string, 8),
+               ProtocolIDs: make([]string, 8),
        }
        return newProviderConfig
 }
diff --git a/config/reference_config.go b/config/reference_config.go
index af8f48d8d..4c443f7e4 100644
--- a/config/reference_config.go
+++ b/config/reference_config.go
@@ -49,7 +49,7 @@ type ReferenceConfig struct {
        Check          *bool             `yaml:"check"  json:"check,omitempty" 
property:"check"`
        URL            string            `yaml:"url"  json:"url,omitempty" 
property:"url"`
        Filter         string            `yaml:"filter" json:"filter,omitempty" 
property:"filter"`
-       Protocol       string            `default:"tri" yaml:"protocol"  
json:"protocol,omitempty" property:"protocol"`
+       Protocol       string            `yaml:"protocol"  
json:"protocol,omitempty" property:"protocol"`
        RegistryIDs    []string          `yaml:"registry-ids"  
json:"registry-ids,omitempty"  property:"registry-ids"`
        Cluster        string            `yaml:"cluster"  
json:"cluster,omitempty" property:"cluster"`
        Loadbalance    string            `yaml:"loadbalance"  
json:"loadbalance,omitempty" property:"loadbalance"`
@@ -89,14 +89,25 @@ func (rc *ReferenceConfig) Init(root *RootConfig) error {
        rc.rootConfig = root
        if root.Application != nil {
                rc.metaDataType = root.Application.MetadataType
+               if rc.Group == "" {
+                       rc.Group = root.Application.Group
+               }
+               if rc.Version == "" {
+                       rc.Version = root.Application.Version
+               }
        }
        if rc.Cluster == "" {
                rc.Cluster = "failover"
        }
-       rc.RegistryIDs = translateRegistryIds(rc.RegistryIDs)
+       rc.RegistryIDs = translateIds(rc.RegistryIDs)
        if len(rc.RegistryIDs) <= 0 {
                rc.RegistryIDs = root.Consumer.RegistryIDs
        }
+
+       if rc.Protocol == "" {
+               rc.Protocol = root.Consumer.Protocol
+       }
+
        if rc.TracingKey == "" {
                rc.TracingKey = root.Consumer.TracingKey
        }
diff --git a/config/service.go b/config/service.go
index 03aa99c5c..723847fca 100644
--- a/config/service.go
+++ b/config/service.go
@@ -64,6 +64,16 @@ func GetProviderService(name string) common.RPCService {
        return proServices[name]
 }
 
+// GetProviderServiceMap gets ProviderServiceMap
+func GetProviderServiceMap() map[string]common.RPCService {
+       return proServices
+}
+
+// GetConsumerServiceMap gets ProviderServiceMap
+func GetConsumerServiceMap() map[string]common.RPCService {
+       return conServices
+}
+
 // SetConsumerServiceByInterfaceName is used by pb serialization
 func SetConsumerServiceByInterfaceName(interfaceName string, srv 
common.RPCService) {
        interfaceNameConServicesLock.Lock()
diff --git a/config/service_config.go b/config/service_config.go
index 516736fe4..9627f2b91 100644
--- a/config/service_config.go
+++ b/config/service_config.go
@@ -73,6 +73,7 @@ type ServiceConfig struct {
        ExecuteLimit                string            `yaml:"execute.limit" 
json:"execute.limit,omitempty" property:"execute.limit"`
        ExecuteLimitRejectedHandler string            
`yaml:"execute.limit.rejected.handler" 
json:"execute.limit.rejected.handler,omitempty" 
property:"execute.limit.rejected.handler"`
        Auth                        string            `yaml:"auth" 
json:"auth,omitempty" property:"auth"`
+       NotRegister                 bool              `yaml:"not_register" 
json:"not_register,omitempty" property:"not_register"`
        ParamSign                   string            `yaml:"param.sign" 
json:"param.sign,omitempty" property:"param.sign"`
        Tag                         string            `yaml:"tag" 
json:"tag,omitempty" property:"tag"`
        GrpcMaxMessageSize          int               `default:"4" 
yaml:"max_message_size" json:"max_message_size,omitempty"`
@@ -108,6 +109,12 @@ func (s *ServiceConfig) Init(rc *RootConfig) error {
        }
        s.exported = atomic.NewBool(false)
        s.metadataType = rc.Application.MetadataType
+       if s.Version == "" {
+               s.Version = rc.Application.Version
+       }
+       if s.Group == "" {
+               s.Group = rc.Application.Group
+       }
        s.unexported = atomic.NewBool(false)
        if len(s.RCRegistriesMap) == 0 {
                s.RCRegistriesMap = rc.Registries
@@ -118,10 +125,15 @@ func (s *ServiceConfig) Init(rc *RootConfig) error {
        if rc.Provider != nil {
                s.ProxyFactoryKey = rc.Provider.ProxyFactory
        }
-       s.RegistryIDs = translateRegistryIds(s.RegistryIDs)
+       s.RegistryIDs = translateIds(s.RegistryIDs)
        if len(s.RegistryIDs) <= 0 {
                s.RegistryIDs = rc.Provider.RegistryIDs
        }
+
+       s.ProtocolIDs = translateIds(s.ProtocolIDs)
+       if len(s.ProtocolIDs) <= 0 {
+               s.ProtocolIDs = rc.Provider.ProtocolIDs
+       }
        if len(s.ProtocolIDs) <= 0 {
                for k, _ := range rc.Protocols {
                        s.ProtocolIDs = append(s.ProtocolIDs, k)
@@ -222,7 +234,11 @@ func (s *ServiceConfig) Export() error {
                return nil
        }
 
-       regUrls := loadRegistries(s.RegistryIDs, s.RCRegistriesMap, 
common.PROVIDER)
+       regUrls := make([]*common.URL, 0)
+       if !s.NotRegister {
+               regUrls = loadRegistries(s.RegistryIDs, s.RCRegistriesMap, 
common.PROVIDER)
+       }
+
        urlMap := s.getUrlMap()
        protocolConfigs := loadProtocol(s.ProtocolIDs, s.RCProtocolsMap)
        if len(protocolConfigs) == 0 {
@@ -595,6 +611,11 @@ func (pcb *ServiceConfigBuilder) SetServiceID(id string) 
*ServiceConfigBuilder {
        return pcb
 }
 
+func (pcb *ServiceConfigBuilder) SetNotRegister(notRegister bool) 
*ServiceConfigBuilder {
+       pcb.serviceConfig.NotRegister = notRegister
+       return pcb
+}
+
 func (pcb *ServiceConfigBuilder) Build() *ServiceConfig {
        return pcb.serviceConfig
 }
diff --git a/config_center/nacos/impl_test.go b/config_center/nacos/impl_test.go
index 209fbaf45..8d7a08aaa 100644
--- a/config_center/nacos/impl_test.go
+++ b/config_center/nacos/impl_test.go
@@ -20,7 +20,6 @@ package nacos
 
 import (
        "reflect"
-       "sync"
        "testing"
 )
 
@@ -156,11 +155,8 @@ type fields struct {
        BaseDynamicConfiguration config_center.BaseDynamicConfiguration
        url                      *common.URL
        rootPath                 string
-       wg                       sync.WaitGroup
-       cltLock                  sync.Mutex
        done                     chan struct{}
        client                   *nacosClient.NacosConfigClient
-       keyListeners             sync.Map
        parser                   parser.ConfigurationParser
 }
 type args struct {
@@ -169,7 +165,7 @@ type args struct {
        value string
 }
 
-func newnNacosDynamicConfiguration(f fields) *nacosDynamicConfiguration {
+func newnNacosDynamicConfiguration(f *fields) *nacosDynamicConfiguration {
        return &nacosDynamicConfiguration{
                BaseDynamicConfiguration: f.BaseDynamicConfiguration,
                url:                      f.url,
@@ -208,7 +204,7 @@ func Test_nacosDynamicConfiguration_PublishConfig(t 
*testing.T) {
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       n := newnNacosDynamicConfiguration(tt.fields)
+                       n := newnNacosDynamicConfiguration(&tt.fields)
                        if err := n.PublishConfig(tt.args.key, tt.args.group, 
tt.args.value); (err != nil) != tt.wantErr {
                                t.Errorf("PublishConfig() error = %v, wantErr 
%v", err, tt.wantErr)
                        }
@@ -253,7 +249,7 @@ func Test_nacosDynamicConfiguration_GetConfigKeysByGroup(t 
*testing.T) {
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       n := newnNacosDynamicConfiguration(tt.fields)
+                       n := newnNacosDynamicConfiguration(&tt.fields)
                        got, err := n.GetConfigKeysByGroup(tt.args.group)
                        if (err != nil) != tt.wantErr {
                                t.Errorf("GetConfigKeysByGroup() error = %v, 
wantErr %v", err, tt.wantErr)
diff --git 
a/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection.pb.go 
b/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection.pb.go
index 334a88b17..7ad066379 100644
--- a/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection.pb.go
+++ b/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection.pb.go
@@ -19,7 +19,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-//     protoc-gen-go v1.25.0
+//     protoc-gen-go v1.26.0
 //     protoc        v3.14.0
 // source: reflection.proto
 
@@ -31,8 +31,6 @@ import (
 )
 
 import (
-       proto "github.com/golang/protobuf/proto"
-
        protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 
        protoimpl "google.golang.org/protobuf/runtime/protoimpl"
@@ -45,10 +43,6 @@ const (
        _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
 
-// This is a compile-time assertion that a sufficiently up-to-date version
-// of the legacy proto package is being used.
-const _ = proto.ProtoPackageIsVersion4
-
 // The message sent by the client when calling ServerReflectionInfo method.
 type ServerReflectionRequest struct {
        state         protoimpl.MessageState
diff --git 
a/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection_triple.pb.go 
b/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection_triple.pb.go
index 97edf8f1d..d85ad7661 100644
--- 
a/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection_triple.pb.go
+++ 
b/protocol/dubbo3/reflection/triple_reflection_v1alpha/reflection_triple.pb.go
@@ -17,7 +17,7 @@
 
 // Code generated by protoc-gen-go-triple. DO NOT EDIT.
 // versions:
-// - protoc-gen-go-triple v1.0.2
+// - protoc-gen-go-triple v1.0.8
 // - protoc             v3.14.0
 // source: reflection.proto
 
@@ -31,6 +31,7 @@ import (
 import (
        grpc_go "github.com/dubbogo/grpc-go"
        codes "github.com/dubbogo/grpc-go/codes"
+       metadata "github.com/dubbogo/grpc-go/metadata"
        status "github.com/dubbogo/grpc-go/status"
 
        constant "github.com/dubbogo/triple/pkg/common/constant"
@@ -38,6 +39,7 @@ import (
 )
 
 import (
+       constant1 "dubbo.apache.org/dubbo-go/v3/common/constant"
        protocol "dubbo.apache.org/dubbo-go/v3/protocol"
        dubbo3 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
        invocation "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
@@ -68,6 +70,10 @@ func (c *ServerReflectionClientImpl) GetDubboStub(cc 
*triple.TripleConn) ServerR
        return NewServerReflectionClient(cc)
 }
 
+func (c *ServerReflectionClientImpl) XXX_InterfaceName() string {
+       return "triple.reflection.v1alpha.ServerReflection"
+}
+
 func NewServerReflectionClient(cc *triple.TripleConn) ServerReflectionClient {
        return &serverReflectionClient{cc}
 }
@@ -133,6 +139,10 @@ func (s *UnimplementedServerReflectionServer) 
XXX_GetProxyImpl() protocol.Invoke
 func (s *UnimplementedServerReflectionServer) XXX_ServiceDesc() 
*grpc_go.ServiceDesc {
        return &ServerReflection_ServiceDesc
 }
+func (s *UnimplementedServerReflectionServer) XXX_InterfaceName() string {
+       return "triple.reflection.v1alpha.ServerReflection"
+}
+
 func (UnimplementedServerReflectionServer) 
mustEmbedUnimplementedServerReflectionServer() {}
 
 // UnsafeServerReflectionServer may be embedded to opt out of forward 
compatibility for this service.
@@ -148,6 +158,13 @@ func RegisterServerReflectionServer(s 
grpc_go.ServiceRegistrar, srv ServerReflec
 
 func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream 
grpc_go.ServerStream) error {
        _, ok := srv.(dubbo3.Dubbo3GrpcService)
+       ctx := stream.Context()
+       md, _ := metadata.FromIncomingContext(ctx)
+       invAttachment := make(map[string]interface{}, len(md))
+       for k, v := range md {
+               invAttachment[k] = v
+       }
+       stream.(grpc_go.CtxSetterStream).SetContext(context.WithValue(ctx, 
constant1.AttachmentKey, invAttachment))
        invo := invocation.NewRPCInvocation("ServerReflectionInfo", nil, nil)
        if !ok {
                fmt.Println(invo)
diff --git a/registry/xds/registry.go b/registry/xds/registry.go
index f6d91dbb3..b3f71b04f 100644
--- a/registry/xds/registry.go
+++ b/registry/xds/registry.go
@@ -39,6 +39,7 @@ import (
 )
 
 var localIP = ""
+var DefaultXDSSniffingTimeoutStr = "5s"
 
 func init() {
        localIP = common.GetLocalIp()
@@ -60,24 +61,25 @@ func getCategory(url *common.URL) string {
        return category
 }
 
-// getServiceName return serviceName $(providers_or_consumers):$(interfaceName)
+// getServiceName return serviceName 
$(providers_or_consumers):$(interfaceName):$(version):$(group)
 func getServiceName(url *common.URL) string {
        var buffer bytes.Buffer
 
        buffer.Write([]byte(getCategory(url)))
        appendParam(&buffer, url, constant.InterfaceKey)
+       appendParam(&buffer, url, constant.VersionKey)
+       appendParam(&buffer, url, constant.GroupKey)
        return buffer.String()
 }
 
-// getSubscribeName returns subscribeName is providers:$(interfaceName)
+// getSubscribeName returns subscribeName is 
providers:$(interfaceName):$(version):$(group)
 func getSubscribeName(url *common.URL) string {
        var buffer bytes.Buffer
 
        buffer.Write([]byte(common.DubboNodes[common.PROVIDER]))
        appendParam(&buffer, url, constant.InterfaceKey)
-       // We would not append group or version to this name, as istio 
ecosystem only cares about 'hostname' during cds procedure.
-       // The subscribe name is used to find the real hostName.
-       // Group or version are managed by traffic policy, not dubbo-go.
+       appendParam(&buffer, url, constant.VersionKey)
+       appendParam(&buffer, url, constant.GroupKey)
        return buffer.String()
 }
 
@@ -164,7 +166,12 @@ func newXDSRegistry(url *common.URL) (registry.Registry, 
error) {
                        constant.PodNameEnvKey, constant.PodNamespaceEnvKey)
        }
 
-       wrappedXDSClient, err := xds.NewXDSWrappedClient(pn, ns, localIP, 
common2.NewHostNameOrIPAddr(url.Ip+":"+url.Port))
+       wrappedXDSClient, err := xds.NewXDSWrappedClient(xds.Config{
+               PodName:   pn,
+               Namespace: ns,
+               LocalIP:   localIP,
+               IstioAddr: common2.NewHostNameOrIPAddr(url.Ip + ":" + url.Port),
+       })
        if err != nil {
                return nil, err
        }
diff --git a/remoting/xds/client.go b/remoting/xds/client.go
index 7c23f5743..3cdffc10d 100644
--- a/remoting/xds/client.go
+++ b/remoting/xds/client.go
@@ -29,6 +29,7 @@ import (
 
 import (
        "dubbo.apache.org/dubbo-go/v3/common/constant"
+       "dubbo.apache.org/dubbo-go/v3/common/logger"
        "dubbo.apache.org/dubbo-go/v3/protocol"
        "dubbo.apache.org/dubbo-go/v3/registry"
        xdsCommon "dubbo.apache.org/dubbo-go/v3/remoting/xds/common"
@@ -127,6 +128,11 @@ type WrappedClientImpl struct {
                subscribeStopChMap stores subscription stop chan
        */
        subscribeStopChMap sync.Map
+
+       /*
+               xdsSniffingTimeout stores xds sniffing timeout duration
+       */
+       xdsSniffingTimeout time.Duration
 }
 
 func GetXDSWrappedClient() *WrappedClientImpl {
@@ -134,18 +140,24 @@ func GetXDSWrappedClient() *WrappedClientImpl {
 }
 
 // NewXDSWrappedClient create or get singleton xdsWrappedClient
-func NewXDSWrappedClient(podName, namespace, localIP string, istioAddr 
xdsCommon.HostAddr) (XDSWrapperClient, error) {
+func NewXDSWrappedClient(config Config) (XDSWrapperClient, error) {
        // todo @(laurence) safety problem? what if to concurrent 'new' both 
create new client?
        if xdsWrappedClient != nil {
                return xdsWrappedClient, nil
        }
+       if config.SniffingTimeout == 0 {
+               config.SniffingTimeout, _ = 
time.ParseDuration(constant.DefaultRegTimeout)
+       }
+       if config.DebugPort == "" {
+               config.DebugPort = "8080"
+       }
 
        // write param
        newClient := &WrappedClientImpl{
-               podName:    podName,
-               namespace:  namespace,
-               localIP:    localIP,
-               istiodAddr: istioAddr,
+               podName:    config.PodName,
+               namespace:  config.Namespace,
+               localIP:    config.LocalIP,
+               istiodAddr: config.IstioAddr,
 
                rdsMap: make(map[string]resource.RouteConfigUpdate),
                cdsMap: make(map[string]resource.ClusterUpdate),
@@ -155,6 +167,8 @@ func NewXDSWrappedClient(podName, namespace, localIP 
string, istioAddr xdsCommon
 
                cdsUpdateEventChan:     make(chan struct{}),
                cdsUpdateEventHandlers: make([]func(), 0),
+
+               xdsSniffingTimeout: config.SniffingTimeout,
        }
 
        // 1. init xdsclient
@@ -166,7 +180,7 @@ func NewXDSWrappedClient(podName, namespace, localIP 
string, istioAddr xdsCommon
        go newClient.runWatchingCdsUpdateEvent()
 
        // 3. load basic info from istiod and start listening cds
-       if err := 
newClient.startWatchingAllClusterAndLoadLocalHostAddrAndIstioPodIP(); err != 
nil {
+       if err := 
newClient.startWatchingAllClusterAndLoadLocalHostAddrAndIstioPodIP(config.LocalDebugMode);
 err != nil {
                return nil, err
        }
 
@@ -174,8 +188,8 @@ func NewXDSWrappedClient(podName, namespace, localIP 
string, istioAddr xdsCommon
        newClient.interfaceMapHandler = mapping.NewInterfaceMapHandlerImpl(
                newClient.xdsClient,
                defaultIstiodTokenPath,
-               
xdsCommon.NewHostNameOrIPAddr(newClient.istiodPodIP+":"+defaultIstiodDebugPort),
-               newClient.hostAddr)
+               
xdsCommon.NewHostNameOrIPAddr(newClient.istiodPodIP+":"+config.DebugPort),
+               newClient.hostAddr, config.LocalDebugMode)
 
        xdsWrappedClient = newClient
        return newClient, nil
@@ -186,6 +200,11 @@ func (w *WrappedClientImpl) 
GetHostAddrByServiceUniqueKey(serviceUniqueKey strin
        return w.interfaceMapHandler.GetHostAddrMap(serviceUniqueKey)
 }
 
+// GetDubboGoMetadata get all registered metadata of dubbogo
+func (w *WrappedClientImpl) GetDubboGoMetadata() (map[string]string, error) {
+       return w.interfaceMapHandler.GetDubboGoMetadata()
+}
+
 // ChangeInterfaceMap change the map of serviceUniqueKey -> appname, if add is 
true, register, else unregister
 func (w *WrappedClientImpl) ChangeInterfaceMap(serviceUniqueKey string, add 
bool) error {
        if add {
@@ -371,17 +390,19 @@ func (w *WrappedClientImpl) initXDSClient() error {
 // 1. start watching all cluster by cds
 // 2. discovery local pod's hostAddr by cds and eds
 // 3. discovery istiod pod ip by cds and eds
-func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioPodIP() error {
+func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioPodIP(localDebugMode bool) 
error {
        // call watch and refresh istiod debug interface
        foundLocalStopCh := make(chan struct{})
        foundIstiodStopCh := make(chan struct{})
        discoveryFinishedStopCh := make(chan struct{})
        // todo timeout configure
-       timeoutCh := time.After(time.Second * 3)
+       timeoutCh := time.After(w.xdsSniffingTimeout)
        foundLocal := false
        foundIstiod := false
        var cancel1 func()
        var cancel2 func()
+       logger.Infof("[XDS Wrapped Client] Start sniffing with istio hostname = 
%s, localIp = %s",
+               w.istiodAddr.HostnameOrIP, w.localIP)
 
        // todo @(laurence) here, if istiod is unhealthy, here should be 
timeout and tell developer.
        _ = w.xdsClient.WatchCluster("*", func(update resource.ClusterUpdate, 
err error) {
@@ -393,6 +414,7 @@ func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioP
                        w.cdsMapLock.Lock()
                        defer w.cdsMapLock.Unlock()
                        delete(w.cdsMap, update.ClusterName[1:])
+                       logger.Infof("[XDS Wrapped Client] Delete cluster %s", 
update.ClusterName)
                        w.cdsUpdateEventChan <- struct{}{} // send update event
                        return
                }
@@ -404,18 +426,22 @@ func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioP
                if foundLocal && foundIstiod {
                        return
                }
+               logger.Infof("[XDS Wrapped Client] Sniffing with cluster name = 
%s", update.ClusterName)
                // only into here during start sniffing istiod/service prcedure
                cluster := xdsCommon.NewCluster(update.ClusterName)
                if cluster.Addr.HostnameOrIP == w.istiodAddr.HostnameOrIP {
                        // 1. find istiod podIP
                        // todo: When would eds level watch be canceled?
+                       logger.Info("[XDS Wrapped Client] Sniffing get istiod 
cluster")
                        cancel1 = 
w.xdsClient.WatchEndpoints(update.ClusterName, func(endpoint 
resource.EndpointsUpdate, err error) {
                                if foundIstiod {
                                        return
                                }
+                               logger.Infof("[XDS Wrapped Client] Sniffing get 
istiod endpoint = %+v, localities = %+v", endpoint, endpoint.Localities)
                                for _, v := range endpoint.Localities {
                                        for _, e := range v.Endpoints {
                                                w.istiodPodIP = 
xdsCommon.NewHostNameOrIPAddr(e.Address).HostnameOrIP
+                                               logger.Infof("[XDS Wrapped 
Client] Sniffing found istiod podIP = %s", w.istiodPodIP)
                                                foundIstiod = true
                                                close(foundIstiodStopCh)
                                        }
@@ -431,6 +457,7 @@ func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioP
                        }
                        for _, v := range endpoint.Localities {
                                for _, e := range v.Endpoints {
+                                       logger.Infof("[XDS Wrapped Client] 
Sniffing Found eds endpoint = %+v", e)
                                        if 
xdsCommon.NewHostNameOrIPAddr(e.Address).HostnameOrIP == w.localIP {
                                                cluster := 
xdsCommon.NewCluster(update.ClusterName)
                                                w.hostAddr = cluster.Addr
@@ -441,6 +468,17 @@ func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioP
                        }
                })
        })
+
+       if localDebugMode {
+               go func() {
+                       <-foundIstiodStopCh
+                       <-foundLocalStopCh
+                       cancel1()
+                       cancel2()
+               }()
+               return nil
+       }
+
        go func() {
                <-foundIstiodStopCh
                <-foundLocalStopCh
@@ -454,8 +492,10 @@ func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioP
                time.Sleep(time.Second)
                cancel1()
                cancel2()
+               logger.Infof("[XDS Wrapper Client] Sniffing Finished with host 
addr = %s, istiod pod ip = %s", w.hostAddr, w.istiodPodIP)
                return nil
        case <-timeoutCh:
+               logger.Warnf("[XDS Wrapper Client] Sniffing timeout with 
duration = %v", w.xdsSniffingTimeout)
                if cancel1 != nil {
                        cancel1()
                }
@@ -466,7 +506,7 @@ func (w *WrappedClientImpl) 
startWatchingAllClusterAndLoadLocalHostAddrAndIstioP
                case <-foundIstiodStopCh:
                        return DiscoverLocalError
                default:
-                       return DiscoverIstiodPodError
+                       return DiscoverIstiodPodIpError
                }
        }
 }
@@ -528,6 +568,7 @@ type XDSWrapperClient interface {
        UnSubscribe(svcUniqueName string)
        GetRouterConfig(hostAddr string) resource.RouteConfigUpdate
        GetHostAddrByServiceUniqueKey(serviceUniqueKey string) (string, error)
+       GetDubboGoMetadata() (map[string]string, error)
        ChangeInterfaceMap(serviceUniqueKey string, add bool) error
        GetClusterUpdateIgnoreVersion(hostAddr string) resource.ClusterUpdate
        GetHostAddress() xdsCommon.HostAddr
diff --git a/remoting/xds/client_test.go b/remoting/xds/client_test.go
index dea3a9f43..23bd845e8 100644
--- a/remoting/xds/client_test.go
+++ b/remoting/xds/client_test.go
@@ -168,13 +168,18 @@ func testWithDiscoverySuccess(t *testing.T) {
        xdsClientFactoryFunction = func(localIP, podName, namespace string, 
istioAddr common.HostAddr) (client.XDSClient, error) {
                return mockXDSClient, nil
        }
-       xdsWrappedClient, err := NewXDSWrappedClient(podNameFoo, 
localNamespaceFoo, localIPFoo, common.NewHostNameOrIPAddr(istioHostAddrFoo))
+       xdsWrappedClient, err := NewXDSWrappedClient(Config{
+               PodName:   podNameFoo,
+               Namespace: localNamespaceFoo,
+               LocalIP:   localIPFoo,
+               IstioAddr: common.NewHostNameOrIPAddr(istioHostAddrFoo),
+       })
        assert.Nil(t, err)
        assert.NotNil(t, xdsWrappedClient)
 
        // assert eds cancel is called
        assert.Equal(t, int32(2), cancelCalledCounter.Load())
-       // discovery p
+       // discovery istiod pod ip
        assert.Equal(t, istioIPFoo, xdsWrappedClient.GetIstioPodIP())
        address := xdsWrappedClient.GetHostAddress()
        assert.Equal(t, localHostAddrFoo, address.String())
@@ -249,8 +254,13 @@ func testFailedWithIstioCDS(t *testing.T) {
        xdsClientFactoryFunction = func(localIP, podName, namespace string, 
istioAddr common.HostAddr) (client.XDSClient, error) {
                return mockXDSClient, nil
        }
-       xdsWrappedClient, err := NewXDSWrappedClient(podNameFoo, 
localNamespaceFoo, localIPFoo, common.NewHostNameOrIPAddr(istioHostAddrFoo))
-       assert.Equal(t, DiscoverIstiodPodError, err)
+       xdsWrappedClient, err := NewXDSWrappedClient(Config{
+               PodName:   podNameFoo,
+               Namespace: localNamespaceFoo,
+               LocalIP:   localIPFoo,
+               IstioAddr: common.NewHostNameOrIPAddr(istioHostAddrFoo),
+       })
+       assert.Equal(t, DiscoverIstiodPodIpError, err)
        assert.Nil(t, xdsWrappedClient)
        assert.Equal(t, int32(1), cancelCalledCounter.Load())
 }
@@ -324,7 +334,12 @@ func testFailedWithLocalCDS(t *testing.T) {
        xdsClientFactoryFunction = func(localIP, podName, namespace string, 
istioAddr common.HostAddr) (client.XDSClient, error) {
                return mockXDSClient, nil
        }
-       xdsWrappedClient, err := NewXDSWrappedClient(podNameFoo, 
localNamespaceFoo, localIPFoo, common.NewHostNameOrIPAddr(istioHostAddrFoo))
+       xdsWrappedClient, err := NewXDSWrappedClient(Config{
+               PodName:   podNameFoo,
+               Namespace: localNamespaceFoo,
+               LocalIP:   localIPFoo,
+               IstioAddr: common.NewHostNameOrIPAddr(istioHostAddrFoo),
+       })
        assert.Equal(t, DiscoverLocalError, err)
        assert.Nil(t, xdsWrappedClient)
        assert.Equal(t, int32(1), cancelCalledCounter.Load())
@@ -399,8 +414,13 @@ func testFailedWithNoneCDS(t *testing.T) {
        xdsClientFactoryFunction = func(localIP, podName, namespace string, 
istioAddr common.HostAddr) (client.XDSClient, error) {
                return mockXDSClient, nil
        }
-       xdsWrappedClient, err := NewXDSWrappedClient(podNameFoo, 
localNamespaceFoo, localIPFoo, common.NewHostNameOrIPAddr(istioHostAddrFoo))
-       assert.Equal(t, DiscoverIstiodPodError, err)
+       xdsWrappedClient, err := NewXDSWrappedClient(Config{
+               PodName:   podNameFoo,
+               Namespace: localNamespaceFoo,
+               LocalIP:   localIPFoo,
+               IstioAddr: common.NewHostNameOrIPAddr(istioHostAddrFoo),
+       })
+       assert.Equal(t, DiscoverIstiodPodIpError, err)
        assert.Nil(t, xdsWrappedClient)
        assert.Equal(t, int32(0), cancelCalledCounter.Load())
 }
@@ -474,7 +494,12 @@ func testFailedWithLocalEDSFailed(t *testing.T) {
        xdsClientFactoryFunction = func(localIP, podName, namespace string, 
istioAddr common.HostAddr) (client.XDSClient, error) {
                return mockXDSClient, nil
        }
-       xdsWrappedClient, err := NewXDSWrappedClient(podNameFoo, 
localNamespaceFoo, localIPFoo, common.NewHostNameOrIPAddr(istioHostAddrFoo))
+       xdsWrappedClient, err := NewXDSWrappedClient(Config{
+               PodName:   podNameFoo,
+               Namespace: localNamespaceFoo,
+               LocalIP:   localIPFoo,
+               IstioAddr: common.NewHostNameOrIPAddr(istioHostAddrFoo),
+       })
        assert.Equal(t, DiscoverLocalError, err)
        assert.Nil(t, xdsWrappedClient)
        assert.Equal(t, int32(2), cancelCalledCounter.Load())
@@ -549,8 +574,13 @@ func testFailedWithIstioEDSFailed(t *testing.T) {
        xdsClientFactoryFunction = func(localIP, podName, namespace string, 
istioAddr common.HostAddr) (client.XDSClient, error) {
                return mockXDSClient, nil
        }
-       xdsWrappedClient, err := NewXDSWrappedClient(podNameFoo, 
localNamespaceFoo, localIPFoo, common.NewHostNameOrIPAddr(istioHostAddrFoo))
-       assert.Equal(t, DiscoverIstiodPodError, err)
+       xdsWrappedClient, err := NewXDSWrappedClient(Config{
+               PodName:   podNameFoo,
+               Namespace: localNamespaceFoo,
+               LocalIP:   localIPFoo,
+               IstioAddr: common.NewHostNameOrIPAddr(istioHostAddrFoo),
+       })
+       assert.Equal(t, DiscoverIstiodPodIpError, err)
        assert.Nil(t, xdsWrappedClient)
        assert.Equal(t, int32(2), cancelCalledCounter.Load())
 }
@@ -722,7 +752,12 @@ func testSubscribe(t *testing.T) {
        }
 
        xdsWrappedClient = nil
-       xdsWrappedClient, err := NewXDSWrappedClient(podNameFoo, 
localNamespaceFoo, localIPFoo, common.NewHostNameOrIPAddr(istioHostAddrFoo))
+       xdsWrappedClient, err := NewXDSWrappedClient(Config{
+               PodName:   podNameFoo,
+               Namespace: localNamespaceFoo,
+               LocalIP:   localIPFoo,
+               IstioAddr: common.NewHostNameOrIPAddr(istioHostAddrFoo),
+       })
        assert.Nil(t, err)
        assert.NotNil(t, xdsWrappedClient)
 
diff --git a/remoting/xds/error.go b/remoting/xds/config.go
similarity index 74%
copy from remoting/xds/error.go
copy to remoting/xds/config.go
index 84325bc5f..92df233e6 100644
--- a/remoting/xds/error.go
+++ b/remoting/xds/config.go
@@ -18,10 +18,19 @@
 package xds
 
 import (
-       "errors"
+       "time"
 )
 
-var (
-       DiscoverLocalError     = errors.New("Discovery local Pod's host from 
xds, failed please register service with endpoint to k8s ")
-       DiscoverIstiodPodError = errors.New("Discovery istiod Pod's host from 
xds failed, please register service with endpoint to k8s ")
+import (
+       xdsCommon "dubbo.apache.org/dubbo-go/v3/remoting/xds/common"
 )
+
+type Config struct {
+       PodName         string
+       Namespace       string
+       IstioAddr       xdsCommon.HostAddr
+       DebugPort       string
+       LocalIP         string
+       LocalDebugMode  bool
+       SniffingTimeout time.Duration
+}
diff --git a/remoting/xds/error.go b/remoting/xds/error.go
index 84325bc5f..2711cf7a7 100644
--- a/remoting/xds/error.go
+++ b/remoting/xds/error.go
@@ -22,6 +22,6 @@ import (
 )
 
 var (
-       DiscoverLocalError     = errors.New("Discovery local Pod's host from 
xds, failed please register service with endpoint to k8s ")
-       DiscoverIstiodPodError = errors.New("Discovery istiod Pod's host from 
xds failed, please register service with endpoint to k8s ")
+       DiscoverLocalError       = errors.New("Discovery local Pod's host from 
xds, failed please register service with endpoint to k8s ")
+       DiscoverIstiodPodIpError = errors.New("Discovery istiod Pod's ip from 
xds failed, please register service with endpoint to k8s ")
 )
diff --git a/remoting/xds/mapping/handler.go b/remoting/xds/mapping/handler.go
index b20431787..36489a91e 100644
--- a/remoting/xds/mapping/handler.go
+++ b/remoting/xds/mapping/handler.go
@@ -28,6 +28,8 @@ import (
 
 import (
        structpb "github.com/golang/protobuf/ptypes/struct"
+
+       perrors "github.com/pkg/errors"
 )
 
 import (
@@ -62,6 +64,7 @@ type InterfaceMapHandlerImpl struct {
        */
        interfaceNameHostAddrMap     map[string]string
        interfaceNameHostAddrMapLock sync.RWMutex
+       localDebugMode               bool
 }
 
 func (i *InterfaceMapHandlerImpl) UnRegister(serviceUniqueKey string) error {
@@ -78,6 +81,10 @@ func (i *InterfaceMapHandlerImpl) Register(serviceUniqueKey 
string) error {
        return i.xdsClient.SetMetadata(i.interfaceAppNameMap2DubboGoMetadata())
 }
 
+func (i *InterfaceMapHandlerImpl) GetDubboGoMetadata() (map[string]string, 
error) {
+       return i.getServiceUniqueKeyHostAddrMapFromPilot()
+}
+
 func (i *InterfaceMapHandlerImpl) GetHostAddrMap(serviceUniqueKey string) 
(string, error) {
        i.interfaceNameHostAddrMapLock.RLock()
        if hostAddr, ok := i.interfaceNameHostAddrMap[serviceUniqueKey]; ok {
@@ -86,6 +93,8 @@ func (i *InterfaceMapHandlerImpl) 
GetHostAddrMap(serviceUniqueKey string) (strin
        }
        i.interfaceNameHostAddrMapLock.RUnlock()
 
+       retryCount := 0
+       maxRetries := 30
        for {
                if interfaceHostAddrMap, err := 
i.getServiceUniqueKeyHostAddrMapFromPilot(); err != nil {
                        return "", err
@@ -95,8 +104,14 @@ func (i *InterfaceMapHandlerImpl) 
GetHostAddrMap(serviceUniqueKey string) (strin
                        i.interfaceNameHostAddrMapLock.Unlock()
                        hostName, ok := interfaceHostAddrMap[serviceUniqueKey]
                        if !ok {
-                               logger.Infof("[XDS Wrapped Client] Try getting 
interface %s 's host from istio %d:8080\n", serviceUniqueKey, i.istioDebugAddr)
+                               logger.Infof("[XDS Wrapped Client] Try getting 
interface %s 's host from istio %s:8080\n", serviceUniqueKey, i.istioDebugAddr)
                                time.Sleep(time.Millisecond * 100)
+                               retryCount++
+                               if retryCount > maxRetries {
+                                       err := perrors.Errorf("[XDS Wrapped 
Client] Try getting interface %s 's host from istio %s:8080 failed. Please 
check if provider's service resource is deployed correctly.\n", 
serviceUniqueKey, i.istioDebugAddr)
+                                       logger.Error(err)
+                                       return "", err
+                               }
                                continue
                        }
                        return hostName, nil
@@ -108,11 +123,13 @@ func (i *InterfaceMapHandlerImpl) 
GetHostAddrMap(serviceUniqueKey string) (strin
 // 'dubbo-go-app.default.svc.cluster.local:20000'
 func (i *InterfaceMapHandlerImpl) getServiceUniqueKeyHostAddrMapFromPilot() 
(map[string]string, error) {
        req, _ := http.NewRequest(http.MethodGet, 
fmt.Sprintf("http://%s/debug/adsz";, i.istioDebugAddr.String()), nil)
-       token, err := ioutil.ReadFile(i.istioTokenPath)
-       if err != nil {
-               return nil, err
+       if !i.localDebugMode {
+               token, err := ioutil.ReadFile(i.istioTokenPath)
+               if err != nil {
+                       return nil, err
+               }
+               req.Header.Add(authorizationHeader, 
istiodTokenPrefix+string(token))
        }
-       req.Header.Add(authorizationHeader, istiodTokenPrefix+string(token))
        rsp, err := http.DefaultClient.Do(req)
        if err != nil {
                logger.Infof("[XDS Wrapped Client] Try getting interface host 
map from istio IP %s with error %s\n",
@@ -138,7 +155,7 @@ func (i *InterfaceMapHandlerImpl) 
interfaceAppNameMap2DubboGoMetadata() *structp
        return GetDubboGoMetadata(string(data))
 }
 
-func NewInterfaceMapHandlerImpl(xdsClient client.XDSClient, istioTokenPath 
string, istioDebugAddr, hostAddr common.HostAddr) InterfaceMapHandler {
+func NewInterfaceMapHandlerImpl(xdsClient client.XDSClient, istioTokenPath 
string, istioDebugAddr, hostAddr common.HostAddr, localDebugMode bool) 
InterfaceMapHandler {
        return &InterfaceMapHandlerImpl{
                xdsClient:                xdsClient,
                interfaceAppNameMap:      map[string]string{},
@@ -146,6 +163,7 @@ func NewInterfaceMapHandlerImpl(xdsClient client.XDSClient, 
istioTokenPath strin
                istioDebugAddr:           istioDebugAddr,
                hostAddr:                 hostAddr,
                istioTokenPath:           istioTokenPath,
+               localDebugMode:           localDebugMode,
        }
 }
 
@@ -153,4 +171,5 @@ type InterfaceMapHandler interface {
        Register(string) error
        UnRegister(string) error
        GetHostAddrMap(string) (string, error)
+       GetDubboGoMetadata() (map[string]string, error)
 }
diff --git a/remoting/xds/mapping/handler_test.go 
b/remoting/xds/mapping/handler_test.go
index 2db03511f..9e1a0d8c5 100644
--- a/remoting/xds/mapping/handler_test.go
+++ b/remoting/xds/mapping/handler_test.go
@@ -53,7 +53,7 @@ const (
 
 func TestNewInterfaceMapHandler(t *testing.T) {
        mockXDSClient := &mocks.XDSClient{}
-       interfaceMapHandler := NewInterfaceMapHandlerImpl(mockXDSClient, 
istioTokenPathFoo, common.NewHostNameOrIPAddr(istiodDebugAddrStrFoo), 
common.NewHostNameOrIPAddr(localPodServiceAddr))
+       interfaceMapHandler := NewInterfaceMapHandlerImpl(mockXDSClient, 
istioTokenPathFoo, common.NewHostNameOrIPAddr(istiodDebugAddrStrFoo), 
common.NewHostNameOrIPAddr(localPodServiceAddr), false)
        assert.NotNil(t, interfaceMapHandler)
 }
 
@@ -61,7 +61,7 @@ func TestInterfaceMapHandlerRegisterAndUnregister(t 
*testing.T) {
        mockXDSClient := &mocks.XDSClient{}
        mockXDSClient.On("SetMetadata", 
mock.AnythingOfType("*structpb.Struct")).Return(nil)
 
-       interfaceMapHandler := NewInterfaceMapHandlerImpl(mockXDSClient, 
istioTokenPathFoo, common.NewHostNameOrIPAddr(istiodDebugAddrStrFoo), 
common.NewHostNameOrIPAddr(localPodServiceAddr))
+       interfaceMapHandler := NewInterfaceMapHandlerImpl(mockXDSClient, 
istioTokenPathFoo, common.NewHostNameOrIPAddr(istiodDebugAddrStrFoo), 
common.NewHostNameOrIPAddr(localPodServiceAddr), false)
 
        assert.Nil(t, interfaceMapHandler.Register(serviceKey1))
        assert.Nil(t, interfaceMapHandler.Register(serviceKey2))
@@ -76,7 +76,7 @@ func TestInterfaceMapHandlerRegisterAndUnregister(t 
*testing.T) {
 
 func TestGetServiceUniqueKeyHostAddrMapFromPilot(t *testing.T) {
        mockXDSClient := &mocks.XDSClient{}
-       interfaceMapHandler := NewInterfaceMapHandlerImpl(mockXDSClient, 
istioTokenPathFoo, common.NewHostNameOrIPAddr(istiodDebugAddrStrFoo), 
common.NewHostNameOrIPAddr(localPodServiceAddr))
+       interfaceMapHandler := NewInterfaceMapHandlerImpl(mockXDSClient, 
istioTokenPathFoo, common.NewHostNameOrIPAddr(istiodDebugAddrStrFoo), 
common.NewHostNameOrIPAddr(localPodServiceAddr), false)
        assert.Nil(t, generateMockToken())
 
        // 1. start mock http server
diff --git a/remoting/xds/mapping/mocks/InterfaceMapHandler.go 
b/remoting/xds/mapping/mocks/InterfaceMapHandler.go
index fd2247550..c98a89b6b 100644
--- a/remoting/xds/mapping/mocks/InterfaceMapHandler.go
+++ b/remoting/xds/mapping/mocks/InterfaceMapHandler.go
@@ -76,3 +76,24 @@ func (_m *InterfaceMapHandler) UnRegister(_a0 string) error {
 
        return r0
 }
+
+// GetDubboGoMetadata provides a mock function
+func (_m *InterfaceMapHandler) GetDubboGoMetadata() (map[string]string, error) 
{
+       ret := _m.Called()
+
+       var r0 map[string]string
+       if rf, ok := ret.Get(0).(func() map[string]string); ok {
+               r0 = rf()
+       } else {
+               r0 = ret.Get(0).(map[string]string)
+       }
+
+       var r1 error
+       if rf, ok := ret.Get(1).(func() error); ok {
+               r1 = rf()
+       } else {
+               r1 = ret.Error(1)
+       }
+
+       return r0, r1
+}
diff --git a/remoting/xds/mocks/client.go b/remoting/xds/mocks/client.go
index 02c7f93b9..65f4b305a 100644
--- a/remoting/xds/mocks/client.go
+++ b/remoting/xds/mocks/client.go
@@ -33,6 +33,11 @@ type WrappedClientMock struct {
        mock.Mock
 }
 
+func (m *WrappedClientMock) GetDubboGoMetadata() (map[string]string, error) {
+       args := m.Called()
+       return args.Get(0).(map[string]string), args.Error(1)
+}
+
 func (m *WrappedClientMock) Subscribe(svcUniqueName, interfaceName, hostAddr 
string, lst registry.NotifyListener) error {
        args := m.Called(svcUniqueName, interfaceName, hostAddr, lst)
        return args.Error(0)
diff --git a/test/xds/main.go b/test/xds/main.go
deleted file mode 100644
index 85b661f32..000000000
--- a/test/xds/main.go
+++ /dev/null
@@ -1,121 +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 main
-
-import (
-       "fmt"
-)
-
-import (
-       v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
-
-       structpb "github.com/golang/protobuf/ptypes/struct"
-
-       "google.golang.org/grpc"
-       "google.golang.org/grpc/credentials/insecure"
-)
-
-import (
-       "dubbo.apache.org/dubbo-go/v3/xds/client"
-       "dubbo.apache.org/dubbo-go/v3/xds/client/bootstrap"
-       _ "dubbo.apache.org/dubbo-go/v3/xds/client/controller/version/v2"
-       _ "dubbo.apache.org/dubbo-go/v3/xds/client/controller/version/v3"
-       "dubbo.apache.org/dubbo-go/v3/xds/client/resource"
-       "dubbo.apache.org/dubbo-go/v3/xds/client/resource/version"
-)
-
-const (
-       gRPCUserAgentName               = "gRPC Go"
-       clientFeatureNoOverprovisioning = 
"envoy.lb.does_not_support_overprovisioning"
-)
-
-// ATTENTION! export GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT=false
-func main() {
-       v3NodeProto := &v3corepb.Node{
-               Id:                   
"sidecar~172.1.1.1~sleep-55b5877479-rwcct.default~default.svc.cluster.local",
-               UserAgentName:        gRPCUserAgentName,
-               Cluster:              "testCluster",
-               UserAgentVersionType: 
&v3corepb.Node_UserAgentVersion{UserAgentVersion: "1.45.0"},
-               ClientFeatures:       []string{clientFeatureNoOverprovisioning},
-               Metadata: &structpb.Struct{
-                       Fields: map[string]*structpb.Value{
-                               "CLUSTER_ID": {
-                                       Kind: 
&structpb.Value_StringValue{StringValue: "Kubernetes"},
-                               },
-                               "LABELS": {
-                                       Kind: 
&structpb.Value_StructValue{StructValue: &structpb.Struct{
-                                               Fields: 
map[string]*structpb.Value{
-                                                       "label1": {
-                                                               Kind: 
&structpb.Value_StringValue{StringValue: "val1"},
-                                                       },
-                                                       "label2": {
-                                                               Kind: 
&structpb.Value_StringValue{StringValue: "val2"},
-                                                       },
-                                               },
-                                       }},
-                               },
-                       },
-               },
-       }
-
-       nonNilCredsConfigV2 := &bootstrap.Config{
-               XDSServer: &bootstrap.ServerConfig{
-                       ServerURI: "localhost:15010",
-                       Creds:     
grpc.WithTransportCredentials(insecure.NewCredentials()),
-                       //CredsType: "google_default",
-                       TransportAPI: version.TransportV3,
-                       NodeProto:    v3NodeProto,
-               },
-               ClientDefaultListenerResourceNameTemplate: "%s",
-       }
-
-       xdsClient, err := client.NewWithConfig(nonNilCredsConfigV2)
-       if err != nil {
-               panic(err)
-       }
-
-       //clusterName := 
"outbound|20000||dubbo-go-app.default.svc.cluster.local" //
-       //clusterName := "outbound|8848||nacos.default.svc.cluster.local"
-       //endpointClusterMap := sync.Map{}
-       //xdsClient.WatchCluster("*", func(update resource.ClusterUpdate, err 
error) {
-       //      xdsClient.WatchEndpoints(update.ClusterName, func(endpoint 
resource.EndpointsUpdate, err error) {
-       //              for _, v := range endpoint.Localities {
-       //                      for _, e := range v.Endpoints {
-       //                              endpointClusterMap.Store(e.Address, 
update.ClusterName)
-       //                      }
-       //              }
-       //      })
-       //})
-
-       //
-       
//xdsClient.WatchEndpoints("outbound|15010||istiod.istio-system.svc.cluster.local",
 func(update resource.EndpointsUpdate, err error) {
-       //      fmt.Printf("%+v\n err = %s", update, err)
-       //})
-
-       xdsClient.WatchCluster("*", func(update resource.ClusterUpdate, err 
error) {
-               fmt.Println(update)
-       })
-
-       //xdsClient.WatchCluster("*", func(update resource.ClusterUpdate, err 
error) {
-       //      fmt.Printf("%+v\n err = %s", update, err)
-       //
-       //})
-       //
-
-       select {}
-}

Reply via email to