Protocol buffers gRPC&x2B;图像上传

Protocol buffers gRPC&x2B;图像上传,protocol-buffers,grpc,Protocol Buffers,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; } 无论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;
}
无论gRPC文档中是否有警告,这种上传图片(和接收图片)的方法仍然可以吗


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

对于大型二进制传输,标准方法是分块。分块有两个目的:

  • 减少处理每条消息所需的最大内存量
  • 提供用于恢复部分上载的边界 对于您的用例,2可能不是很必要

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


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

    问题中提供的解决方案不适用于大文件。它只适用于较小的图像大小。 更好的标准方法是使用分块。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和FileType,对于所有其他请求,只是不发送这些元数据

    2:您也可以使用其中一个更简单的

    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,您可以使用标题,而不是在消息中发送标题。

    您指的是gRPC文档中的什么警告?@Eric Anderson“协议缓冲区不是为处理大型消息而设计的。作为一般经验法则,如果你处理的消息大于每兆字节,则可能是考虑另一种策略的时候了。-所以你建议返回(流字节)。?是否有任何方法可以同时返回元数据和字节流?我建议使用一条消息进行响应,其中一个字段为字节。因此,您可以将元数据作为其他字段。因此,在案例1中,如何确保AuthToken和FileType只发送一次?只发送一次是什么意思?如果您使用的是客户端,它将在其中您的控件只发送一次,如果客户端是某个第三方,他们必须控制它,在任何情况下,在第一个块之后,您都将忽略这两个控件。如果您希望严格限制只发送一次,则方法2是您的选择。