定义有关流的 gRPC 元数据的最佳实践

Best practice for defining gRPC metadata about a stream

我必须向 gRPC 服务器发送消息流,但我还必须发送大量关于该流的元数据。有没有办法定义元数据消息并使其成为客户端和服务器之间接口契约的一部分?据我所知,将另一条消息编组到元数据中似乎完全超出了我的 .proto 文件中的接口定义。

真的,我希望 gRPC 允许流式调用有两个参数,例如:

service DataServer {
    rpc AddData(DataScope, stream MyData) returns (Reply) {}
}

是否有正确的或至少是普遍接受的方法来处理这个问题?

这不可能如你所愿(如你所知)但是,它在功能上等同于:

service DataServer {
    rpc AddStream(AddStreamRequest) returns (AddStreamResponse) {}
    rpc AddData(stream MyData) returns (Reply) {}
}

其中 AddStreamResponse 包含在 MyData 中引用的唯一(流)标识符。

我们决定在 MyData 流消息中嵌入一个可选的流定义“header”消息。我们只在流的第一个 MyData 消息中填充 header 消息。

message StreamBlock {
    DataScope header = 1;
    MyData    data   = 2;
}

当数据足够短以适合单个 MyData protobuf 消息时,它允许我们在单个 gRPC 往返调用中发送 header 和数据。当数据较长并分解为多个 MyData 消息时,后续消息中未使用的 header 字段将不使用 space,因此不会产生额外的开销。

不幸的是,这是不可能的。但这是一个等价物:

您可以使用 oneof 关键字来指定请求应该包含配置(范围)或数据。您的客户很容易理解,他们的 AddDataRequest 流中的第一个对象必须包含范围,而随后的对象必须包含数据。您的服务器实现必须断言此行为。

service DataServer {
    rpc AddData(stream AddDataRequest) returns (AddDataReply) {}
}

message AddDataRequest {
    oneof request {
        AddDataConfiguration configuration = 1;
        Data data = 2;
    }
}