You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by la...@apache.org on 2021/08/30 03:58:51 UTC

[dubbo-go] branch hsf-go-dependency created (now 347fadf)

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

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


      at 347fadf  hsf-go-dependecy branch init

This branch includes the following new commits:

     new 347fadf  hsf-go-dependecy branch init

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


[dubbo-go] 01/01: hsf-go-dependecy branch init

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

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

commit 347fadf50abc6b57e12051b5774190428ab909b5
Author: LaurenceLiZhixin <38...@qq.com>
AuthorDate: Mon Aug 30 11:58:03 2021 +0800

    hsf-go-dependecy branch init
---
 common/constant/default.go            |   2 +-
 common/proxy/proxy.go                 |  30 ++++---
 common/proxy/proxy_factory/default.go |   8 +-
 common/rpc_service.go                 |  41 +++++++---
 common/rpc_service_test.go            |  33 ++++++++
 config/config_loader.go               |   7 +-
 config/metadata_report_config.go      |   2 +-
 config/service.go                     |   6 +-
 metadata/definition/definition.go     | 147 ++++++++++++++++++++++++++++++----
 metadata/service/inmemory/service.go  |   1 +
 metadata/service/remote/service.go    |  16 ----
 metadata/service/service.go           |   4 +-
 registry/protocol/protocol.go         |  40 ++++-----
 13 files changed, 249 insertions(+), 88 deletions(-)

