Protocol Buffers (Protobuf) je binární formát serializace strukturovaných dat, vyvinutý společností Google pro efektivní výměnu informací mezi službami. Formát vyžaduje předchozí definici schématu v .proto souborech, ze kterých je generován kód pro různé jazyky. Podle oficiální dokumentace Google, Protobuf zajišťuje velikost zpráv 3-10krát menší než JSON. Protobuf se používá v gRPC, Google Maps a tisících interních služeb.
Hlavní body
Protocol Buffers je mechanismus serializace strukturovaných dat vyvinutý společností Google, podobný JSON a XML, ale se zásadním rozdílem: data jsou kódována v binárním formátu. To znamená, že zprávu Protobuf nelze přečíst pouhým okem, ale zabírá podstatně méně místa a je zpracovávána rychleji než textové alternativy.
Protobuf byl vytvořen interně v Google pro řešení výkonnostních problémů při výměně dat mezi službami. V roce 2008 se technologie stala open-source projektem s podporou mnoha jazyků: C++, Java, Python, Go, JavaScript, Kotlin, Swift, Dart a dalších. Verze proto3, vydaná v roce 2016, zjednodušila syntaxi a přidala podporu pro více jazyků.
Klíčový rozdíl mezi Protobuf a JSON je nutnost definice schématu před zahájením výměny dat. Soubor schématu (.proto) popisuje strukturu zprávy: pole, typy a jedinečná čísla polí. Z tohoto schématu kompilátor protoc generuje třídy v cílovém jazyce pro serializaci a deserializaci.
Architektura Protobuf zahrnuje tři klíčové komponenty: jazyk definice schématu (.proto), kompilátor protoc a runtime knihovny pro konkrétní jazyky. Vývojář popíše strukturu dat v .proto souboru, spustí kompilaci a získá hotové třídy pro práci s těmito daty.
Každé pole ve zvěsti Protobuf má jedinečné číslo (field number) — není to pořadové číslo, ale tag používaný v binárním formátu k identifikaci pole. Čísla 1 až 15 jsou kódována jedním bytem, čísla 16 až 2047 dvěma byty. Proto důležitá pole s vysokou frekvencí použití by měla být číslována 1 až 15 pro optimalizaci velikosti.
Protobuf podporuje širokou škálu typů: skálární (int32, int64, float, double, bool, string, bytes), výčtové (enum), složené (message) a speciální (oneof, map). Každý typ má specifickou binární reprezentaci optimalizovanou pro odpovídající scénář použití.
| Typ .proto | Typ C++ | Java/Kotlin | Popis |
|---|---|---|---|
| double | double | double | 64-bit číslo s plovoucí čárkou |
| float | float | float | 32-bit číslo s plovoucí čárkou |
| int32 | int32 | int | 32-bit, variable-length encoding |
| int64 | int64 | long | 64-bit, variable-length encoding |
| string | string | String | UTF-8 řetězec |
| bytes | string | ByteString | Libovolné bajty |
| bool | bool | boolean | true / false |
Protobuf poskytuje tři klíčové výhody oproti textovým formátům: velikost zprávy, rychlost serializace a přísné typování. Ve vysoce zatížených systémech a mobilních aplikacích s omezeným provozem se tyto výhody stávají kritickými.
Binární reprezentace Protobuf používá variable-length encoding (Varint) pro čísla: malá čísla zabírají 1 byte, velká až 10 bytů. To umožňuje efektivní kódování identifikátorů, příznaků a čítaček, které by v JSON nebo XML zabíraly desítky bytů jako textové řetězce. Například číslo 150 v Protobuf zabírá 2 byty, v JSON 3 byty (jako text „150”), v XML 3 byty + značky.
Další výhodou je zpětná kompatibilita. Přidání nového pole do schématu neporuší staré klienty: jednoduše ignorují neznámá pole. Odstranění pole vyžaduje pouze rezervaci jeho čísla, aby se předešlo kolizím v budoucnu.
Schéma .proto popisuje strukturu dat ve speciálním jazyce. Soubor začíná specifikací syntaxe (proto3), balíčku a importu závislostí. Každá zpráva je definována klíčovým slovem message s poli, kde každé pole má typ, název a jedinečné číslo.
Pravidla dobrého schématu: čísla polí 1 až 15 pro často používaná pole, smysluplné názvy, seskupování souvisejících polí do samostatných message, použití oneof pro pole, která mohou být pouze jednou z několika variant.
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;
}
Zprávy mohou být vnořené: pole profile typu Profile bude obsahovat data uživatele. Podpora vnořování umožňuje popisovat složité hierarchické struktury bez duplikování definic.
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;
}
Kompilátor protoc převádí .proto soubory do zdrojového kódu v cílovém jazyce. Pro Kotlin/Java se používá parametr --java_out, pro Swift --swift_out (prostřednictvím pluginu Apple Swift Protobuf), pro Dart --dart_out. Generované třídy obsahují builder metody pro konstrukci zpráv a metody serializace/deserializace.
Na Androidu se pro práci s Protobuf používá plugin com.google.protobuf verze 0.9+ v Gradle. Po přidání pluginu a specifikaci .proto souborů kompilace automaticky generuje Kotlin třídy připravené k použití v aplikaci.
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 {
// Serializace do binárního formátu
val bytes = user.toByteArray()
// Deserializace z binárního formátu
return User.parseFrom(bytes)
}
Protobuf je obzvláště efektivní v mikroslužbové architektuře a mobilních aplikacích. UvaŽme typický scénář: mobilní aplikace získává seznam produktů ze serveru přes gRPC. Zpráva Protobuf obsahuje informace o produktu, včetně identifikátoru, názvu, ceny a kategorie. Binární formát zmenšuje velikost odpovědi 5-8krát ve srovnání s JSON.
Příklad gRPC služby s Protobuf na serverové straně. Služba deklaruje RPC metodu GetProducts, která přijímá požadavek s parametry stránkování a vrátí seznam produktů. Implementace v Kotlin používá generované třídy pro práci s požadavky a odpověďmi.
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()
}
}
Nastavení Protobuf v projektu Android se provádí pomocí Gradle pluginu com.google.protobuf. Plugin automaticky spouští kompilátor protoc při kompilaci a generuje Kotlin třídy z .proto souborů. Pro fungování je třeba přidat plugin do build.gradle na úrovni projektu a použít jej v modulu aplikace.
Po nastavení Gradle se .proto soubory umísťují do adresáře src/main/proto. Kompilátor protoc je zpracovává při každé kompilaci a generuje Kotlin třídy, které lze použít v kódu aplikace. Je důležité správně specifikovat verze protobuf a protoc, aby se předešlo konfliktům závislostí s ostatními knihovnami projektu.
Pro iOS projekty se Protobuf připojuje přes CocoaPods nebo Swift Package Manager. Plugin Swift Protobuf automaticky generuje Swift struktury odpovídající protokolu Codable. V Dart projektech pro Flutter se používá balíček protobuf a kompilace se provádí přes dart run protoc_plugin.
Často kladené otázky
Protobuf — binární formát s povinným schématem, 3-10krát kompaktnější než JSON. JSON — textový, člověkem čitelný, nevyžaduje schéma. Protobuf se rychleji serializuje a deserializuje, ale vyžaduje kompilaci .proto souborů. JSON je snazší na ladění a nevyžaduje předchozí nastavení.
Stáhněte protoc z GitHub vydání protobuf pro vaši platformu. Pro macOS nainstalujte přes brew install protobuf. Pro Windows stáhněte zip archiv a přidejte protoc.exe do PATH. Pro Android/Kotlin použijte Gradle plugin com.google.protobuf, který automaticky spouští kompilaci při sestavení.
gRPC je výkonný RPC framework od Google, který používá Protobuf jako jazyk rozhraní (IDL) a serializační formát. gRPC definuje služby a RPC metody v .proto souborech, generuje klientský a serverový kód, podporuje streamování a binární protokoly.
Google oficiálně podporuje: C++, Java, Kotlin, Python, Go, Ruby, C#, PHP, JavaScript, Objective-C, Swift a Dart. Komunita vyvinula podporu pro Rust, TypeScript, Scala, Lua a další jazyky. Pro mobilní vývoj jsou k dispozici Kotlin/Java (Android) a Swift/Objective-C (iOS).
Protobuf podporuje zpětnou kompatibilitu prostřednictvím pravidel: neměňte čísla polí, nemažte pole (použijte reserved), přidávejte nová pole s novými čísly. Staří klienti ignorují neznámá pole, noví klienti dostávají výchozí hodnoty pro chybějící stará pole.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také