在编写StreamClientInterceptor函数时,确定调用者何时完成 RPC 的最佳方法是什么?对于一元拦截器或在服务器端传递执行 RPC 的处理程序,这很简单,但目前尚不清楚如何最好地在客户端执行此操作,在客户端返回调用程序然后与之交互的ClientStream .
一个用例是检测 OpenTracing,其目标是开始和结束一个跨度以标记 RPC 的开始和结束。
我正在研究的一个策略是让流拦截器返回一个经过修饰的 ClientStream。Header
如果任何接口方法、、、、返回错误或被取消CloseSend
,SendMsg
则此新 ClientStream 认为 RPC 已完成。此外,它将此逻辑添加到:RecvMsg
Context
RecvMsg
func (cs *DecoratedClientStream) RecvMsg(m interface{}) error {
err := cs.ClientStream.RecvMsg(m)
if err == io.EOF {
// Consider the RPC as complete
return err
} else if err != nil {
// Consider the RPC as complete
return err
}
if !cs.isResponseStreaming {
// Consider the RPC as complete
}
return err
}
它在大多数情况下都可以工作,但我的理解是,如果调用者Recv
知道结果会是,则不需要调用io.EOF
(请参阅在与 grpc.ClientStreams 交互时是否需要调用 Recv 直到获得 io.EOF?),所以它不会在所有情况下都有效。有没有更好的方法来实现这一点?