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 — більшість публічних Google API використовують Protobuf
  • Envoy Proxy — використовує Protobuf для конфігурації та обміну даними

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

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

Кожне поле в повідомленні Protobuf має унікальний номер (номер поля) — це не порядковий номер, а тег, що використовується в бінарному форматі для ідентифікації поля. Номери від 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-бітне число з плаваючою крапкою
float float float 32-бітне число з плаваючою крапкою
int32 int32 int 32-біт, кодування змінної довжини
int64 int64 long 64-біт, кодування змінної довжини
string string String Рядок UTF-8
bytes string ByteString Довільні байти
bool bool boolean true / false

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

Protobuf дає три ключові переваги порівняно з текстовими форматами: розмір повідомлення, швидкість серіалізації та сувора типізація. У високонавантажених системах та мобільних додатках з обмеженим трафіком ці переваги стають критичними.

Бінарне представлення Protobuf використовує кодування змінної довжини (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 — бінарний формат з обов’язковою схемою, у 3-10 разів компактніший за JSON. 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), додавайте нові поля з новими номерами. Старі клієнти ігнорують невідомі поля, нові клієнти отримують значення за замовчуванням для відсутніх старих полів.

Підсумки

  • Protocol Buffers — бінарний формат серіалізації від Google з обов’язковою схемою даних
  • Розмір повідомлень у 3-10 разів менший за JSON завдяки Varint-кодуванню
  • Швидкість серіалізації та десеріалізації вища за текстові формати
  • .proto схеми забезпечують сувору типізацію та генерацію коду для 12+ мов
  • Зворотня сумісність дозволяє еволюціонувати API без пошкодження клієнтів
  • gRPC використовує Protobuf як стандартний формат для мікросервісної комунікації
  • Ідеальний для високонавантажених систем та мобільних додатків з обмеженим трафіком

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

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