Protocol Buffers (Protobuf) – механизм бинарной сериализации данных, разработанный компанией Google. Протокол не зависит от языка и платформы, и обеспечивает более компактную и быструю сериализацию по сравнению с традиционными текстовыми форматами.
Как работает Protobuf

Описание данных в .proto файле
Все начинается с описания структуры данных в файле с расширением .proto. В этом файле используется простой синтаксис, независимый от языка программирования:
syntax = "proto3";
message Person {
required string name = 1;
optional int32 age = 2;
repeated string hobbies = 3;
}
- required – обязательные поля (запуск программы завершится с ошибкой, если они не заполнены).
- optional – необязательные поля.
- repeated – поле может встречаться несколько раз (используется для списков и массивов).
Генерация кода с помощью компилятора protoc
После того как структура данных определена, используется компилятор protoc, который генерирует код для работы с этой структурой на нужном языке. Здесь генерируется код на C#, но Protobuf поддерживает множество других популярных языков – Python, Java, Go и т.д.:
protoc -I=$SRC_DIR --csharp_out=$DST_DIR $SRC_DIR/person.proto
Сериализация и десериализация данных
После генерации кода можно работать с данными в бинарном формате, используя методы сериализации и десериализации, созданные компилятором. Примеры на C#:
- Сериализация (преобразование данных в компактный бинарный формат):
using Google.Protobuf;
Person mario = new Person
{
Name = "Супер Марио",
Age = 43,
Hobbies = {"Собирать грибы", "Спасать принцесс"}
};
using (var output = File.Create("mario.dat"))
{
mario.WriteTo(output);
}
Десериализация (преобразование бинарных данных обратно в объект):
Person mario;
using (var input = File.OpenRead("mario.dat"))
{
mario = Person.Parser.ParseFrom(input);
}
Совместимость версий
Одно из ключевых преимуществ Protobuf – поддержка эволюции схемы без нарушения совместимости между старыми и новыми версиями кода: старый код может читать сообщения, созданные новым кодом, и наоборот. Совместимость достигается благодаря тому, что каждому полю в .proto-файле присваивается уникальный тег. Когда данные сериализуются, Protobuf использует эти номера для идентификации полей, и в результате совместимость реализуется так:
- Добавление поля – если вы добавили новое поле, старый код его проигнорирует.
- Удаление поля – новый код сможет работать с данными, созданными старым кодом.
Изменение типов полей – чуть более сложный вопрос, поскольку одни изменения безопасны, а другие могут привести к неожиданным последствиям. Например, изменение типа с int32 на int64 обычно безопасно, потому что парсер может заполнить недостающие биты нулями. Однако, если старый код пытается прочитать данные, созданные новым кодом, произойдет усечение значения. Это связано с тем, что старый код по-прежнему хранит значение в 32-битной переменной, и при попытке сохранить 64-битное значение в 32-битный тип, лишние биты будут отброшены.
В двух словах
Текстовые форматы обеспечивают простоту чтения, отладки и совместимость с широким набором инструментов, что делает их подходящими для веб-приложений и ситуаций, где человекопонятность важна. Однако они страдают от избыточности и могут иметь проблемы с производительностью и обработкой бинарных данных.
С другой стороны, бинарная кодировка обеспечивает компактность, высокую скорость сериализации и десериализации, а также более точное представление типов данных. Бинарный формат особенно полезен в высоконагруженных системах и для передачи данных между внутренними сервисами, где важны производительность и экономия ресурсов.
А вы уже использовали Protocol Buffers в своих проектах? Поделитесь своим опытом и расскажите, с какими трудностями столкнулись при внедрении.
Комментарии