我有一个用于grpc服务器的日志记录拦截器,并希望向元数据添加一个值(我想在请求的整个生命周期中跟踪该请求):

func (m *middleware) loggingInterceptor(srv interface{},
    ss grpc.ServerStream,
    info *grpc.StreamServerInfo,
    handler grpc.StreamHandler)

    md, ok := metadata.FromIncomingContext(ss.Context())
    if !ok {
        return errors.New("could not get metadata from incoming stream context")
    }

    // add the transaction id to the metadata so that business logic can track it
    md.Append("trans-id", "some-transaction-id")

    // call the handler func
    return handler(srv, ss)
}

但是FromIncomingContext的文档指出:
// FromIncomingContext returns the incoming metadata in ctx if it exists.  The
// returned MD should not be modified. Writing to it may cause races.
// Modification should be made to copies of the returned MD.

好的,所以我看一下复制功能并复制元数据:
mdCopy := md.Copy()
mdCopy.Append("trans-id", "some-transaction-id")

并思考“如何将元数据附加到ServerStream上下文?”,然后检查是否存在一些ss.SetContext(newCtx),但看不到任何类似信息。我是从错误的角度考虑这个问题,还是缺少其他东西?

最佳答案

您将需要使用NewIncomingContext在流中创建当前上下文的副本。

然后,您将不得不创建wrappedStream类型,该类型将覆盖Context中的ServerStream方法以返回修改后的context。您需要将此wrappedStream传递给在拦截器中收到的handler

您可以在此处看到一个示例(它在这里覆盖了其他方法,但是思想是相同的):
https://github.com/grpc/grpc-go/blob/master/examples/features/interceptor/server/main.go#L106-L124

希望这可以帮助。

关于go - 如何在拦截器中安全地将值添加到grpc ServerStream,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60982406/

10-15 09:29