-
Notifications
You must be signed in to change notification settings - Fork 818
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(gRPC): optimize gRPC error handling #1549
base: develop
Are you sure you want to change the base?
feat(gRPC): optimize gRPC error handling #1549
Conversation
20064bb
to
ed1b013
Compare
012de39
to
8683021
Compare
// Error wraps a pointer of a status proto. It implements error and Status, | ||
// and a nil *Error should never be returned by this package. | ||
type Error struct { | ||
e *spb.Status | ||
e *spb.Status | ||
triggeredByUpstream bool |
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.
这个有点丑,我们要不要通过 code 编码来区别呀?另外streaming里没有什么upstream的概念。。。代码里可以都叫 remote err
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.
更好的办法确实是 code 编码,但是对于 gRPC-python 之类的服务可能不认。
叫 upstream 主要是因为 A -> B -> C,A B 出错导致 B C 调用失败,不提示 upstream 的话很容易以为是 B C 间的问题。。
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.
移除了,现在 http2Server 流/连接被关闭抛出的错误都会带上"[triggered by {remote service}]"后缀
62e6e92
to
ba48fa1
Compare
3087213
to
94687b7
Compare
@@ -451,19 +451,23 @@ func (c *controlBuffer) get(block bool) (interface{}, error) { | |||
select { | |||
case <-c.ch: | |||
case <-c.done: |
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.
done是外部传入的,如果close了的吧,而c.err没数据,会导致返回 nil
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.
c.finish(errStatusConnClosing) 已经注入了 err 了(在 c.err 没数据的情况下)
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.
finish是不是直接return err呀,这样外面不用老是加锁再取一次。
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.
done.
sendRSTStreamFrameSuffix = "[send RST Stream Frame]" | ||
) | ||
|
||
func remoteErrMsg(msg string) string { |
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.
这些方法实际上也没有多大的意义。。。感觉不如直接写到klog.CtxErrorf,一般用于日志的话,不要把格式化放在外层做。因为如果关闭了日志,这些逻辑都不应该被执行。
t.controlBuf.put(&cleanupStream{ | ||
streamID: streamID, | ||
rst: true, | ||
rstCode: http2.ErrCodeRefusedStream, | ||
onWrite: func() {}, | ||
}) | ||
s.cancel(errMaxStreamsExceeded) |
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.
这个变更是为啥?
return errStatusStreamDone | ||
} | ||
|
||
func (s *Stream) SetSourceService(svc string) { |
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.
这是公开的方法,不应该这样直接放出来。
@@ -185,6 +185,7 @@ func (t *svrTransHandler) handleFunc(s *grpcTransport.Stream, svrTrans *SvrTrans | |||
return | |||
} | |||
} | |||
s.SetSourceService(ri.From().ServiceName()) |
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.
还是用一个更通用的方式去存储这类数据吧,不然后面要加一堆的公开接口。
7688c77
to
67c9a2d
Compare
36b87c4
to
a7622dc
Compare
963f2d1
to
c7bb7cd
Compare
9bd9abe
to
95da68d
Compare
@@ -0,0 +1,62 @@ | |||
/* |
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.
外部统一使用 streamx 下暴露的定义
// Error wraps a pointer of a status proto. It implements error and Status, | ||
// and a nil *Error should never be returned by this package. | ||
type Error struct { | ||
e *spb.Status | ||
// kerr is the Kitex custom error that status maps to | ||
kerr error |
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.
携带 kerrors 和 gerrors 中定义的错误,用于 errors.Is 错误处理与内部错误码上报
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.
这个预计会怎么用? fmt.Errorf %w + errors.As 的方式不就够了么,为什么还要封装?
// e.g. RegisterCustomRstCode(1000, kerrors.ErrGracefulShutdown) | ||
// When Kitex receives a RST_STREAM frame with error code 1000, it will inject kerrors.ErrGracefulShutdown into | ||
// *status.Error that users will conceive | ||
func RegisterCustomRstCode(rstCode uint32, mappingErr error) { |
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.
注册 HTTP2 ErrCode 与 kerrors/gerrors 错误之间的映射,使得 RstStream Frame 可以传递信息
95da68d
to
0f7b799
Compare
) | ||
|
||
// SetServiceMeta is used to inject service-related metadata | ||
func (s *Stream) SetServiceMeta(key svcMetaKey, val interface{}) error { |
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.
这个方法到底是对内还是对外的?对内的话,不用暴露出来,对外的话,interface里也没有,保证不了用户套了一层,我们用不了。另外key这类,不要用string
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.
这个方法是对内的,但是不暴露的话,没法在 nphttp2/server_handler.go 中直接使用。
用户即使套了也没有意义,执行 SetServiceMeta 的时候用户还没法感知 Stream
@@ -158,29 +160,54 @@ func (s *Status) Details() []interface{} { | |||
return details | |||
} | |||
|
|||
// WithMappingErr creates a new Status and injects Kitex mapping err | |||
func (s *Status) WithMappingErr(kerr error) *Status { |
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.
这个预计会怎么用? fmt.Errorf %w + errors.As 的方式不就够了么,为什么还要封装?
) | ||
|
||
// IsStreamingError reports whether the given err is a streaming err | ||
func IsStreamingError(err error) bool { |
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.
这个如果在热路径上判断会比较低效,会随着错误变多,每个都要判断一次。加个 streamingError
类型?
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.
done.
// This package contains all the errors suitable for Kitex errors model. | ||
// These errors should not be used by user directly. | ||
// If users need to perceive these errors, the pkg/streamx/provider/grpc/gerrors package should be used. | ||
var ( |
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.
如果用户不需要用的话,就不用定义到这里。哪里返回的话,定义到哪里。反正也不会拿来做逻辑,只是判断、日志,不需要export
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.
内部需要拿到这个类型获取相应错误码,如果不暴露的话,得修改 *status.Error 的 Code() 方法返回值,或者加个 TypeID() 方法,内部错误码定义放在开源库里。
basic error | ||
} | ||
|
||
func newErrType(message string) *errType { |
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.
这个实现成 fmt.Errorf("%w - %s", kerrors.ErrStreamingProtocol, message)
好像跟你的一样。
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.
主要是考虑有可能会对 errType 做扩展,用 fmt.Errorf 确实最快
be89793
to
3cc884a
Compare
9d514fa
to
a9dee0c
Compare
What type of PR is this?
feat
Check the PR title.
(Optional) Translate the PR title into Chinese.
(Optional) More detailed description for this PR(en: English/zh: Chinese).
en:
ConnectionError
tocode = 14, msg = ConnectionError.Desc
statuszh(optional):
the stream is done
,现在可以拿到流被关闭的真正原因ConnectionError
转化为code = 14, msg = ConnectionError.Desc
的 status(Optional) Which issue(s) this PR fixes:
(optional) The PR that updates user documentation: