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 Описание
doubledoubledouble64-битово число с плаваща запетая
floatfloatfloat32-битово число с плаваща запетая
int32int32int32-битово, variable-length encoding
int64int64long64-битово, variable-length encoding
stringstringStringUTF-8 низ
bytesstringByteStringПроизволни байтове
boolboolbooleantrue / 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 е бинарен формат със задължителна схема, 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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също