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 ответов
для больших двоичных передач стандартным подходом является chunking. Чанкинг может служить двум целям: 1) уменьшить максимальный объем памяти, необходимый для обработки каждого сообщения, и 2) обеспечить границу для восстановления частичных загрузок. Для вашего использования, #2, вероятно, не очень нужны.
в gRPC вызов потоковой передачи клиента позволяет довольно естественный фрагмент, так как он имеет управление потоком, конвейеризацию и легко поддерживать контекст в коде клиента и сервера. Если вы заботитесь о восстановление частичных загрузок, затем двунаправленная потоковая передача работает хорошо, так как сервер может отвечать подтверждением прогресса, который клиент может использовать для возобновления.
Chunking с использованием отдельных RPCs также возможно, но имеет больше осложнений. При балансировке нагрузки бэкэнд может потребоваться для координации с другими бэкэндами каждого фрагмента. Если вы загружаете куски последовательно, то задержка сети может замедлить скорость загрузки, поскольку вы проводите большую часть времени в ожидании получать ответы от сервера. Вам тогда либо придется загружать параллельно (но сколько параллельно?) или увеличить размер куска. Но увеличение размера куска увеличивает память, необходимую для обработки каждого куска, и увеличивает степень детализации для восстановления неудачных загрузок. Параллельная загрузка также требует, чтобы сервер обрабатывал неупорядоченные загрузки.
решение, предусмотренное в вопросе, не будет работать для файлов больших размеров. он будет работать только для меньших размеров изображения. лучший и стандартный подход - использовать chunking. grpc поддерживает потоковое встроенное. таким образом, это довольно легко отправить кусками
syntax = 'proto3'
message UploadImageRequest{
bytes image = 1;
}
rpc UploadImage(stream UploadImageRequest) returns (Ack);
выше мы можем использовать потоковую передачу для chunking.
для chunking все языки обеспечивают свой собственный путь к файлу chunk на основе размера куска.
вещи, чтобы взять уход:
вам нужно обрабатывать логику чанкинга, потоковая передача помогает в отправке естественным образом. если вы хотите отправить метаданные, также есть три подхода.
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);
наконец, для auth вы можете использовать заголовки вместо отправки этого в сообщении.