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 ответа

Решение

Для больших двоичных передач стандартным подходом является разбиение на фрагменты. Разделение на части может служить двум целям: 1) уменьшить максимальный объем памяти, необходимый для обработки каждого сообщения, и 2) обеспечить границу для восстановления частичных загрузок. Для вашего случая использования #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: вы также можете использовать 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); 

наконец, для аутентификации вы можете использовать заголовки вместо отправки их в сообщении.

Другие вопросы по тегам