2016-01-23 178 views
4

我想创建一个简单的gRPC端点,用户可以上传他/她的图片。协议缓存声明如下:gRPC +图片上传

message UploadImageRequest { 
    AuthToken auth = 1; 
    // An enum with either JPG or PNG 
    FileType image_format = 2; 
    // Image file as bytes 
    bytes image = 3; 
} 

是上传图片(和recieving图片)的这种方法还行,而不管GRPC文档中的警告?

如果不是,使用标准表单上传图片并更改图片文件位置是更好的方法(标准)吗?

+0

您提到的gRPC文档中有哪些警告? –

+0

@EricAnderson“协议缓冲区并不是为了处理大量消息而设计的,根据一般经验,如果您处理的消息大于每兆字节,则可能是考虑替代策略的时候了。” -https://developers.google.com/protocol-buffers/docs/techniques?hl = en –

回答

4

对于大型二进制传输,标准方法是分块。分块可以用于两个目的:1)减少处理每条消息所需的最大内存量; 2)为恢复部分上载提供一个边界。对于你的用例,#2可能不是非常必要的。

在gRPC中,客户端流式调用允许相当自然的分块,因为它具有流控制,流水线并且易于在客户端和服务器代码中维护上下文。如果您关心部分上传的恢复,那么双向流技术可以很好地工作,因为服务器可以响应客户端可以用来恢复的进度确认。

使用独立RPC的分块也是可能的,但有更多的复杂性。当负载均衡时,后端可能需要与每个块的其他后端进行协调。如果您连续上传块,那么网络的延迟会降低上传速度,因为您大部分时间都在等待接收来自服务器的响应。然后,您必须并行上传(但多少并行?)或增加块大小。但增加块大小会增加处理每个块所需的内存,并增加恢复失败上载的粒度。并行上传还要求服务器处理乱序上传。

+0

所以你建议返回(流字节)?有什么方法可以将元数据和字节流返回到一个? – FrozenKiwi

+0

我建议用消息来回复,其中一个字段是字节。所以你可以有元数据作为其他领域。 –

1

问题中提供的解决方案不适用于大尺寸文件。它只适用于较小的图像尺寸。 更好和标准的方法是使用chunking。 GRPC支持流内置的,所以它是很容易在块中,我们可以使用流媒体分块上述方式发送

syntax = 'proto3' 

message UploadImageRequest{ 
    bytes image = 1; 

} 

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

用于分块的所有语言提供了它自己的方式来基于块大小的块文件。

事情打理:

你需要处理的分块逻辑,流有助于自然发送。 如果你想发送元数据也有三种方法。

1:以下结构

message UploadImageRequest{ 
    AuthToken auth = 1; 
    FileType image_format = 2; 
    bytes image = 3; 
} 

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

这里字节的使用仍然块和第一个块发送的authToken和文件类型以及所有其他请求只是不发送这些元数据。

2:您还可以使用oneof这是更容易。

message UploadImageRequest{ 
     oneof test_oneof { 
       Metadata meta = 2; 
       bytes image = 1; 
     } 
} 
message Metadata{ 
    AuthToken auth = 1; 
    FileType image_format = 2; 
} 

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

3:只是使用以下结构与在第一组块发送的元数据和其他块将有数据。你需要在代码中处理。

syntax = 'proto3' 

message UploadImageRequest{ 
    bytes message = 1; 

} 

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

最后为auth你可以使用头,而不是发送消息。