Protobuf — что это, бинарный формат данных и принцип работы

Автор: IT Sectr Опубликовано: 2026-03-08 Время чтения: 8 мин

Protocol Buffers (Protobuf) — это бинарный формат сериализации структурированных данных, разработанный Google для эффективного обмена информацией между сервисами. Формат требует предварительного определения схемы в .proto файлах, из которых генерируется код для различных языков. По данным официальной документации Google, Protobuf обеспечивает размер сообщений в 3-10 раз меньше JSON. Protobuf используется в gRPC, Google Maps и тысячах внутренних сервисов.

Главное

  • Protobuf — бинарный формат от Google для сериализации с компактным представлением данных
  • .proto схемы — строго типизированное описание структуры данных с компиляцией в код
  • Производительность — сериализация в 3-10 раз быстрее и компактнее JSON
  • Обратная совместимость — эволюция схем без поломки существующих клиентов
  • gRPC — основная транспортная технология для Protobuf в микросервисах

Что такое Protocol Buffers?

Protocol Buffers — это разработанный Google механизм сериализации структурированных данных, аналогичный JSON и XML, но с принципиальным отличием: данные кодируются в бинарный формат. Это означает, что сообщение Protobuf невозможно прочитать невооружённым глазом, но оно занимает значительно меньше места и обрабатывается быстрее текстовых аналогов.

Protobuf был создан внутри Google для решения проблем производительности при обмене данными между сервисами. В 2008 году технология стала открытым проектом с поддержкой множества языков: C++, Java, Python, Go, JavaScript, Kotlin, Swift, Dart и других. Версия proto3, выпущенная в 2016 году, упростила синтаксис и добавила поддержку большего количества языков.

Ключевое отличие Protobuf от JSON — необходимость определения схемы до начала обмена данными. Файл схемы (.proto) описывает структуру сообщения: поля, типы и уникальные номера полей. Из этой схемы компилятор protoc генерирует классы на целевом языке для сериализации и десериализации.

Экосистема Protobuf

  • gRPC — высокопроизводительный RPC-фреймворк, использующий Protobuf по умолчанию
  • protoc — компилятор схем .proto в код на разных языках программирования
  • Google API — большинство публичных API Google используют Protobuf
  • Envoy Proxy — использует Protobuf для конфигурации и обмена данными

Архитектура Protobuf

Архитектура Protobuf включает три ключевых компонента: язык определения схемы (.proto), компилятор protoc и runtime-библиотеки для конкретных языков. Разработчик описывает структуру данных в .proto файле, запускает компиляцию и получает готовые классы для работы с этими данными.

Каждое поле в сообщении Protobuf имеет уникальный номер (field number) — это не порядковый номер, а тег, используемый в бинарном формате для идентификации поля. Номера от 1 до 15 кодируются одним байтом, от 16 до 2047 — двумя. Поэтому важные поля с высокой частотой использования стоит нумеровать от 1 до 15 для оптимизации размера.

Типы данных Protobuf

Protobuf поддерживает широкий спектр типов: скалярные (int32, int64, float, double, bool, string, bytes), перечисления (enum), составные (message) и специальные (oneof, map). Каждый тип имеет определённое бинарное представление, оптимизированное под соответствующий сценарий использования.

Тип .proto C++ тип Java/Kotlin Описание
double double double 64-bit число с плавающей точкой
float float float 32-bit число с плавающей точкой
int32 int32 int 32-bit, variable-length encoding
int64 int64 long 64-bit, variable-length encoding
string string String UTF-8 строка
bytes string ByteString Произвольные байты
bool bool boolean true / false

Преимущества бинарного формата

Protobuf даёт три ключевых преимущества перед текстовыми форматами: размер сообщения, скорость сериализации и строгая типизация. В высоконагруженных системах и мобильных приложениях с ограниченным трафиком эти преимущества становятся критически важными.

Бинарное представление Protobuf использует variable-length encoding (Varint) для чисел: маленькие числа занимают 1 байт, большие — до 10 байт. Это позволяет эффективно кодировать идентификаторы, флаги и счётчики, которые в JSON или XML заняли бы десятки байт в виде текстовых строк. Например, число 150 в Protobuf занимает 2 байта, в JSON — 3 байта (как текст "150"), в XML — 3 байта + теги.

Дополнительное преимущество — обратная совместимость. Добавление нового поля в схему не ломает старых клиентов: они просто игнорируют неизвестные поля. Удаление поля требует лишь резервирования его номера, чтобы избежать коллизий в будущем.

Определение схемы .proto

Схема .proto описывает структуру данных на специальном языке. Файл начинается с указания синтаксиса (proto3), пакета и импорта зависимостей. Каждое сообщение определяется ключевым словом message с полями, где каждое поле имеет тип, имя и уникальный номер.

Правила хорошей схемы: номера полей от 1 до 15 для часто используемых полей, осмысленные имена, группировка связанных полей в отдельные message, использование oneof для полей, которые могут быть только одним из нескольких вариантов.

protobuf
syntax = "proto3";

package mobileapp;

message User {
  string user_id = 1;
  string name = 2;
  string email = 3;
  int32 age = 4;
  UserRole role = 5;
  repeated string tags = 6;
  map<string, string> metadata = 7;
}

enum UserRole {
  USER_ROLE_UNSPECIFIED = 0;
  USER_ROLE_USER = 1;
  USER_ROLE_ADMIN = 2;
  USER_ROLE_MODERATOR = 3;
}

Вложенные сообщения

Сообщения могут быть вложенными: поле profile типа Profile будет содержать внутри себя данные пользователя. Поддержка вложенности позволяет описывать сложные иерархические структуры без дублирования определений.

protobuf
syntax = "proto3";

package mobileapp;

message Order {
  string order_id = 1;
  repeated OrderItem items = 2;
  double total_price = 3;
  PaymentInfo payment = 4;
}

message OrderItem {
  string product_id = 1;
  string title = 2;
  int32 quantity = 3;
  double price = 4;
}

message PaymentInfo {
  string method = 1;
  string transaction_id = 2;
  double amount = 3;
}

Генерация кода из .proto

Компилятор protoc преобразует .proto файлы в исходный код на нужном языке. Для Kotlin/Java используется параметр --java_out, для Swift --swift_out (через плагин Apple Swift Protobuf), для Dart --dart_out. Сгенерированные классы содержат builder-методы для конструирования сообщений и методы сериализации/десериализации.

На Android для работы с Protobuf используется плагин com.google.protobuf версии 0.9+ в Gradle. После добавления плагина и указания .proto файлов, сборка автоматически генерирует Kotlin-классы, готовые к использованию в приложении.

kotlin
import com.google.protobuf.kotlin.toByteString
import com.example.mobileapp.UserOuterClass.User

fun createUser(): User {
    return User.newBuilder()
        .setUserId("usr_001")
        .setName("IT Sectr")
        .setEmail("team@itsectr.com")
        .setAge(5)
        .setRole(UserOuterClass.UserRole.USER_ROLE_ADMIN)
        .addTags("mobile")
        .addTags("backend")
        .build()
}

fun serializeAndDeserialize(user: User): User {
    // Сериализация в бинарный формат
    val bytes = user.toByteArray()

    // Десериализация из бинарного формата
    return User.parseFrom(bytes)
}

Примеры использования Protobuf

Protobuf особенно эффективен в микросервисной архитектуре и мобильных приложениях. Рассмотрим типовой сценарий: мобильное приложение получает список товаров от сервера через gRPC. Сообщение Protobuf содержит информацию о товаре, включая идентификатор, название, цену и категорию. Бинарный формат сокращает размер ответа в 5-8 раз по сравнению с JSON.

gRPC сервис на Kotlin

Пример gRPC-сервиса с Protobuf на серверной стороне. Сервис объявляет RPC-метод GetProducts, который принимает запрос с параметрами пагинации и возвращает список товаров. Реализация на Kotlin использует сгенерированные классы для работы с запросами и ответами.

