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

Stream 定义关于流的gRPC元数据的最佳实践,stream,metadata,grpc,rpc,grpc-go,Stream,Metadata,Grpc,Rpc,Grpc Go,我必须向gRPC服务器发送消息流,但我还必须发送大量关于该流的元数据。有没有办法定义元数据消息并使其成为客户端和服务器之间接口契约的一部分?据我所知,似乎将另一条消息封送到元数据中完全超出了我的.proto文件中的接口定义 真的,我希望gRPC允许流式呼叫有两个参数,如: service DataServer { rpc AddData(DataScope, stream MyData) returns (Reply) {} } 是否有一种正确的方法,或者至少是一种普遍接受的方法来实现

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

真的,我希望gRPC允许流式呼叫有两个参数,如:

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

是否有一种正确的方法,或者至少是一种普遍接受的方法来实现这一点?

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

服务数据服务器{
rpc AddStream(AddStreamRequest)返回(AddStreamResponse){}
rpc AddData(stream MyData)返回(Reply){}
}

其中,
AddStreamResponse
包含一个在
MyData

中引用的唯一(流)标识符,这是不可能的(如您所知),但是,它在功能上等同于:

服务数据服务器{
rpc AddStream(AddStreamRequest)返回(AddStreamResponse){}
rpc AddData(stream MyData)返回(Reply){}
}

其中
AddStreamResponse
包含一个唯一的(流)标识符,该标识符在
MyData
中引用。我们决定在MyData流消息中嵌入一个可选的流定义“header”消息。我们只在流的第一条MyData消息中填充该头消息

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

当数据足够短,可以全部放入单个MyData protobuf消息时,它允许我们在单个gRPC往返呼叫中发送标头和数据。当数据较长并分解为多条MyData消息时,后续消息中未使用的标头字段不占用空间,因此不会产生额外开销。

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

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

当数据足够短,可以全部放入单个MyData protobuf消息时,它允许我们在单个gRPC往返呼叫中发送标头和数据。当数据较长并分解为多条MyData消息时,后续消息中未使用的标头字段将不占用空间,因此不会产生额外的开销。

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

您可以使用oneof关键字指定请求应包含配置(范围)或数据。您的客户机将很容易理解,AddDataRequest流中的第一个对象必须包含作用域,以下对象必须包含数据。您的服务器实现必须声明此行为

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

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

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

您可以使用oneof关键字指定请求应包含配置(范围)或数据。您的客户机将很容易理解,AddDataRequest流中的第一个对象必须包含作用域,以下对象必须包含数据。您的服务器实现必须声明此行为

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

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

感谢您发布此Daz。我喜欢这个解决方案。我们没有朝这个方向走的唯一原因是它创建了一些额外的服务器端管理,因为服务器需要跟踪AddStream密钥/头,等待将来的AddData。如果客户端出错,服务器可能无法获得匹配的AddData,服务器将开始累积密钥/头。感谢发布此Daz。我喜欢这个解决方案。我们没有朝这个方向走的唯一原因是它创建了一些额外的服务器端管理,因为服务器需要跟踪AddStream密钥/头,等待将来的AddData。如果客户端出错,服务器可能无法获得匹配的AddData,服务器将开始累积密钥/头。您应该通过keywork之一定义此行为。看看我的回答,你应该通过一个键来定义这种行为。看看我的回答,我不确定这是否比嵌入在流块中的可选头消息好。对于只需要一条流消息的短数据,这将始终至少需要两条消息。我不确定这是否比嵌入流块中的可选头消息好。对于仅需要一条流消息的短数据,这将始终至少需要两条消息。可能重复?可能重复?