gRPC, OpenAPI, REST’i anlamak ve API tasarımında ne zaman kullanılacakları (2020)
(cloud.google.com)- API tasarımının başlangıç noktası RPC ile REST arasındaki farktır; üç yöntem de HTTP ile ilişkilendirilebilir, ancak çağrı oluşturma ve istemciyi yapılandırma modelleri farklıdır
- REST, sunucunun sağladığı URL’leri izleyen bir hipertext modelidir; bu nedenle istemcinin URL biçimlerini birleştirdiği OpenAPI tarzı API’lerden ayrılır
- OpenAPI, URL yol şablonları ve HTTP metotlarıyla işleri tanımlar; pratik ve yaygın olarak kullanılır, ancak REST’ten çok HTTP’ye eşlenmiş bir RPC modeline daha yakındır
- gRPC, IDL, kod üretimi, ikili payload ve HTTP/2 bağlantı yönetimi aracılığıyla RPC API’lerini doğrudan tanımlar ve HTTP ayrıntılarını gizler
- gRPC, her iki tarafta da özel yazılım gerektirir ve proxy ile güçlendirme, eşzamanlı güncellemeleri önleme ve kısmi güncellemelerde kısıtları vardır; bu yüzden özellikle dahili API’ler veya Cloud Endpoints gibi bir dönüştürme katmanı kullanılabildiğinde uygundur
HTTP tabanlı API’lere bakmak için üç model
- HTTP’yi API taşıma katmanı olarak kullanan başlıca yaklaşımlar REST, OpenAPI ve gRPC olarak ayrılır
- Pek çok açık API’nin ve özel dağıtık API’nin HTTP kullanmasının nedenlerinden biri, kurumların 80 ve 443 numaralı portlardaki HTTP trafiğinin güvenlik konularına aşina olmasıdır
- Üç yöntem de HTTP ile ilişkilendirilebilir, ancak neyin adres olarak alındığı ve istemcinin çağrıları nasıl oluşturduğu farklıdır
REST: URL’leri birleştirmek değil, izlemek
- REST’te istemci, sunucunun ilettiği URL’yi olduğu gibi kullanır; URL biçimini API tanımının bir parçası olarak anlamaz veya birleştirmez
- Tarayıcı, mevcut sayfayı, yer imlerini ve kullanıcının girdiği URL’leri izler; en fazla URL’den HTTP istek bilgilerini çıkarır veya göreli URL’leri mutlak URL’ye dönüştürür
- REST API’nin özü, kaynaklar arasındaki referansları diğer kaynakların URL’leriyle ifade eden hipertext/hipermedya kullanımıdır
- REST yaklaşımında tüm tanımlayıcılar URL olarak alınıp verilir
POST /accounts→account_URLPOST /subscriptionsiçineaccount_URLiletilir →subscription_URLGET {account_URL}→ hesap veri ağacını döndürür
- REST’in avantajları web’in kendi kararlılığına, tutarlılığına ve evrenselliğine yakındır; HTTP/REST’in varlık odaklı modeli API’yi daha basit ve daha düzenli hâle getirebilir
OpenAPI: HTTP’ye doğrudan eşlenmiş RPC’ye yakın
- OpenAPI,
pathsaltında URL yol şablonlarını tanımlar ve yol ile HTTP metodunun birleşimine işlem(operation) der /pets/{petId}gibi bir yol, istemcinin{petId}değerini bilmesini ve bunu URL şablonuna yerleştirerek HTTP isteği oluşturmasını gerektirir- Bu yaklaşımda istemcinin URL biçimini ayrıntılı şekilde bilmesi gerekir; bu yüzden REST’in hipertext modelinin tersidir
- OpenAPI’nin yaygın kullanılmasının nedeni açıktır
- Geleneksel RPC modeline benzediği için programcılara tanıdıktır
- RPC kavramlarını HTTP isteklerine doğrudan eşlemek mümkündür
- Açık API’lerde standart HTTP teknolojileriyle neredeyse tüm dillerden ve ortamlardan erişilebilmesi büyük bir avantajdır
- Buna karşılık URL yolu, HTTP metodu ve parametre eşlemelerinin tasarlanması gerektiği için hem API sağlayıcılarının hem de tüketicilerinin öğrenmesi gereken ayrıntılar artar
gRPC: HTTP/2’yi gizleyen RPC uygulama teknolojisi
- gRPC, HTTP/2’yi taşıma katmanı olarak kullanır, ancak API tasarımcısına ve istemci-sunucu koduna HTTP ayrıntılarını göstermez
- gRPC istemcisinin çağrı akışı basittir
- Çağrılacak prosedüre karar verir
- Kullanılacak parametre değerlerini hesaplar
- Parametreleri kod üretilmiş stub’a geçirerek çağrıyı yapar
- gRPC, uzak prosedürleri interface description language temelinde tanımlar; OpenAPI’de olduğu gibi URL yolu, parametre ve HTTP metodu eşlemelerini birlikte ifade etmeye gerek yoktur
- Kod üretimi, framework’ler ve kütüphaneler aracılığıyla istemci kütüphaneleri ve sunucu uygulamaları oluşturmak daha kolay olabilir
- İkili payload ve HTTP/2 bağlantı yönetiminden yararlanarak performans avantajları sağlar; aynı teknolojileri gRPC olmadan doğrudan kullanmak da mümkündür, ancak daha fazla teknik öğrenim gerektirir
OpenAPI yerine gRPC’yi değerlendirirken
- OpenAPI ile API tasarlarken işlemleri ve parametreleri URL yolları ile HTTP metotlarının birleşimi olarak ifade etmek gerekir; seçenekler çok olduğundan bu zorlayıcı olabilir
- RPC tarzı modeli kullanmaya devam edilecekse gRPC, HTTP’ye yönelik özel eşleme tasarlama yükünü azaltır
- gRPC ve OpenAPI’nin temel API modelleri benzerdir, ancak HTTP’yi dışa açma biçimleri farklıdır
- OpenAPI, HTTP taşıma ayrıntılarını istemciye gösterir ve tasarımcı eşlemeyi kontrol eder
- gRPC, önceden tanımlanmış eşlemeler ve üretilmiş kod aracılığıyla HTTP ayrıntılarını gizler
- OpenAPI’nin büyük avantajı, istemcinin standart HTTP araçlarını ve teknolojilerini olduğu gibi kullanabilmesidir; pek çok API tasarımcısı için bu avantaj ek tasarım maliyetini haklı çıkarır
RPC’ye varlık odaklı modeli eklemek
- gRPC veya OpenAPI kullanılsa bile RPC metotlarını varlık merkezli biçimde sınırlandırmak REST’in bazı avantajlarını sağlayabilir
- Prosedür tanımlarından başlamak yerine önce kaynak tiplerini tanımlayıp ardından her tipe standart varlık işlemlerini karşılık getiren bir yaklaşımdır
- Temel işlemler Create, Retrieve, Update, Delete ve List’tir; genellikle CRUD plus List olarak görülebilir
- Gerektiğinde ek işlemler tanımlanabilir, ancak varlık odaklı kavramlarla prosedür odaklı kavramlar karıştığında bazı avantajlar zayıflayabilir
- Prosedürleri varlık tiplerine göre gruplamak, nesne yönelimli dillerin temel fikirlerinden biridir
gRPC’nin kısıtları ve dikkat edilmesi gerekenler
- gRPC, hem istemci hem de sunucu tarafında özel yazılım gerektirir; üretilmiş kodun iki tarafın derleme süreçlerine de entegre edilmesi gerekir
- JavaScript veya Python gibi geliştirme ortamlarında derleme süreci çok az olan dinamik dil kullanıcıları için bu gereksinim yük olabilir
- Google Cloud Endpoints, gRPC API’lerine HTTP ve JSON üzerinden erişim sağlayarak istemci seçeneklerini geri kazandırır; ancak tüm kullanıcılar bunu kullanamaz veya eşdeğer işlevi kuramaz
- REST API’de metaveri olmadan bile tamamını tarayan bir bot yapmak kolaydır; buna karşılık gRPC veya OpenAPI gibi RPC tarzı API’lerde her varlık tipi için farklı API’ler ve metaveri ya da özel yazılım gerekir
- HTTP API’lerinde çoğu zaman Apigee Edge gibi API yönetim araçları ve proxy’ler aracılığıyla güvenlik özellikleri, giriş doğrulama, veri biçimi eşlemeleri, header ve gövde düzenlemeleri eklenir; ancak gRPC’de bu tür proxy güçlendirmeleri çok daha zor olabilir
- gRPC, eşzamanlı güncellemelerden kaynaklanan veri kaybını önlemeye yönelik standart bir mekanizma tanımlamaz
- HTTP bunun için
EtagveIf-Matchheader’larını sunar
- HTTP bunun için
- gRPC kısmi güncelleme mekanizması da tanımlamaz
- HTTP’de
PATCHvardır; JSON için standart olarak JSON merge patch ve JSON patch bulunur - JSON merge patch daha basittir, ancak dizi güncellemeleri gibi tüm durumları ele alamaz
- JSON patch daha fazla durumu ele alır, ancak kullanımı daha karmaşıktır
- HTTP’de
Seçim ölçütleri
- REST hipertext modelini zaten tasarlamayı biliyorsanız veya öğrenmeye istekliyseniz, kararlılık, tutarlılık ve evrenselliği hedefleyen iyi bir seçenek olabilir
- OpenAPI, yalnızca standart HTTP teknolojileriyle erişilebilen API’ler oluşturabilir; ancak RPC kavramlarını HTTP’ye eşleme tasarım seçenekleri arttığı için tasarım, uygulama ve öğrenme zorlaşabilir
- OpenAPI düşünülen bir API için gRPC’yi de birlikte değerlendirmek anlamlıdır. İki yöntemin temel API modelleri karşılaştırılabilir düzeydedir ve gRPC, HTTP eşlemesini doğrudan oluşturma ihtiyacını azaltır
- gRPC şu koşullarda özellikle caziptir
- Cloud Endpoints gibi ürünlerle istemcinin gRPC teknolojisini mutlaka benimsemesinin gerekmediği durumlarda
- Sunucu ve tüm istemcilerin teknoloji seçimlerini kontrol edebildiğiniz dahili API’lerde
- OpenAPI veya REST yerine gRPC benimsenirken, Apigee Edge gibi API yönetim araçlarına dayalı proxy’lerle API davranışını güçlendirme veya düzeltme fırsatlarının çok daha sınırlı olabileceği dikkate alınmalıdır
1 yorum
Hacker News yorumları
Zamanı geri alabilseydim gRPC'yi en başta öğrenmemi engellemek isteyecek kadar böyle düşünüyorum.
Başta vizyonuna kapılmıştım ama birkaç yıl geçince çok fazla baş ağrısı çıkardığını gördüm. İç yapıyı gizlediği iddiası da neredeyse şaka gibi; 10 isteğin 1'inde yaşanan hatanın nedenini bulmak için debug loglarını boca edip, adları bile muğlak 10-20 timeout/yeniden deneme ayarını kurcalamak zorunda kalıyorsunuz.
Maven eklentileri, tuhaf
deadline exceededhataları, HTTP/2'den hoşlanmayan load balancer'lar, güvenlik duvarları yüzünden sonunda standart API kullanmak zorunda kalınan durumlar, zayıf dokümantasyon ve gözlemlenebilirlik tarafında işe yarar hata mesajları elde etmeye çalışmak; hepsi zaman yedi.Üretilen kodun geliştirici deneyimi kötü; client stub'ları
finalsomut sınıflar olduğu için testlerde mock'lamak zor, sunucu implementasyonu da interface yerine somut bir sınıftan miras almak zorunda.Sunucu metotları asenkron imzaya sahip olduğundan
@Transactionalgibi AOP tabanlı davranışları bozuyor; exception desteği de yok. Değişmez değer sınıfları güzel ama hepsini builder ile oluşturmak gerekiyor.Sonuçta SOA'da gRPC kullanmak istiyorsanız, gRPC gürültüsünü gizleyip test edilebilir, temiz kod elde etmek için çok fazla tesisat kodu yazmanız gerekiyor. Thrift'in RPC derleyicisinde de benzer sorunlara ek başka sorunlar var.
Güncel .NET ve C# ile gRPC deneyimi oldukça iyi; Microsoft da WCF gibi eski RPC teknolojilerini sonlandırıp gRPC'ye odaklandı.
protoctarafından üretilen binding çıktısını doğrulamak, doğrudan serileştirme yapmaktan daha laf kalabalığına açık ve hataya yatkındı.Wire protokolü type-safe değil; type tag'ler var ama aynı tag birden çok veri tipi için yeniden kullanılıyor. zig-zag tamsayı kodlaması da yavaş.
Bir RPC kütüphanesi olarak berbat; bizzat deneyimlediklerim arasında ondan daha kötüsü sadece FlatBuffers'dı.
Bu farkın Java'dan mı yoksa gRPC teknolojisinin kendisinden mi kaynaklandığını merak ediyorum.
Java+gRPC'ye özgü bir sorun olup olmadığını merak ediyorum.
Uzun süredir API geliştiriyorum; hem gRPC hem de HTTP/REST kullandım ve OpenAPI tanımından Go istemcisi ve sunucusu üreten kütüphane https://github.com/oapi-codegen/oapi-codegen’i de yayımladım.
Yazıda OpenAPI ile REST’i ayırma biçimine katılmak zor. OpenAPI, HTTP API’lerinin davranışını belgelemenin bir yoludur; ister RESTful API olsun ister tamamen keyfi bir API, ikisini de ifade edebilir. Araçların yorumlayabileceği şekilde API’yi açıklayan bir şema dili olması bakımından, gRPC protokolünü belirleyen Protocol Buffer dosyalarıyla kavramsal olarak benzerdir.
gRPC, proto alıp gönderen bir RPC mekanizmasıdır; Google protobuf’u açık kaynak yaparken şirket içi RPC katmanı Stubby’yi açmamıştı ve gRPC, Stubby kadar iyi değildir. Yine de aktarım verimliliği yüksektir ve genişletmesi de görece kolaydır.
Ancak gRPC, yaygın HTTP kütüphaneleri kadar sağlam bir ekosistem değildir; logging veya kimlik doğrulama gibi middleware’leri çoğu zaman kendiniz uygulamanız gerekir. Farklı dillerde uygulanmış servisler arasındaki RPC’de bu özellikle böyledir.
Bana göre gRPC’nin asıl sorunu proto dosyalarıdır. Tüm istemcilerin sunucuyla uyumlu bir
.protodosyasıyla derlenmiş olması gerektiği için keşfedilebilir bir protokol değildir. HTTP API’leri, OpenAPI açıklaması olmadan dacurlveya kendi yazdığınız kodla çağrılabilir; bu da bağı daha gevşek kılar ve bu yüzden geliştirme ile debug etmeyi kolaylaştırır.Roy Fielding’in 2000 tarihli doktora tezinde tanımladığı REST’te, kök URL’ye
GETyapıldığında200 OKyanıtının içinde bağlantılar olur ve bu bağlantılar izlenerek API’nin sunduğu tüm kaynaklar gezilebilmeliydi. Hiyerarşik yapı serbestti ama her şeye bağlantı ağacının bir yerinden erişilebilmesi gerekiyordu; amaç keşfedilebilirlik sağlamaktı.Son 20 yılda çalıştığım yerlerin neredeyse tamamı
POST resource_name/resource_id/sub_resource/sub_resource_id/mutation_typeveya şirketin idempotency işleme biçimine görePUT resource_name/resource_id/sub_resource/sub_resource_idkullanıyordu; istemci de Swagger/OpenAPI gibi yapısal bilgilere dayanarak sihirli URL’ler oluşturuyordu.Bu yüzden titiz kişiler, Fielding’in REST tanımını uygulamadığı anlamında pratikteki bu tarza “REST” değil “RESTful” demeyi tercih eder.
İç/dış istemcileri olan oldukça büyük API’leri yöneten biri olarak, OpenAPI tanımından kod üretme akışını da anlamakta zorlanıyorum. Üretilen stub’ları doldurup API tanımını tekrar tekrar iyileştirdiğinizde araç yeniden yeni stub’lar üretiyor; elle birleştirme gerekiyor ve API büyüdükçe ilgili değişiklikleri bulmak zorlaşıyor.
Bu yüzden
go/astvb. kullanarak koddan OpenAPI tanımı üreten bir canavar yaptım. Mükemmel değil ama hem Echo hem Gin’de çalışan %95’lik bir çözüm; yeni endpoint gerektiğinde istek/yanıt struct’larını ve boş handler’ı oluşturup dokümanı üreterek frontend geliştiricisine göndermek şeklinde hızlı ilerlemek mümkün.Çoğu geliştiricinin API’yi OpenAPI ile nasıl ifade edeceğini düşünmesine gerek kalmıyor ve dokümantasyon da kodla her zaman uyumlu oluyor.
Apipe.new(GitHun) |> from("search/repositories") |> eq(:language, "elixir") |> order_by(:updated) |> limit(1) |> execute()Kullanılabilir gRPC fonksiyonlarını veya üçüncü taraf API’nin RESTful tuhaflıklarını bilmek gerekmiyor; yerleşik dokümantasyon ve tip erişimi de korunuyor.
https://github.com/cpursley/apipe
JS/TS projelerine Supabase gibi eklenebilmesi için bir TypeScript adapter katmanı da düşünüyorum.
const { data, error } = await apipe.from('search/repositories').eq('language', 'elixir').order_by('updated').limit(1)Bu çağrı bir Elixir proxy üzerinden geçirilip asenkron işleme veya hız sınırlama gibi ağır işleri ona yaptırabilir.
Protobuf’un JSON serileştirmesine dayanarak OpenAPI açıklaması oluşturup Swagger ile sunabilirsiniz; gRPC’nin kendisi de yerleşik reflection ve bunu kullanan
grpcurlyardımcı aracını sağlar.FAANG şirketlerinden birkaçında çalışmış biri olarak Thrift/gRPC iç servis yönlendirmesi için gerçekten çok kullanışlı
Ancak bu karmaşıklığın önemli bir kısmı; kütüphaneleri, servis keşif katmanını, yönlendirmeyi vb. yapan ekipler tarafından yönetiliyor. RPC protokolü kullanınca, sıradan JSON/REST servisleriyle yapılması zor olan ölçekte ve hızda bunlar mümkün hale geliyor
Fiillerin REST API’dan dışarı sızmadığı bir durum da hiç görmedim; bir backend service mesh kurmam ya da iki yerel servisi bir ağ akışıyla bağlamam gerekse her zaman gRPC’yi seçerdim
Ama müşteriye veya web’e açık kullanım için gRPC’yi asla kullanmam. RPC güçlüdür çünkü birçok kararı sabitler ve “tek bir yöntemi” dayatır. Buna karşılık, farklı teknoloji yığınlarındaki çeşitli istemcilerin servisi kullanması gerekiyorsa REST çok daha iyidir
POST /api/doThingyadresine JSON gövdesi göndermek gibi ele alıyorumEn temel HTTP istemcisi olan herkesin katılabileceği kolay bir RPC; tüm işletim sistemleri ve tarayıcılarda iyi çalışıyor. URL yoluna mı, sorgu parametresine mi, gövdeye mi koyacağınla boğuşmaya da gerek yok
Buf veya Connect gibi işleri daha az zahmetli hale getirmeye çalışan sunucu ailelerini kullanırsan gRPC’de de HTTP üzerinden JSON’u memnuniyetle kabul ediyorlar
REST’ten çok daha gerçek zamanlı iletişim gerektiren çevrimiçi oyunlar veya MMO’lar aklıma geliyor; ama bugünlerde soket bağlantısının üzerine bir şeyler mi bindiriliyor, pek emin değilim
Başka neleri denediklerini de bilmek isterim
Çift yönlü streaming yapmıyorsanız gRPC’nin çoğunlukla zaman kaybı olduğunu düşünüyorum
Çalışma zamanı geçişli bağımlılık cehennemi, araç zinciri cehennemi var; Google içinde her uygulamayı yöneten ekipler bile temel işlevlerin nasıl çalışması gerektiği konusunda felsefi olarak uzlaşamıyor gibi görünüyor
Kendi dilimi kullanmayan ekiplere, özellikle Go/Python/Java olmayan ya da onlar olsa bile eski sürümlerini kullanan ekiplere bir gRPC API açmayı; ticari hazır ürünlerle entegre etmeyi; ya da tarayıcıya açmayı denerseniz hepsinde bir ara katman gerekiyor
gRPC genel olarak sorunsuzdu
Backend servislerinin birbiriyle iletişiminde REST kullanmak da performans gereksinimi varsa pek anlamlı değil; arada sırada küçük veri alan çağrılar dışında insan tarafından okunabilir bir protokol/API kullanmak için güçlü bir neden yok
oneofalt tiplerinden, o anda alanı olmayan bir tipi döndürünce otomatik dönüşüm sonucu{ "id": "id", "sub_type_two": { } }gibi çıkıyorduİşlevsel olarak çalışıyor ve ileride alan eklense bile o kod çalışmaya devam ediyor. Ama web dünyasında yanıt tipini boş nesneyle göstermek tuhaf; protobuf yazarken bu tür sorunlar pek görünmeyebilir
Akla gelebilecek neredeyse tüm ikili protokollerle karşılaştırıldığında streaming karşıtı sayılır
Şirkette gRPC kullandığım tek deneyim, başka bir kıdemli geliştiricinin “performans lazım” diyerek dayattığı bir projeydi
Sonunda frontend’in tüketebilmesi gerektiği için JSON API de yaptık; o geliştirici dışında gRPC deneyimi olan kimse yoktu. Aslında o geliştirici de gRPC Python hızlı başlangıç kılavuzunun ötesine geçmemişti ve hata düzeltmelerine de yardım etmedi
Proje pek çok nedenle berbat durumdaydı ve gRPC’yi haklı çıkaracak ölçeğe de hiç ulaşmadı
Yine de kişisel olarak biraz kullandığım gRPC hoşuma gitti; çok daha fazla çalışma ve düşünme gerektirdiğini hissettiriyor. Bu, JSON API’lerle çok daha fazla deneyimim olduğu için de olabilir
ConnectRPC https://connectrpc.com/ kullanmayı keyifli buluyorum
gRPC’nin sorunlu kısımlarının çoğunu düzeltiyor; Safari WebTransport’u kabul ederse ConnectRPC’nin daha iyi streaming geliştirebileceğini umuyorum
Başta https://buf.build bana fazla gelmişti, ama üçüncü taraf proto dosyalarını tek tek indirmeden getirebilme özelliği belirleyici oldu
deps:- buf.build/landeed/protopatch- buf.build/googleapis/googleapisOtomatik SDK üretimi de büyük bir avantaj. Eskiden yaklaşık 9 dil için SDK’ları otomatik ürettiğini övecektim; ama son bir iki gün içinde güncellenmiş ve artık 16 dilin yanı sıra OpenAPI ve başka yeni özellikler de görünüyor
Ben de gRPC streaming’in sahte vaadine kapıldım ve bu belge deneyimimle tam olarak örtüşüyor: https://connectrpc.com/docs/go/streaming/
Bu sayede tarayıcıda da çift yönlü streaming kullanılabiliyor
Google, sektörün tamamına psikolojik savaş açmış gibi, herkesi iç servis iletişiminde gRPC kullanmaya zorlamış hissi veriyor
gRPC’nin geliştirici deneyimi REST’e göre epey kötü
Birine bir endpoint’i çağırmak için basit tek bir komut veremiyorsunuz; standartlaşmamış ek araçlar gerekiyor. Üstelik üretilen istemci tarafı kodu, hangi dilde olursa olsun nadiren görülecek kadar çirkin bir yığın
Tek bir protokol değişikliğiyle hangi alt tüketicileri güncellemek ve yeniden dağıtmak gerektiğini statik olarak bilebiliyorsunuz; bu da haftalar sürecek işi bir saatlik değişikliğe indirebilir
Aldığınız ve gönderdiğiniz mesajların anında doğrulandığını da biliyorsunuz; ayrıca daha sonra geri yüklemek üzere ucuza saklayabiliyorsunuz
proto ile son derece okunabilir API dokümantasyonu elde ediyorsunuz; kodun ya da iş mantığının içinde bulanıklaşmıyor. Sürüm yönetimi ve kullanım dışı bırakma anlamları da yerleşik; map dışında daha zengin veri yapıları da destekleniyor
Karşılaştırınca JSON backend’de şişkin ve eski görünüyor
Veri tiplerini ve fonksiyon imzalarını yazınca, gerçek bir fonksiyon gibi çağırabileceğiniz bir şey elde edersiniz; serileştirme/ters serileştirme boilerplate’i yerine iş mantığına odaklanabilirsiniz
Thrift de aynı şekilde her şeyi elde yapmaya göre çok daha iyi; GraphQL’in ise daha da iyi olduğunu düşünüyorum
Go’da bile yeniden üretilebilirlik ve paylaşılan proto sürüm yönetimini çözmek zahmetli; her yeni dil eklendiğinde daha da kötüleşiyor
Yine de tüm startup’lar 100 mikroservise ve gRPC’ye ihtiyaçları olduğunu düşünüyor gibi
“API bir REST API ise istemcinin URL biçimini anlaması gerekmez; bu biçim istemciye verilen API spesifikasyonunun bir parçası değildir” cümlesi Roy Fielding’in REST tanımıyla örtüşüyor
Fielding, bir REST API’ye başlangıç URI’si ve standartlaştırılmış medya tipi kümesi dışında ön bilgi olmadan girilmesi gerektiğini; bundan sonra tüm uygulama durum geçişlerinin, sunucunun sunduğu seçenekler arasından istemcinin seçim yapmasıyla gerçekleşmesi gerektiğini yazmıştı
https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...
Zaten çok tartışılmış bir konu ama gerçek RESTful bir sistemde istemciye verilen “API spesifikasyonu”nun yalnızca ilk giriş noktası URI/URL’si olması gerektiği hâlâ ilginç
Şahsen bunun şişkin olduğunu ve gerçek bir problemi çözmediğini düşünüyorum
https://en.m.wikipedia.org/wiki/HATEOAS
Özellikle istemcinin üzerinde işlem yapabileceği kaynakları ya da istek/yanıt modellerini nasıl keşfetmesi gerektiğini bilmiyorum
Yapılandırma açısından böyle olabilir; ama API spesifikasyonu URL’den çok daha fazlası olmalı ve sistemin kullandığı medya tiplerini ayrıntılı açıklamalı. Yani HTTP istek/yanıt gövdelerinin açıklaması çoğunlukla gerekli
Bağlantıda da “REST API, açıklama çabasının neredeyse tamamını kaynakları temsil eden ve uygulama durumunu yönlendiren medya tipi tanımlarına harcamalıdır” deniyor
Sonuçta yalnızca
application/jsondöndürmüyor; belirli bir+jsongibi bir şey döndürüyor ve çoğu zaman bu genel JSON değil, uygulamanın anlaması gereken iş verilerini içeriyorPopüler tartışmalarda odak yalnızca başlangıç URL’sine kayıyor; Fielding’in söylediği “medya tipini açıklayın” kısmındaki işlerin çoğu atlanıyor. Bu yüzden “tek URL yeter” sözünü duyan birinin “spesifikasyonun geri kalanı nerede?” diye sorması doğal
Ben de yine REST’i anlamamış bir blog yazarı mı diye yazıya tıkladım ama yazar en azından temel kavramları biliyor gibi
gRPC’yi de seviyorum ve ticari projelerde oldukça çekici; ama kişisel ya da idealist bir proje olsaydı REST’in daha iyi olduğunu düşünüyorum
Veri merkezi içinde gRPC kullanmayı sevmiyorum
Performans gerekçesiyle seçiliyor ama gRPC’nin yüksek performanslı olduğunu söylemek zor; herkese açık istemci kalitesi de özellikle C++/Java çekirdek uygulamalarının dışında çok düşük. Örneğin Node.js uygulaması böyle
protobuf’un API spesifikasyonu olarak kullanılmasına karşı değilim; ancak TCP üzerinde bir framing protokolüyle birlikte kullanılabilmeli. Ne var ki bu tür RPC’de belirgin biçimde baskın bir seçenek yok
Web tabanlı API’lerde okunabilir payload’ları daha çok tercih ederim; ama genelde JSON kullanılırken tip kesinliği gevşiyor ve backend dilleri arasında birlikte çalışabilirlik sorunları çıkıyor. Özellikle Node.js’te
JSON.parsebir şema eşleme uygulaması gibi kullanılıyorBunu düzgün yapmak için şemadan encoder ve decoder’ları açıkça üretmek gerekir; bu da JS bağlamında JSON kullanmanın avantajını bir ölçüde azaltır
Microsoft’un TypeSpec projesini de izliyorum: typespec.io
Tek dilli bir teknoloji stack’iniz varsa önemi azalır. Ayrıca Google’ın ana dilleri dışında bir şey kullanıyorsanız deneyimin o kadar iyi olmama ihtimali yüksek
gRPC, Google dışındaki geri kalan insanlar için gereksiz yere erişilmesi zor hissettiriyordu
gRPC JS istemcisi gereksiz yere ağır ve oldukça opak. Fikir iyi, ama REST’in “basitliğine” alışkın olanlara kıyasla uygulaması hayal kırıklığı yaratıyor
RPC, veri modelinin kardinalitesini veya ilişkilerini tek bir kuralcı kalıba zorla uydurmak zorunda olmadığı için anlamsal olarak bakımı daha kolay. API’lerin hızla değiştiği bir dünyada güzel RESTful varlıkları tutturmak zor; büyük ekiplerde ve değişen gereksinimler/sahipliklerde servis odaklı tasarım daha iyi
Frontend tarafı backend sistemlerini bakımını yapmaz. Anlaşılması kolay API’ler ister ve REST ile soyutlanabilen varlıklar ister. Bu tür tasarımın nihai faydalanıcısıdır
REST’e harcanan emek, API satan ve üçüncü taraf geliştiricilerin ana müşteri olduğu şirketlerde anlamlıdır
Backend geliştirmede protobuf ve ikili wire encoding daha kolaydır. API’yi tanımlayıp statik tipli bir şekilde servisler arasında paylaşabilirsiniz; mesaj kodlama/kod çözme süresi de azalır. JSON ne anlamsaldır ne de tiplenmiştir, ayrıca overhead’i de yüksektir
Buna karşılık frontend metin ve JSON’u native olarak işler. Protobuf tanımlarını indirmek ya da ikili veriyi ikinci sınıf vatandaş gibi ele almak istemez; araçlarla da temiz şekilde uyuşmaz
gRPC’de yönlendirme, yeniden deneme, yan kanallar, streaming ve protokol sonlandırma semantiği iyi yerleşmiştir, ancak bunlar frontend’e neredeyse hiç görünmez. Hepsi backend tüketicileri içindir
Sonuçta bu %100 frontend/backend araç uçurumu ve arayüz ile kullanılabilirlik uyumsuzluğudur
Temelde kaynağını görebilirsiniz, insanlar tarafından okunabilir ve incelemesi kolaydır
gRPC, makinelerin birbirleriyle verimli konuşması içindir; ister kodlama ister istek/yanıt inceleme olsun, insan araya girince biraz rahatsız edicidir
Bağlam ve hedefler farklı olduğu için bu kullanılabilirlik farkı anlaşılır
Bana göre buf.build tarafındaki implementasyon iyi
https://buf.build/blog/protobuf-es-the-protocol-buffers-type...
Sözleşmeli ikili RPC gibi bir protokole ihtiyaç var gibi göründüğü için pek çok şeyi seçmişler sanki; ancak GoLang’den uzaklaştıkça giderek kötüleşiyor
Basit CRUD servisleri için REST de yeterlidir