diff --git a/common/constant/default.go b/common/constant/default.go
index da8cd20..1596f9f 100644
--- a/common/constant/default.go
+++ b/common/constant/default.go
@@ -51,7 +51,7 @@ const (
 const (
 	DEFAULT_KEY               = "default"
 	PREFIX_DEFAULT_KEY        = "default."
-	DEFAULT_SERVICE_FILTERS   = "echo,token,accesslog,tps,generic_service,execute,pshutdown"
+	DEFAULT_SERVICE_FILTERS   = "token,accesslog,tps,generic_service,execute,pshutdown"
 	DEFAULT_REFERENCE_FILTERS = "cshutdown"
 	GENERIC_REFERENCE_FILTERS = "generic"
 	GENERIC                   = "$invoke"
diff --git a/common/proxy/proxy.go b/common/proxy/proxy.go
index fd34810..f35e7ab 100644
--- a/common/proxy/proxy.go
+++ b/common/proxy/proxy.go
@@ -129,24 +129,25 @@ func DefaultProxyImplementFunc(p *Proxy, v common.RPCService) {
 	makeDubboCallProxy := func(methodName string, outs []reflect.Type) func(in []reflect.Value) []reflect.Value {
 		return func(in []reflect.Value) []reflect.Value {
 			var (
-				err    error
-				inv    *invocation_impl.RPCInvocation
-				inIArr []interface{}
-				inVArr []reflect.Value
-				reply  reflect.Value
+				err            error
+				inv            *invocation_impl.RPCInvocation
+				inIArr         []interface{}
+				inVArr         []reflect.Value
+				reply          reflect.Value
+				replyEmptyFlag bool
 			)
 			if methodName == "Echo" {
 				methodName = "$echo"
 			}
 
-			if len(outs) == 2 {
+			if len(outs) == 2 { // return (reply, error)
 				if outs[0].Kind() == reflect.Ptr {
 					reply = reflect.New(outs[0].Elem())
 				} else {
 					reply = reflect.New(outs[0])
 				}
-			} else {
-				reply = valueOf
+			} else { // only return error
+				replyEmptyFlag = true
 			}
 
 			start := 0
@@ -160,10 +161,6 @@ func DefaultProxyImplementFunc(p *Proxy, v common.RPCService) {
 					}
 					start += 1
 				}
-				if len(outs) == 1 && in[end-1].Type().Kind() == reflect.Ptr {
-					end -= 1
-					reply = in[len(in)-1]
-				}
 			}
 
 			if end-start <= 0 {
@@ -184,8 +181,11 @@ func DefaultProxyImplementFunc(p *Proxy, v common.RPCService) {
 			}
 
 			inv = invocation_impl.NewRPCInvocationWithOptions(invocation_impl.WithMethodName(methodName),
-				invocation_impl.WithArguments(inIArr), invocation_impl.WithReply(reply.Interface()),
+				invocation_impl.WithArguments(inIArr),
 				invocation_impl.WithCallBack(p.callback), invocation_impl.WithParameterValues(inVArr))
+			if !replyEmptyFlag {
+				inv.SetReply(reply.Interface())
+			}
 
 			for k, value := range p.attachments {
 				inv.SetAttachments(k, value)
@@ -215,8 +215,6 @@ func DefaultProxyImplementFunc(p *Proxy, v common.RPCService) {
 				} else {
 					logger.Warnf("result err: %v", err)
 				}
-			} else {
-				logger.Debugf("[makeDubboCallProxy] result: %v, err: %v", result.Result(), err)
 			}
 			if len(outs) == 1 {
 				return []reflect.Value{reflect.ValueOf(&err).Elem()}
@@ -251,7 +249,7 @@ func DefaultProxyImplementFunc(p *Proxy, v common.RPCService) {
 				continue
 			}
 
-			var funcOuts = make([]reflect.Type, outNum)
+			funcOuts := make([]reflect.Type, outNum)
 			for i := 0; i < outNum; i++ {
 				funcOuts[i] = t.Type.Out(i)
 			}
diff --git a/common/proxy/proxy_factory/default.go b/common/proxy/proxy_factory/default.go
index dd8ce02..6a070bc 100644
--- a/common/proxy/proxy_factory/default.go
+++ b/common/proxy/proxy_factory/default.go
@@ -137,10 +137,10 @@ func (pi *ProxyInvoker) Invoke(ctx context.Context, invocation protocol.Invocati
 
 	// prepare replyv
 	var replyv reflect.Value
-	if method.ReplyType() == nil && len(method.ArgsType()) > 0 {
-		replyv = reflect.New(method.ArgsType()[len(method.ArgsType())-1].Elem())
-		in = append(in, replyv)
-	}
+	//if method.ReplyType() == nil && len(method.ArgsType()) > 0 {
+	//	replyv = reflect.New(method.ArgsType()[len(method.ArgsType())-1].Elem())
+	//	in = append(in, replyv)
+	//}
 
 	returnValues := method.Method().Func.Call(in)
 
diff --git a/common/rpc_service.go b/common/rpc_service.go
index f739e31..dc10e2a 100644
--- a/common/rpc_service.go
+++ b/common/rpc_service.go
@@ -34,14 +34,43 @@ import (
 	"github.com/apache/dubbo-go/common/logger"
 )
 
-// RPCService
+// RPCService the type alias of interface{}
+type RPCService = interface{}
+
+// ReferencedRPCService
 // rpc service interface
-type RPCService interface {
+type ReferencedRPCService interface {
 	// Reference:
 	// rpc service id or reference id
 	Reference() string
 }
 
+// GetReference return the reference id of the service.
+// If the service implemented the ReferencedRPCService interface,
+// it will call the Reference method. If not, it will
+// return the struct name as the reference id.
+func GetReference(service RPCService) string {
+	if s, ok := service.(ReferencedRPCService); ok {
+		return s.Reference()
+	}
+
+	ref := ""
+	sType := reflect.TypeOf(service)
+	kind := sType.Kind()
+	switch kind {
+	case reflect.Struct:
+		ref = sType.Name()
+	case reflect.Ptr:
+		sName := sType.Elem().Name()
+		if sName != "" {
+			ref = sName
+		} else {
+			ref = sType.Elem().Field(0).Name
+		}
+	}
+	return ref
+}
+
 // AsyncCallbackService callback interface for async
 type AsyncCallbackService interface {
 	// Callback: callback
@@ -358,12 +387,6 @@ func suiteMethod(method reflect.Method) *MethodType {
 		return nil
 	}
 
-	if outNum != 1 && outNum != 2 {
-		logger.Warnf("method %s of mtype %v has wrong number of in out parameters %d; needs exactly 1/2",
-			mname, mtype.String(), outNum)
-		return nil
-	}
-
 	// The latest return type of the method must be error.
 	if returnType := mtype.Out(outNum - 1); returnType != typeOfError {
 		if mname != METHOD_MAPPER {
@@ -372,7 +395,7 @@ func suiteMethod(method reflect.Method) *MethodType {
 		return nil
 	}
 
-	// replyType
+	// todo, for multi reply condition, replyType is empty
 	if outNum == 2 {
 		replyType = mtype.Out(0)
 		if !isExportedOrBuiltinType(replyType) {
diff --git a/common/rpc_service_test.go b/common/rpc_service_test.go
index e8bd393..5c04c9e 100644
--- a/common/rpc_service_test.go
+++ b/common/rpc_service_test.go
@@ -213,3 +213,36 @@ func TestSuiteMethod(t *testing.T) {
 	methodType = suiteMethod(method)
 	assert.Nil(t, methodType)
 }
+
+type ServiceWithoutRef struct{}
+
+func TestGetReference(t *testing.T) {
+	s0 := &TestService{}
+	ref0 := GetReference(s0)
+	assert.Equal(t, referenceTestPath, ref0)
+
+	//s1 := TestService{}
+	//ref1 := GetReference(s1)
+	//assert.Equal(t, referenceTestPath, ref1)
+
+	s2 := &struct {
+		TestService
+	}{}
+	ref2 := GetReference(s2)
+	assert.Equal(t, referenceTestPath, ref2)
+
+	expectedReference := "ServiceWithoutRef"
+	s3 := &ServiceWithoutRef{}
+	ref3 := GetReference(s3)
+	assert.Equal(t, expectedReference, ref3)
+
+	s4 := ServiceWithoutRef{}
+	ref4 := GetReference(s4)
+	assert.Equal(t, expectedReference, ref4)
+
+	s5 := &struct {
+		ServiceWithoutRef
+	}{}
+	ref5 := GetReference(s5)
+	assert.Equal(t, expectedReference, ref5)
+}
diff --git a/config/config_loader.go b/config/config_loader.go
index 14caf2c..6f7d6fa 100644
--- a/config/config_loader.go
+++ b/config/config_loader.go
@@ -132,7 +132,7 @@ func loadConsumerConfig() {
 	}
 
 	// start the metadata report if config set
-	if err := startMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
+	if err := StartMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
 		logger.Errorf("Provider starts metadata report error, and the error is {%#v}", err)
 		return
 	}
@@ -220,7 +220,7 @@ func loadProviderConfig() {
 	}
 
 	// start the metadata report if config set
-	if err := startMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
+	if err := StartMetadataReport(GetApplicationConfig().MetadataType, GetBaseConfig().MetadataReportConfig); err != nil {
 		logger.Errorf("Provider starts metadata report error, and the error is {%#v}", err)
 		return
 	}
@@ -375,7 +375,8 @@ func GetRPCService(name string) common.RPCService {
 
 // RPCService create rpc service for consumer
 func RPCService(service common.RPCService) {
-	consumerConfig.References[service.Reference()].Implement(service)
+	ref := common.GetReference(service)
+	consumerConfig.References[ref].Implement(service)
 }
 
 // GetMetricConfig find the MetricConfig
diff --git a/config/metadata_report_config.go b/config/metadata_report_config.go
index 6fb3fd2..602ba56 100644
--- a/config/metadata_report_config.go
+++ b/config/metadata_report_config.go
@@ -92,7 +92,7 @@ func (c *MetadataReportConfig) IsValid() bool {
 }
 
 // StartMetadataReport: The entry of metadata report start
-func startMetadataReport(metadataType string, metadataReportConfig *MetadataReportConfig) error {
+func StartMetadataReport(metadataType string, metadataReportConfig *MetadataReportConfig) error {
 	if metadataReportConfig == nil || !metadataReportConfig.IsValid() {
 		return nil
 	}
diff --git a/config/service.go b/config/service.go
index 6deff3b..3eac7d3 100644
--- a/config/service.go
+++ b/config/service.go
@@ -28,12 +28,14 @@ var (
 
 // SetConsumerService is called by init() of implement of RPCService
 func SetConsumerService(service common.RPCService) {
-	conServices[service.Reference()] = service
+	ref := common.GetReference(service)
+	conServices[ref] = service
 }
 
 // SetProviderService is called by init() of implement of RPCService
 func SetProviderService(service common.RPCService) {
-	proServices[service.Reference()] = service
+	ref := common.GetReference(service)
+	proServices[ref] = service
 }
 
 // GetConsumerService gets ConsumerService by @name
diff --git a/metadata/definition/definition.go b/metadata/definition/definition.go
index a032313..015bdc0 100644
--- a/metadata/definition/definition.go
+++ b/metadata/definition/definition.go
@@ -21,7 +21,13 @@ import (
 	"bytes"
 	"encoding/json"
 	"fmt"
+	"reflect"
 	"strings"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
 )
 
 import (
@@ -36,10 +42,10 @@ type ServiceDefiner interface {
 
 // ServiceDefinition is the describer of service definition
 type ServiceDefinition struct {
-	CanonicalName string
-	CodeSource    string
-	Methods       []MethodDefinition
-	Types         []TypeDefinition
+	CanonicalName string             `json:"canonicalName"`
+	CodeSource    string             `json:"codeSource"`
+	Methods       []MethodDefinition `json:"methods"`
+	Types         []TypeDefinition   `json:"types"`
 }
 
 // ToBytes convert ServiceDefinition to json string
@@ -76,20 +82,20 @@ type FullServiceDefinition struct {
 
 // MethodDefinition is the describer of method definition
 type MethodDefinition struct {
-	Name           string
-	ParameterTypes []string
-	ReturnType     string
-	Parameters     []TypeDefinition
+	Name           string           `json:"name"`
+	ParameterTypes []string         `json:"parameterTypes"`
+	ReturnType     string           `json:"returnType"`
+	Parameters     []TypeDefinition `json:"parameters"`
 }
 
 // TypeDefinition is the describer of type definition
 type TypeDefinition struct {
-	Id              string
-	Type            string
-	Items           []TypeDefinition
-	Enums           []string
-	Properties      map[string]TypeDefinition
-	TypeBuilderName string
+	Id              string                    `json:"id"`
+	Type            string                    `json:"type"`
+	Items           []TypeDefinition          `json:"items"`
+	Enums           []string                  `json:"enums"`
+	Properties      map[string]TypeDefinition `json:"properties"`
+	TypeBuilderName string                    `json:"typeBuilderName"`
 }
 
 // BuildServiceDefinition can build service definition which will be used to describe a service
@@ -99,15 +105,26 @@ func BuildServiceDefinition(service common.Service, url *common.URL) *ServiceDef
 
 	for k, m := range service.Method() {
 		var paramTypes []string
+		var param string
 		if len(m.ArgsType()) > 0 {
 			for _, t := range m.ArgsType() {
-				paramTypes = append(paramTypes, t.Kind().String())
+				if t.Kind() == reflect.Ptr {
+					param = getArgType(reflect.New(t).Interface())
+				} else {
+					param = t.Kind().String()
+				}
+				paramTypes = append(paramTypes, param)
 			}
 		}
 
 		var returnType string
+
 		if m.ReplyType() != nil {
-			returnType = m.ReplyType().Kind().String()
+			if m.ReplyType().Kind() == reflect.Ptr {
+				returnType = getArgType(reflect.New(m.ReplyType()).Interface())
+			} else {
+				returnType = m.ReplyType().Kind().String()
+			}
 		}
 
 		methodD := MethodDefinition{
@@ -135,3 +152,101 @@ func ServiceDescriperBuild(serviceName string, group string, version string) str
 	}
 	return buf.String()
 }
+
+func getArgType(v interface{}) string {
+	if v == nil {
+		return "V"
+	}
+
+	v = reflect.ValueOf(v).Elem().Interface()
+
+	switch v.(type) {
+	// Serialized tags for base types
+	case nil:
+		return "V"
+	case bool:
+		return "Z"
+	case []bool:
+		return "[Z"
+	case byte:
+		return "B"
+	case []byte:
+		return "[B"
+	case int8:
+		return "B"
+	case []int8:
+		return "[B"
+	case int16:
+		return "S"
+	case []int16:
+		return "[S"
+	case uint16: // Equivalent to Char of Java
+		return "C"
+	case []uint16:
+		return "[C"
+	// case rune:
+	//	return "C"
+	case int:
+		return "J"
+	case []int:
+		return "[J"
+	case int32:
+		return "I"
+	case []int32:
+		return "[I"
+	case int64:
+		return "J"
+	case []int64:
+		return "[J"
+	case time.Time:
+		return "java.util.Date"
+	case []time.Time:
+		return "[Ljava.util.Date"
+	case float32:
+		return "F"
+	case []float32:
+		return "[F"
+	case float64:
+		return "D"
+	case []float64:
+		return "[D"
+	case string:
+		return "java.lang.String"
+	case []string:
+		return "[Ljava.lang.String;"
+	case []hessian.Object:
+		return "[Ljava.lang.Object;"
+	case map[interface{}]interface{}:
+		// return  "java.util.HashMap"
+		return "java.util.Map"
+	case hessian.POJO:
+		return v.(hessian.POJO).JavaClassName()
+	//  Serialized tags for complex types
+	default:
+		t := reflect.TypeOf(v)
+		if reflect.Ptr == t.Kind() {
+			t = reflect.TypeOf(reflect.ValueOf(v).Elem())
+		}
+		switch t.Kind() {
+		case reflect.Struct:
+			v, ok := v.(hessian.POJO)
+			if ok {
+				return v.JavaClassName()
+			}
+			return "java.lang.Object"
+		case reflect.Slice, reflect.Array:
+			if t.Elem().Kind() == reflect.Struct {
+				return "[Ljava.lang.Object;"
+			}
+			// return "java.util.ArrayList"
+			return "java.util.List"
+		case reflect.Map: // Enter here, map may be map[string]int
+			return "java.util.Map"
+		default:
+			return ""
+		}
+	}
+
+	// unreachable
+	// return "java.lang.RuntimeException"
+}
diff --git a/metadata/service/inmemory/service.go b/metadata/service/inmemory/service.go
index 8da78c3..36eefe0 100644
--- a/metadata/service/inmemory/service.go
+++ b/metadata/service/inmemory/service.go
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package inmemory
 
 import (
diff --git a/metadata/service/remote/service.go b/metadata/service/remote/service.go
index e2a7a64..302ae32 100644
--- a/metadata/service/remote/service.go
+++ b/metadata/service/remote/service.go
@@ -132,22 +132,6 @@ func (mts *MetadataService) PublishServiceDefinition(url *common.URL) error {
 			return nil
 		}
 		logger.Errorf("publishProvider interfaceName is empty . providerUrl:%v ", url)
-	} else {
-		params := make(map[string]string, len(url.GetParams()))
-		url.RangeParams(func(key, value string) bool {
-			params[key] = value
-			return true
-		})
-		id := &identifier.MetadataIdentifier{
-			BaseMetadataIdentifier: identifier.BaseMetadataIdentifier{
-				ServiceInterface: interfaceName,
-				Version:          url.GetParam(constant.VERSION_KEY, ""),
-				Group:            url.GetParam(constant.GROUP_KEY, constant.DUBBO),
-				Side:             url.GetParam(constant.SIDE_KEY, "consumer"),
-			},
-		}
-		mts.delegateReport.StoreConsumerMetadata(id, params)
-		return nil
 	}
 
 	return nil
diff --git a/metadata/service/service.go b/metadata/service/service.go
index 1d90f8a..f7a39bd 100644
--- a/metadata/service/service.go
+++ b/metadata/service/service.go
@@ -30,7 +30,7 @@ import (
 // MetadataService is used to define meta data related behaviors
 // usually the implementation should be singleton
 type MetadataService interface {
-	common.RPCService
+	common.ReferencedRPCService
 	// ServiceName will get the service's name in meta service , which is application name
 	ServiceName() (string, error)
 	// ExportURL will store the exported url in metadata
@@ -86,7 +86,7 @@ func (mts *BaseMetadataService) ServiceName() (string, error) {
 	return mts.serviceName, nil
 }
 
-// Version will return the version of metadata service
+// Reference will return the reference id of metadata service
 func (mts *BaseMetadataService) Reference() string {
 	return constant.SIMPLE_METADATA_SERVICE_NAME
 }
diff --git a/registry/protocol/protocol.go b/registry/protocol/protocol.go
index e50e2b9..0f37ac7 100644
--- a/registry/protocol/protocol.go
+++ b/registry/protocol/protocol.go
@@ -186,20 +186,22 @@ func (proto *registryProtocol) Export(invoker protocol.Invoker) protocol.Exporte
 	serviceConfigurationListener.OverrideUrl(providerUrl)
 
 	var reg registry.Registry
-	if regI, loaded := proto.registries.Load(registryUrl.Key()); !loaded {
-		reg = getRegistry(registryUrl)
-		proto.registries.Store(registryUrl.Key(), reg)
-		logger.Infof("Export proto:%p registries address:%p", proto, proto.registries)
-	} else {
-		reg = regI.(registry.Registry)
-	}
 
-	registeredProviderUrl := getUrlToRegistry(providerUrl, registryUrl)
-	err := reg.Register(registeredProviderUrl)
-	if err != nil {
-		logger.Errorf("provider service %v register registry %v error, error message is %s",
-			providerUrl.Key(), registryUrl.Key(), err.Error())
-		return nil
+	if registryUrl.Protocol != "" {
+		if regI, loaded := proto.registries.Load(registryUrl.Key()); !loaded {
+			reg = getRegistry(registryUrl)
+			proto.registries.Store(registryUrl.Key(), reg)
+			logger.Infof("Export proto:%p registries address:%p", proto, proto.registries)
+		} else {
+			reg = regI.(registry.Registry)
+		}
+		registeredProviderUrl := getUrlToRegistry(providerUrl, registryUrl)
+		err := reg.Register(registeredProviderUrl)
+		if err != nil {
+			logger.Errorf("provider service %v register registry %v error, error message is %s",
+				providerUrl.Key(), registryUrl.Key(), err.Error())
+			return nil
+		}
 	}
 
 	key := getCacheKey(invoker)
@@ -214,11 +216,13 @@ func (proto *registryProtocol) Export(invoker protocol.Invoker) protocol.Exporte
 		logger.Infof("The exporter has not been cached, and will return a new exporter!")
 	}
 
-	go func() {
-		if err = reg.Subscribe(overriderUrl, overrideSubscribeListener); err != nil {
-			logger.Warnf("reg.subscribe(overriderUrl:%v) = error:%v", overriderUrl, err)
-		}
-	}()
+	if registryUrl.Protocol != "" {
+		go func() {
+			if err := reg.Subscribe(overriderUrl, overrideSubscribeListener); err != nil {
+				logger.Warnf("reg.subscribe(overriderUrl:%v) = error:%v", overriderUrl, err)
+			}
+		}()
+	}
 	return cachedExporter.(protocol.Exporter)
 }