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 вы можете использовать заголовки вместо отправки этого в сообщении.