-
Notifications
You must be signed in to change notification settings - Fork 934
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: sort out triple logic and fix comments #2454
Merged
chickenlj
merged 8 commits into
apache:feature-triple
from
DMwangnima:feature-triple_enhancement
Nov 9, 2023
Merged
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a428399
feat: sort out triple logic and fix comments
DMwangnima 7485def
modify grpc related comments
DMwangnima e1d408a
modify some statements and add some tests
DMwangnima 643075e
Merge branch 'feature-triple_dubbo_load' into feature-triple_enhancement
DMwangnima 41d39e6
add dubbo3 client stub code compatibility and default timeout for una…
DMwangnima 208d90f
add attribute related functions and ignore golang-lint error
DMwangnima c3bf05b
replace ignoring lint tag
DMwangnima c825ea0
modify listening port
DMwangnima File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
add dubbo3 client stub code compatibility and default timeout for una…
…ry call
- Loading branch information
commit 41d39e605197343090bc377593558e6e41f2eec9
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
/* | ||
* 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 triple | ||
|
||
import ( | ||
"context" | ||
"reflect" | ||
"strconv" | ||
"strings" | ||
"sync" | ||
"time" | ||
) | ||
|
||
import ( | ||
"github.com/dubbogo/gost/log/logger" | ||
|
||
"github.com/dubbogo/grpc-go/metadata" | ||
|
||
tripleConstant "github.com/dubbogo/triple/pkg/common/constant" | ||
triConfig "github.com/dubbogo/triple/pkg/config" | ||
"github.com/dubbogo/triple/pkg/triple" | ||
|
||
"github.com/dustin/go-humanize" | ||
) | ||
|
||
import ( | ||
"dubbo.apache.org/dubbo-go/v3/common" | ||
"dubbo.apache.org/dubbo-go/v3/common/constant" | ||
"dubbo.apache.org/dubbo-go/v3/config" | ||
"dubbo.apache.org/dubbo-go/v3/protocol" | ||
invocation_impl "dubbo.apache.org/dubbo-go/v3/protocol/invocation" | ||
) | ||
|
||
// same as dubbo_invoker.go attachmentKey | ||
var attachmentKey = []string{ | ||
constant.InterfaceKey, constant.GroupKey, constant.TokenKey, constant.TimeoutKey, | ||
constant.VersionKey, tripleConstant.TripleServiceGroup, tripleConstant.TripleServiceVersion, | ||
} | ||
|
||
// DubboInvoker is implement of protocol.Invoker, a dubboInvoker refer to one service and ip. | ||
type DubboInvoker struct { | ||
protocol.BaseInvoker | ||
// the net layer client, it is focus on network communication. | ||
client *triple.TripleClient | ||
// quitOnce is used to make sure DubboInvoker is only destroyed once | ||
quitOnce sync.Once | ||
// timeout for service(interface) level. | ||
timeout time.Duration | ||
// clientGuard is the client lock of dubbo invoker | ||
clientGuard *sync.RWMutex | ||
} | ||
|
||
// NewDubbo3Invoker constructor | ||
func NewDubbo3Invoker(url *common.URL) (*DubboInvoker, error) { | ||
rt := config.GetConsumerConfig().RequestTimeout | ||
|
||
timeout := url.GetParamDuration(constant.TimeoutKey, rt) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should also consider method timeout. |
||
// for triple pb serialization. The bean name from provider is the provider reference key, | ||
// which can't locate the target consumer stub, so we use interface key.. | ||
interfaceKey := url.GetParam(constant.InterfaceKey, "") | ||
consumerService := config.GetConsumerServiceByInterfaceName(interfaceKey) | ||
|
||
dubboSerializerType := url.GetParam(constant.SerializationKey, constant.ProtobufSerialization) | ||
triCodecType := tripleConstant.CodecType(dubboSerializerType) | ||
// new triple client | ||
opts := []triConfig.OptionFunction{ | ||
triConfig.WithClientTimeout(timeout), | ||
triConfig.WithCodecType(triCodecType), | ||
triConfig.WithLocation(url.Location), | ||
triConfig.WithHeaderAppVersion(url.GetParam(constant.AppVersionKey, "")), | ||
triConfig.WithHeaderGroup(url.GetParam(constant.GroupKey, "")), | ||
triConfig.WithLogger(logger.GetLogger()), | ||
} | ||
maxCallRecvMsgSize := constant.DefaultMaxCallRecvMsgSize | ||
if maxCall, err := humanize.ParseBytes(url.GetParam(constant.MaxCallRecvMsgSize, "")); err == nil && maxCall != 0 { | ||
maxCallRecvMsgSize = int(maxCall) | ||
} | ||
maxCallSendMsgSize := constant.DefaultMaxCallSendMsgSize | ||
if maxCall, err := humanize.ParseBytes(url.GetParam(constant.MaxCallSendMsgSize, "")); err == nil && maxCall != 0 { | ||
maxCallSendMsgSize = int(maxCall) | ||
} | ||
opts = append(opts, triConfig.WithGRPCMaxCallRecvMessageSize(maxCallRecvMsgSize)) | ||
opts = append(opts, triConfig.WithGRPCMaxCallSendMessageSize(maxCallSendMsgSize)) | ||
|
||
tracingKey := url.GetParam(constant.TracingConfigKey, "") | ||
if tracingKey != "" { | ||
tracingConfig := config.GetTracingConfig(tracingKey) | ||
if tracingConfig != nil { | ||
if tracingConfig.Name == "jaeger" { | ||
if tracingConfig.ServiceName == "" { | ||
tracingConfig.ServiceName = config.GetApplicationConfig().Name | ||
} | ||
opts = append(opts, triConfig.WithJaegerConfig( | ||
tracingConfig.Address, | ||
tracingConfig.ServiceName, | ||
*tracingConfig.UseAgent, | ||
)) | ||
} else { | ||
logger.Warnf("unsupported tracing name %s, now triple only support jaeger", tracingConfig.Name) | ||
} | ||
} | ||
} | ||
|
||
triOption := triConfig.NewTripleOption(opts...) | ||
tlsConfig := config.GetRootConfig().TLSConfig | ||
if tlsConfig != nil { | ||
triOption.TLSCertFile = tlsConfig.TLSCertFile | ||
triOption.TLSKeyFile = tlsConfig.TLSKeyFile | ||
triOption.CACertFile = tlsConfig.CACertFile | ||
triOption.TLSServerName = tlsConfig.TLSServerName | ||
logger.Infof("Triple Client initialized the TLSConfig configuration") | ||
} | ||
client, err := triple.NewTripleClient(consumerService, triOption) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &DubboInvoker{ | ||
BaseInvoker: *protocol.NewBaseInvoker(url), | ||
client: client, | ||
timeout: timeout, | ||
clientGuard: &sync.RWMutex{}, | ||
}, nil | ||
} | ||
|
||
func (di *DubboInvoker) setClient(client *triple.TripleClient) { | ||
di.clientGuard.Lock() | ||
defer di.clientGuard.Unlock() | ||
|
||
di.client = client | ||
} | ||
|
||
func (di *DubboInvoker) getClient() *triple.TripleClient { | ||
di.clientGuard.RLock() | ||
defer di.clientGuard.RUnlock() | ||
|
||
return di.client | ||
} | ||
|
||
// Invoke call remoting. | ||
func (di *DubboInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result { | ||
var ( | ||
result protocol.RPCResult | ||
) | ||
|
||
if !di.BaseInvoker.IsAvailable() { | ||
// Generally, the case will not happen, because the invoker has been removed | ||
// from the invoker list before destroy,so no new request will enter the destroyed invoker | ||
logger.Warnf("this dubboInvoker is destroyed") | ||
result.Err = protocol.ErrDestroyedInvoker | ||
return &result | ||
} | ||
|
||
di.clientGuard.RLock() | ||
defer di.clientGuard.RUnlock() | ||
|
||
if di.client == nil { | ||
result.Err = protocol.ErrClientClosed | ||
return &result | ||
} | ||
|
||
if !di.BaseInvoker.IsAvailable() { | ||
// Generally, the case will not happen, because the invoker has been removed | ||
// from the invoker list before destroy,so no new request will enter the destroyed invoker | ||
logger.Warnf("this grpcInvoker is destroying") | ||
result.Err = protocol.ErrDestroyedInvoker | ||
return &result | ||
} | ||
|
||
for _, k := range attachmentKey { | ||
var paramKey string | ||
switch k { | ||
case tripleConstant.TripleServiceGroup: | ||
paramKey = constant.GroupKey | ||
case tripleConstant.TripleServiceVersion: | ||
paramKey = constant.VersionKey | ||
default: | ||
paramKey = k | ||
} | ||
|
||
if v := di.GetURL().GetParam(paramKey, ""); len(v) > 0 { | ||
invocation.SetAttachment(k, v) | ||
} | ||
} | ||
|
||
// append interface id to ctx | ||
gRPCMD := make(metadata.MD, 0) | ||
// triple will convert attachment value to []string | ||
for k, v := range invocation.Attachments() { | ||
if str, ok := v.(string); ok { | ||
gRPCMD.Set(k, str) | ||
continue | ||
} | ||
if str, ok := v.([]string); ok { | ||
gRPCMD.Set(k, str...) | ||
continue | ||
} | ||
logger.Warnf("[Triple Protocol]Triple attachment value with key = %s is invalid, which should be string or []string", k) | ||
} | ||
ctx = metadata.NewOutgoingContext(ctx, gRPCMD) | ||
ctx = context.WithValue(ctx, tripleConstant.InterfaceKey, di.BaseInvoker.GetURL().GetParam(constant.InterfaceKey, "")) | ||
in := make([]reflect.Value, 0, 16) | ||
in = append(in, reflect.ValueOf(ctx)) | ||
|
||
if len(invocation.ParameterValues()) > 0 { | ||
in = append(in, invocation.ParameterValues()...) | ||
} | ||
|
||
methodName := invocation.MethodName() | ||
triAttachmentWithErr := di.client.Invoke(methodName, in, invocation.Reply()) | ||
result.Err = triAttachmentWithErr.GetError() | ||
result.Attrs = make(map[string]interface{}) | ||
for k, v := range triAttachmentWithErr.GetAttachments() { | ||
result.Attrs[k] = v | ||
} | ||
result.Rest = invocation.Reply() | ||
return &result | ||
} | ||
|
||
// get timeout including methodConfig | ||
func (di *DubboInvoker) getTimeout(invocation *invocation_impl.RPCInvocation) time.Duration { | ||
timeout := di.GetURL().GetParam(strings.Join([]string{constant.MethodKeys, invocation.MethodName(), constant.TimeoutKey}, "."), "") | ||
if len(timeout) != 0 { | ||
if t, err := time.ParseDuration(timeout); err == nil { | ||
// config timeout into attachment | ||
invocation.SetAttachment(constant.TimeoutKey, strconv.Itoa(int(t.Milliseconds()))) | ||
return t | ||
} | ||
} | ||
// set timeout into invocation at method level | ||
invocation.SetAttachment(constant.TimeoutKey, strconv.Itoa(int(di.timeout.Milliseconds()))) | ||
return di.timeout | ||
} | ||
|
||
// IsAvailable check if invoker is available, now it is useless | ||
func (di *DubboInvoker) IsAvailable() bool { | ||
client := di.getClient() | ||
if client != nil { | ||
// FIXME here can't check if tcp server is started now!!! | ||
return client.IsAvailable() | ||
} | ||
return false | ||
} | ||
|
||
// Destroy destroy dubbo3 client invoker. | ||
func (di *DubboInvoker) Destroy() { | ||
di.quitOnce.Do(func() { | ||
di.BaseInvoker.Destroy() | ||
client := di.getClient() | ||
if client != nil { | ||
di.setClient(nil) | ||
client.Close() | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand it right, this
url
contains the complete configuration of a specific service? I think we need to call something like below to get the method level timeout configuration:timeout := url.GetMethodParamDuration(constant.TimeoutKey, "")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the default timeout value for
(constant.TimeoutKey, "")
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized something. Are we in the middle of an
RPC invoke
here? If not, we might not be able to get themethod name
needed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specific method level timeout (optional) passed in with
ctx
inTripleInvoker.invoke(ctx)
, then toclientManager.callUnary/callClientStream()
. If timeout presents in ctx, then it will be used as the timeout value; If not, the default value calculated here bytimeout := url.GetParamDuration(constant.TimeoutKey, "")
will be used.Is the above process right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is. The
ctx
used by users would have highest priority. It is more ideal for uses to usectx
to specify timeout for method level since they can usecancel
function directly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are in the process of
Refer
, i.e. initialize client and some general configurations.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, this sounds reasonable to me.
One more thing, we need to check the
method level timeout
ifctx
is not set, then putmethod timeout
intoctx
.