kotlin
import com.example.mobileapp.ProductServiceGrpcKt
import com.example.mobileapp.ProductOuterClass.Product
import com.example.mobileapp.ProductOuterClass.GetProductsRequest
import com.example.mobileapp.ProductOuterClass.GetProductsResponse

class ProductService : ProductServiceGrpcKt.ProductServiceCoroutineImplBase() {

    override suspend fun getProducts(
        request: GetProductsRequest
    ): GetProductsResponse {
        val products = fetchProductsFromDb(
            page = request.page,
            limit = request.limit
        )

        return GetProductsResponse.newBuilder()
            .addAllProducts(products)
            .setTotalCount(products.size)
            .build()
    }
}

Настройка Protobuf в Android проекте

Настройка Protobuf в Android-проекте выполняется через Gradle-плагин com.google.protobuf. Плагин автоматически запускает компилятор protoc при сборке и генерирует Kotlin-классы из .proto файлов. Для работы требуется добавить плагин в build.gradle уровня проекта и применить его в модуле приложения.

После настройки Gradle .proto файлы размещаются в директории src/main/proto. Компилятор protoc обрабатывает их при каждой сборке, генерируя Kotlin-классы, которые можно использовать в коде приложения. Важно правильно указать версию protobuf и protoc, чтобы избежать конфликтов зависимостей с другими библиотеками проекта.

Для iOS-проектов Protobuf подключается через CocoaPods или Swift Package Manager. Плагин Swift Protobuf автоматически генерирует Swift-структуры, соответствующие протоколу Codable. В Dart-проектах для Flutter используется пакет protobuf, а компиляция выполняется через dart run protoc_plugin.

Часто задаваемые вопросы

В чём разница между Protobuf и JSON?

Protobuf — бинарный формат с обязательной схемой, компактнее JSON в 3-10 раз. JSON — текстовый, человекочитаемый, не требует схемы. Protobuf быстрее сериализуется и десериализуется, но требует компиляции .proto файлов. JSON проще в отладке и не требует предварительной настройки.

Как установить компилятор protoc?

Скачайте protoc с GitHub-релиза protobuf под вашу платформу. Для macOS установите через brew install protobuf. Для Windows скачайте zip-архив и добавьте protoc.exe в PATH. Для Android/Kotlin используйте Gradle-плагин com.google.protobuf, который автоматически запускает компиляцию при сборке.

Что такое gRPC и как он связан с Protobuf?

gRPC — это высокопроизводительный RPC-фреймворк от Google, использующий Protobuf в качестве интерфейсного языка (IDL) и формата сериализации. gRPC определяет сервисы и RPC-методы в .proto файлах, генерирует клиентский и серверный код, поддерживает потоковую передачу и бинарные протоколы.

Какие языки поддерживает Protobuf?

Google официально поддерживает: C++, Java, Kotlin, Python, Go, Ruby, C#, PHP, JavaScript, Objective-C, Swift и Dart. Сообщество разработало поддержку для Rust, TypeScript, Scala, Lua и других языков. Для мобильной разработки доступны Kotlin/Java (Android) и Swift/Objective-C (iOS).

Как обеспечить обратную совместимость схем?

Protobuf поддерживает обратную совместимость через правила: не изменяйте номера полей, не удаляйте поля (используйте reserved), добавляйте новые поля с новыми номерами. Старые клиенты игнорируют неизвестные поля, новые клиенты получают default-значения для отсутствующих старых полей.

Итоги

  • Protocol Buffers — бинарный формат сериализации от Google с обязательной схемой данных
  • Размер сообщений в 3-10 раз меньше JSON благодаря Varint-кодированию
  • Скорость сериализации и десериализации выше текстовых форматов
  • .proto схемы обеспечивают строгую типизацию и генерацию кода для 12+ языков
  • Обратная совместимость позволяет эволюционировать API без поломки клиентов
  • gRPC использует Protobuf как стандартный формат для микросервисной коммуникации
  • Идеален для высоконагруженных систем и мобильных приложений с ограниченным трафиком

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также