Protocol Buffers (Protobuf), Google tarafından hizmetler arasında verimli bilgi alışverişi için geliştirilmiş, yapılandırılmış veriler için ikili bir serileştirme formatıdır. Format, .proto dosyalarında önceden şema tanımlaması gerektirir ve bu dosyalardan çeşitli diller için kod üretilir. Google'ın resmi dokümantasyonuna göre Protobuf, JSON'dan 3-10 kat daha küçük mesaj boyutları sağlar. Protobuf, gRPC, Google Maps ve binlerce iç hizmette kullanılır.
Önemli Noktalar
Protocol Buffers, Google tarafından geliştirilen, JSON ve XML'e benzer, ancak temel bir farkı olan yapılandırılmış veri serileştirme mekanizmasıdır: veriler ikili formatta kodlanır. Bu, bir Protobuf mesajının çıplak gözle okunamayacağı, ancak metin tabanlı benzerlerine göre önemli ölçüde daha az yer kapladığı ve daha hızlı işlendiği anlamına gelir.
Protobuf, hizmetler arasındaki veri alışverişindeki performans sorunlarını çözmek için Google içinde oluşturuldu. 2008'de teknoloji, birçok dili destekleyen açık kaynak projesi haline geldi: C++, Java, Python, Go, JavaScript, Kotlin, Swift, Dart ve diğerleri. 2016'da yayınlanan proto3 sürümü, sözdizimini basitleştirdi ve daha fazla dil için destek ekledi.
Protobuf ve JSON arasındaki temel fark, veri alışverişi başlamadan önce bir şema tanımlama gerekliliğidir. Şema dosyası (.proto), mesaj yapısını açıklar: alanlar, türler ve benzersiz alan numaraları. Bu şemadan, protoc derleyicisi, serileştirme ve deserileştirme için hedef dilde sınıflar üretir.
Protobuf Mimarisi üç temel bileşen içerir: şema tanımlama dili (.proto), protoc derleyicisi ve belirli diller için çalışma zamanı kütüphaneleri. Geliştirici, .proto dosyasında veri yapısını tanımlar, derlemeyi çalıştırır ve bu verilerle çalışmak için hazır sınıflar alır.
Bir Protobuf mesajındaki her alanın benzersiz bir numarası (alan numarası) vardır — bu sıralı bir numara değil, ikili formatta alanı tanımlamak için kullanılan bir etikettir. 1'den 15'e kadar olan numaralar bir baytta, 16'dan 2047'ye kadar olanlar iki baytta kodlanır. Bu nedenle, sık kullanılan önemli alanlar, boyutu optimize etmek için 1'den 15'e kadar numaralandırılmalıdır.
Protobuf geniş bir yelpazede türü destekler: skaler (int32, int64, float, double, bool, string, bytes), numaralandırmalar (enum), bileşik (message) ve özel türler (oneof, map). Her tür, ilgili kullanım durumu için optimize edilmiş belirli bir ikili gösterime sahiptir.
| .proto Türü | C++ Türü | Java/Kotlin | Açıklama |
|---|---|---|---|
| double | double | double | 64-bit kayan noktalı sayı |
| float | float | float | 32-bit kayan noktalı sayı |
| int32 | int32 | int | 32-bit, değişken uzunluklu kodlama |
| int64 | int64 | long | 64-bit, değişken uzunluklu kodlama |
| string | string | String | UTF-8 dizesi |
| bytes | string | ByteString | Rastgele baytlar |
| bool | bool | boolean | true / false |
Protobuf, metin tabanlı formatlara göre üç temel avantaj sunar: mesaj boyutu, serileştirme hızı ve güçlü tür belirtimi. Yüksek yüklü sistemlerde ve sınırlı trafiğe sahip mobil uygulamalarda bu avantajlar kritik hale gelir.
Protobuf'un ikili gösterimi, sayılar için değişken uzunluklu kodlama (Varint) kullanır: küçük sayılar 1 bayt, büyük sayılar 10 bayta kadar yer kaplar. Bu, JSON veya XML'de metin dizeleri olarak onlarca bayt kaplayacak tanımlayıcıların, bayrakların ve sayaçların verimli bir şekilde kodlanmasını sağlar. Örneğin, 150 sayısı Protobuf'ta 2 bayt, JSON'da 3 bayt (metin olarak “150”), XML'de 3 bayt + etiketler yer kaplar.
Ek bir avantaj da geriye uyumluluktur. Şemaya yeni bir alan eklemek eski istemcileri bozmaz: bilinmeyen alanları yok sayarlar. Bir alanı silmek, gelecekte çakışmaları önlemek için yalnızca numarasını ayırmayı gerektirir.
.proto şeması veri yapısını özel bir dilde tanımlar. Dosya, sözdizimini (proto3), paketi ve import bağımlılıklarını belirterek başlar. Her mesaj, alanlarıyla birlikte message anahtar sözcüğüyle tanımlanır ve her alanın bir türü, adı ve benzersiz numarası vardır.
İyi şema uygulamaları: sık kullanılan alanlar için 1'den 15'e alan numaraları, anlamlı adlar, ilgili alanları ayrı bir message'da gruplama, yalnızca birkaç seçenekten biri olabilen alanlar için oneof kullanımı.
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;
}
Mesajlar iç içe olabilir: Profile türündeki bir profile alanı içinde kullanıcı verilerini barındırır. İç içe yerleştirme desteği, tanımları tekrarlamadan karmaşık hiyerarşik yapıları tanımlamaya olanak tanır.
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;
}
protoc derleyicisi .proto dosyalarını hedef dilde kaynak koda dönüştürür. Kotlin/Java için --java_out parametresi, Swift için --swift_out (Apple Swift Protobuf eklentisi aracılığıyla), Dart için --dart_out kullanılır. Üretilen sınıflar, mesajları oluşturmak için builder yöntemleri ve serileştirme/deserileştirme yöntemlerini içerir.
Android'de Protobuf ile çalışmak için Gradle'da com.google.protobuf eklentisi 0.9+ sürümü kullanılır. Eklentiyi ekledikten ve .proto dosyalarını belirttikten sonra, derleme otomatik olarak uygulamada kullanıma hazır Kotlin sınıfları üretir.
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 {
// İkili biçimde serileştirme
val bytes = user.toByteArray()
// İkili biçimden deserileştirme
return User.parseFrom(bytes)
}
Protobuf, mikro hizmet mimarisinde ve mobil uygulamalarda özellikle etkilidir. Tipik bir senaryo düşünelim: bir mobil uygulama, gRPC aracılığıyla sunucudan bir ürün listesi alır. Protobuf mesajı, tanımlayıcı, ad, fiyat ve kategori dahil olmak üzere ürün bilgilerini içerir. İkili format, yanıt boyutunu JSON'a kıyasla 5-8 kat azaltır.
Sunucu tarafında Protobuf ile bir gRPC hizmeti örneği. Hizmet, sayfalama parametreleriyle bir isteği kabul eden ve ürün listesini döndüren GetProducts RPC yöntemini bildirir. Kotlin uygulaması, istekler ve yanıtlarla çalışmak için üretilen sınıfları kullanır.
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()
}
}
Android projesinde Protobuf kurulumu, com.google.protobuf Gradle eklentisi aracılığıyla yapılır. Eklenti, derleme sırasında otomatik olarak protoc derleyicisini çalıştırır ve .proto dosyalarından Kotlin sınıfları üretir. Çalışması için, eklentiyi proje düzeyindeki build.gradle dosyasına eklemeniz ve uygulama modülünde uygulamanız gerekir.
Gradle'ı yapılandırdıktan sonra, .proto dosyaları src/main/proto dizinine yerleştirilir. protoc derleyicisi her derlemede bunları işleyerek uygulama kodunda kullanılabilecek Kotlin sınıfları üretir. Projenin diğer kütüphaneleriyle bağımlılık çakışmalarını önlemek için protobuf ve protoc sürümlerini doğru belirtmek önemlidir.
iOS projeleri için Protobuf, CocoaPods veya Swift Package Manager aracılığıyla bağlanır. Swift Protobuf eklentisi, Codable protokolüne uygun Swift yapılarını otomatik olarak üretir. Flutter için Dart projelerinde protobuf paketi kullanılır ve derleme dart run protoc_plugin aracılığıyla yapılır.
Sıkça Sorulan Sorular
Protobuf, zorunlu şeması olan ikili bir formattır, JSON'dan 3-10 kat daha sıkıştırılmıştır. JSON metin tabanlıdır, insan tarafından okunabilir ve şema gerektirmez. Protobuf daha hızlı serileştirir ve deserileştirir ancak .proto dosyalarının derlenmesini gerektirir. JSON'da hata ayıklamak daha kolaydır ve önceden yapılandırma gerektirmez.
protoc'yu platformunuz için protobuf GitHub sürümünden indirin. macOS için brew install protobuf ile kurun. Windows için zip arşivini indirin ve protoc.exe'yi PATH'e ekleyin. Android/Kotlin için, derleme sırasında otomatik olarak derlemeyi çalıştıran com.google.protobuf Gradle eklentisini kullanın.
gRPC, Protobuf'u arabirim tanımlama dili (IDL) ve serileştirme formatı olarak kullanan, Google tarafından geliştirilmiş yüksek performanslı bir RPC çerçevesidir. gRPC, .proto dosyalarında hizmetleri ve RPC yöntemlerini tanımlar, istemci ve sunucu kodu üretir ve akış ve ikili protokolleri destekler.
Google tarafından resmi olarak desteklenenler: C++, Java, Kotlin, Python, Go, Ruby, C#, PHP, JavaScript, Objective-C, Swift ve Dart. Topluluk, Rust, TypeScript, Scala, Lua ve diğer diller için destek geliştirmiştir. Mobil geliştirme için Kotlin/Java (Android) ve Swift/Objective-C (iOS) mevcuttur.
Protobuf şu kurallarla geriye uyumluluğu destekler: alan numaralarını değiştirmeyin, alanları silmeyin (reserved kullanın), yeni numaralarla yeni alanlar ekleyin. Eski istemciler bilinmeyen alanları yok sayar, yeni istemciler eksik eski alanlar için varsayılan değerler alır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun