38 puan yazan GN⁺ 2025-12-05 | 10 yorum | WhatsApp'ta paylaş
  • Web API’lerinin fiili standardı haline gelen JSON, okunması kolay ve esnek olsa da performans ve kararlılık açısından sınırlara sahip
  • Protobuf (Protocol Buffers), katı tip tanımı ve otomatik kod üretimi sayesinde veri yapısını açık biçimde garanti eder
  • İkili serileştirme kullanarak JSON’a kıyasla veri boyutunu yaklaşık 3 kat veya daha fazla azaltır ve iletim hızını artırır
  • Sunucu ve istemci aynı .proto şemasını paylaştığı için tip uyuşmazlığı veya manuel doğrulama gerekmez
  • Hata ayıklama daha zor olsa da performans, bakım kolaylığı ve geliştirme verimliliği açısından Protobuf modern API’ler için daha uygundur

JSON’un yaygınlığı ve sınırları

  • JSON, insanın kolay okuyabildiği bir metin formatıdır; veriyi yalnızca basit bir console.log() ile bile kontrol etmek mümkündür
  • Web ile kusursuz entegrasyonu sayesinde JavaScript ve backend framework ekosisteminde geniş çapta benimsenmiştir
  • Alan ekleme-silme-tip değiştirme konusunda serbestlik sağlayan esneklik sunar, ancak bu da yapı uyuşmazlığına veya hatalara yol açabilir
  • Araç ekosistemi zengindir; yalnızca bir metin editörü veya curl ile bile kolayca çalışılabilir
  • Ancak bu avantajlara rağmen performans ve tip güvenliği açısından daha iyi alternatifler vardır

Protobuf’a genel bakış

  • Google tarafından 2001’de geliştirilen ve 2008’de yayımlanan bir ikili serileştirme formatı
  • Dahili sistemlerde ve mikroservisler arası iletişimde yaygın olarak kullanılır
  • Sıklıkla gRPC ile birlikte kullanılmak zorunda olduğu sanılır, ancak Protobuf bağımsız olarak HTTP API’lerinde de kullanılabilir
  • Başlangıçta ikili formatın görünmezliği nedeniyle erişilebilirliği düşük görünse de verimlilik ve kararlılık açısından güçlüdür

Güçlü tip sistemi ve kod üretimi

  • Protobuf, .proto dosyaları üzerinden veri yapısını açıkça tanımlar
    • Her alanın katı bir tipi, sayısal tanımlayıcısı ve sabit bir adı vardır
  • Örnek:
    message User {
      int32 id = 1;
      string name = 2;
      string email = 3;
      bool isActive = 4;
    }
    
    Reklam
  • protoc komutuyla Dart, TypeScript, Kotlin, Swift, C#, Go, Rust gibi birçok dil için otomatik kod üretimi desteklenir
  • Üretilen kodla serileştirme (writeToBuffer) ve ters serileştirme (fromBuffer) yapılır; manuel doğrulama veya parse etme gerekmez
  • Sonuç olarak aynı anda hem zamandan tasarruf hem de bakım kolaylığında artış sağlanır

İkili serileştirmenin verimliliği

  • Protobuf, metin yerine ikili veri olarak serileştirildiği için son derece kompakt ve hızlıdır
  • Aynı verinin (User nesnesi) boyut karşılaştırması:
    • JSON: 86 bayt (boşluklar kaldırıldığında 68 bayt)
    • Protobuf: 30 bayt
  • Verimliliğin nedenleri:
    • Sayılar için varint encoding kullanılması
    • Metin anahtarlar yerine sayısal etiketler kullanılması
    • Boşlukların ve gereksiz sözdiziminin kaldırılması
    • Opsiyonel alan optimizasyonu
  • Sonuç olarak bant genişliği tasarrufu, yanıt hızında artış, mobil veri kullanımında azalma ve kullanıcı deneyiminde iyileşme sağlar

Dart tabanlı Protobuf API örneği

  • shelf paketi kullanılarak basit bir HTTP sunucusu kurulup User nesnesi Protobuf olarak döndürülür
  • Sunucu kodunun özü:
    • User() nesnesi oluşturulur ve writeToBuffer() ile serileştirilir
    • Yanıt başlığında 'content-type': 'application/protobuf' belirtilir
  • İstemci, http paketi ve user.pb.dart kullanarak Protobuf verisini doğrudan decode eder
  • Sunucu ve istemci aynı .proto şemasını paylaştığı için veri yapısı uyuşmazlığı oluşmaz
  • Aynı yaklaşım Go, Rust, Kotlin, Swift, C#, TypeScript gibi dillerde de aynı şekilde uygulanabilir
Reklam

JSON’un kalan avantajları

  • Protobuf’ta şema olmadan anlamı yorumlamak zordur
    • Alan adları yerine yalnızca sayısal tanımlayıcılar göründüğü için insan tarafından okunması zordur
  • Karşılaştırma örneği:
    • JSON: { "id": 42, "name": "Alice" }
    • Protobuf: 1: 42, 2: "Alice"
  • Bu yüzden Protobuf için:
    • Özel decode araçları gerekir
    • Şema yönetimi ve sürümleme zorunludur
  • Buna rağmen performans ve verimlilik avantajları çok daha büyüktür

Sonuç

  • Protobuf, olgun ve yüksek performanslı bir serileştirme teknolojisidir ve açık API’lerde de rahatlıkla kullanılabilir
  • gRPC olmadan da genel HTTP API içinde bağımsız şekilde çalışır
  • Performansı, sağlamlığı, hata azaltımını ve geliştirme verimliliğini birlikte iyileştiren bir araçtır
  • Yeni nesil projelerde Protobuf’u benimsemek için fazlasıyla geçerli nedenler vardır

10 yorum

 
tested 2025-12-09
 
onixboox 2025-12-08

https://msgpack.org/ buna ne dersiniz?

 
cosine20 2025-12-08

MessagePack de iyi.

 
savvykang 2025-12-06

Hata ayıklama için resmi bir decoder’ı bile olmayan bir formatın olgun olduğunu iddia etmenin çelişkili olduğunu düşünüyorum.

 
jjw9512151 2025-12-05

Her araçta olduğu gibi bunun da her derde deva bir çözüm olmadığını düşünüyorum ama Protobuf’un da fazlasıyla iyi bir araç olduğunu söyleyebilirim.
Özellikle gömülü ortamda, farklı dillere sahip istemcilere yüksek hacimli ve yüksek frekanslı (saniyede 20 kez) veri göndermem gereken bir durum olmuştu; o zaman nanopb ile bunu oldukça temiz bir şekilde halletmiştim.

 
ifmkl 2025-12-05

Bu kadar katı olunca XML'le gelmez mi zaten? :)

 
click 2025-12-06

Şema da DTD ile tanımlanıp parser tarafında önbelleğe alınırsa, şemanın yalnızca bir kez gönderilmesi gibi bir etki de olur sanırım.

 
bakyeono 2025-12-05
  • Benim hayalini kurduğum ikili format, şema tabanlı olup aynı zamanda mesajın içinde şemayı da barındıran bir yapı. Böyle olursa bir vim eklentisiyle doğrudan okunabilir. Milyonlarca nesneyle çalışırken 2 GB’lık bir mesaja 1 KB’lık şema eklemek büyük bir yük değil
  • Ancak web servislerinde çoğu zaman tam tersi oluyor; şema 200 KB, mesaj ise 1 KB olabiliyor. Bu durumda verimsiz

