Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gRPC + Image Upload

I want to create a simple gRPC endpoint which the user can upload his/her picture. The protocol buffer declaration is the following:

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

Is this approach of uploading pictures (and recieving pictures) still ok regardless of the warning in the gRPC documentation?

And if not, is the better approach (standard) to upload pictures using the standard form and storing the image file location instead?

like image 869
Nate Lee Avatar asked Jan 23 '16 22:01

Nate Lee


People also ask

Is gRPC scalable?

gRPC is a robust open-source RPC (Remote Procedure Call) framework used to build scalable and fast APIs. It allows the client and server applications to communicate transparently and develop connected systems.

Is gRPC real time?

Point-to-point real-time communication - gRPC can push messages in real time without polling and has excellent support for bi-directional streaming. Network constrained environments – binary gRPC messages are always smaller than an equivalent text-based JSON message.


2 Answers

For large binary transfers, the standard approach is chunking. Chunking can serve two purposes:

  1. reduce the maximum amount of memory required to process each message
  2. provide a boundary for recovering partial uploads.

For your use-case #2 probably isn't very necessary.

In gRPC, a client-streaming call allows for fairly natural chunking since it has flow control, pipelining, and is easy to maintain context in the client and server code. If you care about recovery of partial uploads, then bidirectional-streaming works well since the server can be responding with acknowledgements of progress that the client can use to resume.

Chunking using individual RPCs is also possible, but has more complications. When load balancing, the backend may be required to coordinate with other backends each chunk. If you upload the chunks serially, then the latency of the network can slow upload speed as you spend most of the time waiting to receive responses from the server. You then either have to upload in parallel (but how many in parallel?) or increase the chunk size. But increasing the chunk size increases the memory required to process each chunk and increases the granularity for recovering failed uploads. Parallel upload also requires the server to handle out-of-order uploads.

like image 118
Eric Anderson Avatar answered Oct 23 '22 07:10

Eric Anderson


the solution provided in the question will not work for files having large sizes. it will only work for smaller image sizes. the better and standard approach is use chunking. grpc supports streaming a built in. so it is fairly easy to send in chunks

syntax = 'proto3'

message UploadImageRequest{
    bytes image = 1;

}

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

in the above way we can use streaming for chunking.

for chunking all the languages provide its own way to chunk file based on chunk size.

Things to take care:

you need to handle the chunking logic, streaming helps in sending naturally. if you want to send the metadata also there are three approaches.

1: use below structure

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

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

here bytes is still chunks and for the first chunk send AuthToken and FileType and for all other requests just don't send those metadata.

2: you can also use oneof which is much easier.

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: just use below structure and in first chunk send metadata and other chunks will have data. you need to handle that in code.

syntax = 'proto3'

message UploadImageRequest{
    bytes message = 1;

}

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

lastly for auth you can use headers instead of sending that in message.

like image 45
Samarendra Avatar answered Oct 23 '22 08:10

Samarendra