web-dev-qa-db-ja.com

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ドキュメントの警告に関係なく、写真をアップロードする(および写真を受信する)このアプローチはまだ有効ですか?

そうでない場合は、標準形式を使用して画像をアップロードし、代わりに画像ファイルの場所を保存する方が良い方法です(標準)。

16
Nate Lee

大規模なバイナリ転送の場合、標準的なアプローチはチャンクです。チャンキングには2つの目的があります。1)各メッセージの処理に必要なメモリの最大量を削減し、2)部分的なアップロードを回復するための境界を提供します。ユースケースでは、おそらく2は必要ありません。

GRPCでは、クライアントストリーミングコールは、フロー制御、パイプライン化を備えており、クライアントコードとサーバーコードのコンテキストを維持しやすいため、かなり自然なチャンクが可能です。部分的なアップロードの回復が必要な場合は、サーバーがクライアントが再開に使用できる進行状況の確認で応答できるため、双方向ストリーミングが適切に機能します。

個々のRPCを使用したチャンキングも可能ですが、より複雑です。ロードバランシングの場合、バックエンドは各チャンクと他のバックエンドと調整する必要があります。チャンクを連続してアップロードすると、ほとんどの時間をサーバーからの応答の受信を待機するため、ネットワークの遅延によりアップロード速度が遅くなる可能性があります。次に、並行してアップロードする必要があります(ただし、並行していくつアップロードしますか?)か、チャンクサイズを大きくする必要があります。ただし、チャンクサイズを大きくすると、各チャンクの処理に必要なメモリが増加し、失敗したアップロードを回復するための粒度が高くなります。並行アップロードでは、サーバーが順不同のアップロードを処理する必要もあります。

16
Eric Anderson

質問で提供されている解決策は、サイズが大きいファイルでは機能しません。小さい画像サイズでのみ機能します。より良い標準的なアプローチは、チャンクを使用することです。 grpcは組み込みのストリーミングをサポートしています。そのため、チャンクで送信するのはかなり簡単です。

syntax = 'proto3'

message UploadImageRequest{
    bytes image = 1;

}

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

上記の方法で、チャンクにストリーミングを使用できます。

チャンク化のために、すべての言語はチャンクサイズに基づいてファイルをチャンクする独自の方法を提供します。

注意すること:

チャンクロジックを処理する必要がある場合、ストリーミングは自然に送信するのに役立ちます。メタデータを送信する場合も3つのアプローチがあります。

1:以下の構造を使用

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

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

ここで、バイトはまだチャンクであり、最初のチャンクではAuthTokenとFileTypeを送信し、他のすべてのリクエストではこれらのメタデータを送信しません。

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); 

以下の構造を使用し、最初のチャンクでメタデータを送信し、他のチャンクはデータを持ちます。コードでそれを処理する必要があります。

syntax = 'proto3'

message UploadImageRequest{
    bytes message = 1;

}

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

最後に、認証では、メッセージで送信する代わりにヘッダーを使用できます。

12
Samarendra