diff --git a/cluster/cluster/failover/cluster_invoker.go b/cluster/cluster/failover/cluster_invoker.go index e13dcf5ec..d70a3994d 100644 --- a/cluster/cluster/failover/cluster_invoker.go +++ b/cluster/cluster/failover/cluster_invoker.go @@ -19,6 +19,7 @@ package failover import ( "context" + "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol" "fmt" ) @@ -83,7 +84,7 @@ func (invoker *failoverClusterInvoker) Invoke(ctx context.Context, invocation pr invoked = append(invoked, ivk) // DO INVOKE result = ivk.Invoke(ctx, invocation) - if result.Error() != nil { + if result.Error() != nil && !isBizError(result.Error()) { providers = append(providers, ivk.GetURL().Key()) continue } @@ -100,13 +101,16 @@ func (invoker *failoverClusterInvoker) Invoke(ctx context.Context, invocation pr } } - return &protocol.RPCResult{ - Err: perrors.Wrap(result.Error(), fmt.Sprintf("Failed to invoke the method %v in the service %v. "+ - "Tried %v times of the providers %v (%v/%v)from the registry %v on the consumer %v using the dubbo version %v. "+ - "Last error is %+v.", methodName, invokerSvc, retries, providers, len(providers), len(invokers), - invokerUrl, ip, constant.Version, result.Error().Error()), - ), - } + logger.Errorf(fmt.Sprintf("Failed to invoke the method %v in the service %v. "+ + "Tried %v times of the providers %v (%v/%v)from the registry %v on the consumer %v using the dubbo version %v. "+ + "Last error is %+v.", methodName, invokerSvc, retries, providers, len(providers), len(invokers), + invokerUrl, ip, constant.Version, result.Error().Error())) + + return result +} + +func isBizError(err error) bool { + return triple_protocol.IsWireError(err) && triple_protocol.CodeOf(err) == triple_protocol.CodeBizError } func getRetries(invokers []protocol.Invoker, methodName string) int { diff --git a/protocol/result.go b/protocol/result.go index 904bce326..d86cac27e 100644 --- a/protocol/result.go +++ b/protocol/result.go @@ -53,9 +53,10 @@ var _ Result = (*RPCResult)(nil) // RPCResult is default RPC result. type RPCResult struct { - Attrs map[string]interface{} - Err error - Rest interface{} + Attrs map[string]interface{} + BizErr error + Err error + Rest interface{} } // SetError sets error. @@ -68,6 +69,16 @@ func (r *RPCResult) Error() error { return r.Err } +// SetBizError sets error. +func (r *RPCResult) SetBizError(err error) { + r.BizErr = err +} + +// BizError gets error. Replaced with error code in triple protocol since 3.2.0 +func (r *RPCResult) BizError() error { + return r.BizErr +} + // SetResult sets invoker result. func (r *RPCResult) SetResult(rest interface{}) { r.Rest = rest diff --git a/protocol/triple/triple_protocol/code.go b/protocol/triple/triple_protocol/code.go index c66074a67..60bc67fe1 100644 --- a/protocol/triple/triple_protocol/code.go +++ b/protocol/triple/triple_protocol/code.go @@ -104,6 +104,8 @@ const ( // authentication credentials for the operation. CodeUnauthenticated Code = 16 + CodeBizError Code = 17 + minCode = CodeCanceled maxCode = CodeUnauthenticated ) diff --git a/server/server.go b/server/server.go index 1931d6f6f..5d9281ed9 100644 --- a/server/server.go +++ b/server/server.go @@ -20,6 +20,7 @@ package server import ( "context" + "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol" "fmt" "sort" "sync" @@ -106,7 +107,9 @@ func (ii *infoInvoker) Invoke(ctx context.Context, invocation protocol.Invocatio if method, ok := ii.methodMap[name]; ok { res, err := method.MethodFunc(ctx, args, ii.svc) result.SetResult(res) - result.SetError(err) + if err != nil { + result.SetError(triple_protocol.NewError(triple_protocol.CodeBizError, err)) + } return result } result.SetError(fmt.Errorf("no match method for %s", name))