使用 StreamClientInterceptor 确定 RPC 会话何时结束的最佳方法是什么?

What's the best way to determine when an RPC session ends using a StreamClientInterceptor?

编写调用程序随后与之交互的 StreamClientInterceptor function, what's the best way to determine when an invoker finishes the RPC? This is straightforward enough with unary interceptors or on the server-side where you're passed a handler that performs the RPC, but it's not clear how best to do this on the client-side where you return a ClientStream 时。

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

我正在研究的一种策略是让流拦截器 return 是经过修饰的 ClientStream。如果任何接口方法 HeaderCloseSendSendMsgRecvMsg return 出现错误或 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 调用。除了像你自己提到的那样装饰流,我无法找到检测流结束的好方法。也就是说,直到我遇到 grpc-go (https://godoc.org/google.golang.org/grpc/stats) 提供的统计挂钩。尽管 stats API 用于收集有关 RPC 调用的统计信息,但它提供的挂钩对于跟踪也非常有帮助。

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