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);
наконец, для аутентификации вы можете использовать заголовки вместо отправки их в сообщении.