=> Şema zaten eninde sonunda en az bir kez gönderilmek zorunda değil mi? JSON’da da şema yok değil; sadece verinin içine örtük olarak gömülü durumda, yani aslında şema hiç gönderilmiyor değil. Hatta her bir öğe için şemayı tekrar tekrar gönderdiği için daha da verimsiz. "Şema tabanlı olup aynı zamanda mesajın içinde şemayı da barındıran bir yapı" fikri bence oldukça iyi görünüyor.

 
GN⁺ 2025-12-05
Hacker News yorumu
  • JSON çoğu zaman muğlak ya da garanti edilmeyen veriler göndermeye yol açar. Alan eksikliği, tip hataları, anahtar yazım yanlışları, belgelenmemiş yapılar gibi çeşitli sorunlar ortaya çıkar. Ancak Protobuf, mesaj yapısını .proto dosyalarıyla açıkça tanımlayarak bunun imkansız hale geldiğini savunan bir yazı vardı. Fakat bu, Protobuf’un felsefesini yanlış anlamaktır. proto3, required alanları hiç desteklemez. Resmi belgelerde de (Protobuf Best Practices) “required alanlar zararlı olduğu için kaldırıldı” deniyor. Sonuçta Protobuf istemcileri de JSON API’leri gibi savunmacı yazılmalıdır

    • Söz konusu blogda buna benzer birçok yanlış anlama var. Örneğin SVG kullanımına karşı çıkan yazıda, vektör formatının serbest ölçeklenebilirliği avantajı dikkate alınmıyor
    • Meselenin özü sadece dil ya da istemci/sunucu implementasyonu farkları. Ben Go’daki Marshalling kavramını kullanarak istemci tarafında Gooey framework’ünü kullanıyorum. Go’nun sınırlamalarını aşarsanız oldukça type-safe kullanılabiliyor. Yalnız json:"-" ile private alanları engellemek önemli. Projemi Gooey üzerinde görebilirsiniz
    • Bu yazı, serileştirme formatı ile sözleşme (Contract) kavramını birbirine karıştırıyor
    • Ağ sistemlerinde, kodlama biçiminden bağımsız olarak veri uyumsuzluğu (Skew) sorunu her zaman vardır. Yine de Protobuf, decode edildikten sonra statik tipli nesneler sağlar. JSON da doğrulanabilir ama çoğu zaman böyle yapılmaz. Sonunda JSON nesneleri oradan oraya dönüştürülür ve kimse iç yapısından emin olamaz hale gelir
    • Muhtemelen asıl yazar sadece Protobuf’ta eksik alanların varsayılan değerlerle başlatıldığını söylemek istiyordu. Bu, “required” alan kavramından farklıdır
  • Sıkıştırılmış JSON gayet kullanılabilir ve ilk iletişim maliyeti düşüktür. Elbette alanlar eksik olursa ya da tipler değişirse sorun çıkar, ama tamamen tiplenmiş yapılar tasarlayıp sürüm senkronizasyon süreçleri kurmaya çalışanların çoğu başarısız olur. Sonunda insan maliyeti daha düşük olan taraf kazanır. Bu yüzden JSON, daha düşük insan iletişim maliyeti sunan bir alternatif çıkana kadar ortadan kaybolmayacak

    • Evet. Çoğu mimar, gRPC gibi net bir ihtiyaç yoksa proto’yu değerlendirmiyor. console.log() ile anında debug edilebilen bir alternatif çıkmadıkça JSON yerini kaybetmeyecek
    • Debugging de JSON’un güçlü yönlerinden biri. Açıp okumak yeterli. Protobuf ise tooling gerektiriyor
    • Doğru. Ama insanlar tasarım aşamasında 15 dakika daha harcamak yerine, sonrasında 3 ay boyunca sorunları geriye dönük izlemeyi tercih ediyor
    • JSON, COBOL gibi tamamen yok olmaz belki ama yeni projelerde kullanmak için özel bir neden kalmadı
  • Protobuf kusursuz değil. Sunucu ve istemci farklı zamanlarda dağıtılıp spec sürümleri farklıysa güvenlik bozulur. ID’lerin yeniden kullanılmaması, unknown-field kopyalama gibi yöntemlerle bu hafifletilebilir ama dağıtık sistemler doğası gereği karmaşıktır. Yine de protobuf3, protobuf2’nin birçok sorununu çözdü. Eskiden varsayılan değerin özellikle mi verildiği yoksa alanın eksik mi olduğu anlaşılamıyordu; artık message tipiyle bu çözülebiliyor

    • Güvenli olmak için JSON ya da Protobuf fark etmeksizin sürüm uyumluluğu testleri CI pipeline’da zorunlu tutulmalı
    • Hangi tip sistemi olursa olsun, ağdan geçince bozulur
  • Yazıda “süper verimli” denmiş ama gzip’ten hiç bahsedilmiyor. Çoğu metin verisi zaten otomatik olarak sıkıştırılarak iletiliyor. Bu nedenle Protobuf, gzip’lenmiş JSON ile karşılaştırılmalı

    • Ben de çeşitli ikili formatları test ettim ama sonunda gzipped JSON ezici biçimde verimli çıktı
    • JSON’un dezavantajı serileştirme/ters serileştirme hızıdır. Geri kalan her şey kademeli olarak çözülebilir
    • Streaming Brotli/zstd JSON/HTML de düşünmeye değer. Bağlantı açıkken sıkıştırma penceresinden yararlanabilirsiniz
    • İlgili bir referans: Auth0’un Protobuf performans karşılaştırması yazısı
    • JSON ile mod_deflate kombinasyonu hissedilir derecede büyük fark yaratıyor
  • Daha iyi bir protokolü savunmak güzel ama Protobuf’un hem verimlilikte hem kullanılabilirlikte JSON’un yerini aldığını söylemek zor. Protobuf, katı şeması yüzünden JSON’un iyi olduğu alanları kaçırıyor. Hatta CBOR, JSON’un yerine geçmek için daha uygun olabilir. CBOR, JSON kadar esnek ama daha kompakt bir kodlamaya sahip

    • Ama Protobuf’un katı şeması aslında avantaj da olabilir. Çoğu API JSON şemasını yayınlamıyor. Ben ajv ya da superstruct ile doğrulama yaptım ama Protobuf’ta buna gerek yok
    • Keşke tarayıcılar CBOR API’sini doğrudan desteklese. İç implementasyon zaten var, bu yüzden zor olmamalı
  • 1984 tarihli ASN.1, Protobuf’un yaptığını daha esnek şekilde zaten yapıyordu. DER encoding kullanılırsa o kadar da kötü değil. ASN.1 DER örneğine bakabilirsiniz. Protobuf, başardığı şeye kıyasla gereğinden fazla karmaşık

    • ASN.1’in özelliği fazla. Her şeyi desteklerseniz aşırı karmaşık bir kütüphane olur, yalnızca bir kısmını desteklerseniz artık standart ASN.1 olmaz
    • Ben ASN.1 DER tercih ediyorum. C ile kendi DER encoder/decoder’ımı yazıp FOSS olarak yayımladım. Genişletilmiş bir “ASN.1X” oluşturarak JSON’un veri modelini tamamen kapsadım
    • Ama SNMP gibi sistemlerde ASN.1’in aşırı esnekliği bizzat sorun oldu. Her üretici canının istediği gibi genişletti
    • Google içinde de Protobuf serileştirme/ters serileştirmesi ciddi CPU tüketiyordu
    • ASN.1 overengineered; bu yüzden desteklemesi zor. Kalıtım gibi özellikler gereksiz
  • Tüm prodüksiyon sistemimi Protobuf ile kurdum ama yönetmesi başlı başına bir eziyetti. Teknik olarak iyi görünüyor ama pratikte JSON çok daha basit

    • JSON’un okunabilirliği ve debug kolaylığı küçümsenemez. Çoğu ekip kısa vadeli verim için JSON’u seçiyor
    • Ne tür sorunlar yaşandığını merak ediyorum. Benim deneyimimde Protobuf’un rahatsızlığına kıyasla JSON’daki veri bozulması riski daha büyük. Protobuf bunu derleme hatasıyla yakalıyor, JSON ise prodüksiyonda patlıyor
  • Protobuf harika ama zero-copy desteklememesi üzücü. Cap’n Proto gibi formatlar serileştirme/ters serileştirme darboğazını ortadan kaldırıyor

    • Ama pratikte zero-copy daha yavaş bile olabilir. Cache içindeki kopyalama neredeyse bedavadır, buna karşılık dinamik yapılarla doğrudan uğraşmak ek yük oluşturur. Çoğu durumda tek bir kopya (one-copy) yeterlidir
    • Bu, Cap’n Proto pazarlamasından çıkan bir iddia sadece; gerçekte performans farkı çok küçüktür. Her iki formatta da native tipler ↔ binary dönüşümü gerekir. Performans, payload’a bağlı olarak benzerdir
    • Bu, formatın değil kütüphane implementasyonunun sorunu da olabilir
  • Bir NodeJS projesinde tüm API’yi .proto ile tanımlayıp Content-Type’a göre proto ya da JSON dönen bir sunucu yazdım. Swagger’dan çok daha yapısal. Yalnız Google’ın böyle bir özelliği resmi kütüphane olarak sunmaması üzücü. gRPC ise HTTP/2 bağımlılığı nedeniyle kullanışsız. Ayrıca Text proto’nun en iyi statik yapılandırma dili olduğunu düşünüyorum

    • Bu tür bir amaç için Twirp uygun. Protobuf ya da JSON’u sade HTTP üzerinden ele alıyor
    • ConnectRPC da benzer bir yaklaşım sunuyor. Ancak destek kapsamı henüz belirsiz görünüyor
  • Hayalimdeki ikili format, şema tabanlı olup aynı zamanda şemayı mesajın içine gömen bir yapı. Böyle olursa bir vim eklentisiyle doğrudan okunabilir. Milyonlarca nesneyle çalışırken 2GB’lık bir mesaja 1KB’lık şema eklemek büyük yük değil

    • Google içinde zaten böyle şema gömülü bir Protobuf ekosistemi var. Riegeli buna bakmak için iyi bir örnek
    • Avro ya da Yardl da benzer yaklaşım sunuyor
    • Ama web servislerinde bazen şema 200KB, mesaj ise 1KB oluyor. Böyle durumlarda verimsiz kalır
    • Avro hâlâ iyi bir alternatif
 
vipeen 2025-12-06

"Hata ayıklaması zor ama"

Elendi