3

在编写StreamClientInterceptor函数时,确定调用者何时完成 RPC 的最佳方法是什么?对于一元拦截器或在服务器端传递执行 RPC 的处理程序,这很简单,但目前尚不清楚如何最好地在客户端执行此操作,在客户端返回调用程序然后与之交互的ClientStream .

一个用例是检测 OpenTracing,其目标是开始和结束一个跨度以标记 RPC 的开始和结束。

我正在研究的一个策略是让流拦截器返回一个经过修饰的 ClientStream。Header如果任何接口方法、、、、返回错误或被取消CloseSendSendMsg则此新 ClientStream 认为 RPC 已完成。此外,它将此逻辑添加到:RecvMsgContextRecvMsg

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?),所以它不会在所有情况下都有效。有没有更好的方法来实现这一点?

4

1 回答 1

3

我有一个非常相似的问题,我想跟踪流式 gRPC 调用。除了像您自己提到的那样装饰流之外,我找不到检测流结束的好方法。也就是说,直到我遇到 grpc-go ( https://godoc.org/google.golang.org/grpc/stats ) 提供的统计信息钩子。尽管 stats API 旨在收集有关 RPC 调用的统计信息,但它提供的钩子对于跟踪也非常有帮助。

如果您仍在寻找跟踪流式调用的方法,我已经使用 stats 钩子编写了一个用于 gRPC 的 OpenTracing 检测的库: https ://github.com/charithe/otgrpc 。但是,请记住,这种方法可能不适合创建长寿命流的系统。

于 2017-05-14T18:40:21.963 回答