Пост, который вы указали, верный. В качестве входных данных вы будете использовать один буфер протокола и, как правило, он должен называться как «FooRequest». То же самое относится и к объекту ответа, который должен называться что-то вроде «FooResponse». Отделение объектов запроса и ответа от их содержимого даст вам возможность со временем изменить свой API обратно-совместимым образом.
Тот факт, что мы не поддерживаем несколько типов запросов, на практике не является препятствием,потому что протос может быть вложен произвольно. Рассмотрим такой API.
message FileData {
string filename = 1;
bytes data = 2;
}
message UploadRequest {
oneof payload {
string filename = 1;
FileData file_data = 2;
}
}
service KeyValueStore {
rpc upload (stream UploadRequest) returns (UploadResponse) {}
}
Конечно, с точки зрения сервера, теперь неправильно работающий клиент может отправлять имя файла в середине потока. Или, наоборот, начать отправку фрагментов данных без предварительной отправки имени файла.
Вы можете решить, что клиент должен отправить имя файла в качестве первого сообщения. Или, возможно, все в порядке, если имя файла отправляется до окончания потока. Или, возможно, отправка имени файла является совершенно необязательной, и ее не может привести к значению по умолчанию для имени файла.
Ваше решение по этим пунктам будет частью вашего API, но not будет автоматически реализован protobuf как IDL. Вам нужно явно обработать эти угловые случаи в коде вашего сервера. Помните, однако, что, поскольку это соображения API, они должны записываться где-то в вашем файле protobuf. Сделайте все возможное, чтобы каждое сообщение, RPC и поле имели четкую и краткую строку документации.