web-dev-qa-db-fra.com

gRPC + téléchargement d'image

Je veux créer un simple point de terminaison gRPC que l'utilisateur peut télécharger sa photo. La déclaration de tampon de protocole est la suivante:

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

Cette approche de téléchargement d'images (et de réception d'images) est-elle toujours correcte, indépendamment de l'avertissement dans la documentation gRPC?

Et sinon, est-ce la meilleure approche (standard) pour télécharger des images en utilisant le formulaire standard et en stockant l'emplacement du fichier image à la place?

16
Nate Lee

Pour les gros transferts binaires, l'approche standard est la segmentation. Le découpage peut servir à deux fins: 1) réduire la quantité maximale de mémoire requise pour traiter chaque message et 2) fournir une limite pour récupérer des téléchargements partiels. Pour votre cas d'utilisation, # 2 n'est probablement pas très nécessaire.

Dans gRPC, un appel de streaming client permet une segmentation assez naturelle car il a un contrôle de flux, un pipeline et est facile à maintenir le contexte dans le code client et serveur. Si vous vous souciez de la récupération des téléchargements partiels, le streaming bidirectionnel fonctionne bien car le serveur peut répondre avec des accusés de réception que le client peut utiliser pour reprendre.

Le découpage à l'aide de RPC individuels est également possible, mais présente plus de complications. Lors de l'équilibrage de charge, le backend peut être amené à se coordonner avec les autres backends de chaque bloc. Si vous téléchargez les morceaux en série, la latence du réseau peut ralentir la vitesse de téléchargement car vous passez la plupart du temps à attendre de recevoir des réponses du serveur. Vous devez alors soit télécharger en parallèle (mais combien en parallèle?) Soit augmenter la taille du bloc. Mais l'augmentation de la taille du bloc augmente la mémoire requise pour traiter chaque bloc et augmente la granularité pour la récupération des téléchargements ayant échoué. Le téléchargement parallèle nécessite également que le serveur gère les téléchargements hors service.

16
Eric Anderson

la solution fournie dans la question ne fonctionnera pas pour les fichiers de grande taille. cela ne fonctionnera que pour des tailles d'image plus petites. l'approche meilleure et standard consiste à utiliser la segmentation. grpc prend en charge le streaming intégré. il est donc assez facile d'envoyer des morceaux

syntax = 'proto3'

message UploadImageRequest{
    bytes image = 1;

}

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

de la manière ci-dessus, nous pouvons utiliser le streaming pour le découpage.

pour le découpage en morceaux, toutes les langues fournissent leur propre façon de découper un fichier en fonction de la taille du bloc.

Choses à prendre en charge:

vous devez gérer la logique de segmentation, le streaming aide à envoyer naturellement. si vous souhaitez également envoyer les métadonnées, il existe trois approches.

1: utiliser la structure ci-dessous

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

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

ici, les octets sont toujours des morceaux et pour le premier morceau, envoyez AuthToken et FileType et pour toutes les autres demandes, n'envoyez simplement pas ces métadonnées.

2: vous pouvez également utiliser oneof ce qui est beaucoup plus facile.

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

: utilisez simplement la structure ci-dessous et dans le premier bloc, envoyez les métadonnées et les autres blocs auront des données. vous devez gérer cela dans le code.

syntax = 'proto3'

message UploadImageRequest{
    bytes message = 1;

}

rpc UploadImage(stream UploadImageRequest) returns (Ack); 

enfin pour l'authentification, vous pouvez utiliser des en-têtes au lieu d'envoyer cela dans un message.

12
Samarendra