Projenin OpenAPI Swagger Dökümanı: http://localhost:8080/swagger-ui/index.html
- gRPC kullanılacak.
- gRPC ile parametreli ve parametresiz metotlar yazılacak.
Özellikle mikroservis mimarileri ve dağıtık sistemler günümüzde oldukça yaygın kullanılır. Bu durum sistemlerde esnekliği ve ölçeklenebilirliği arttırmasının yanı sıra dağıtık sistemlerde servisler arası iletişim önemli bir yer tuttuğundan iletişim ve veri iletim hızı için bir dezavantajdır. Bu sorunda geleneksel REST API'ler yaygın bir kullanım alanına sahipken hız konusunda pek yeterli değildir, tam bu noktada gRPC (Google Remote Procedure Call) gibi daha hızlı ve verimli alternatifler de vardır. Bu avatajları büyük ölçüde HTTP/1 yerine HTTP/2 protokülü kullanmasından alır. Bu dökümantasyonda, RPC nedir, gRPC nedirden, gRPC'nin temellerine, çalışma prensiplerine, kullanılan teknolojilere ve gRPC'nin desteklediği RPC pattern'larına kadar çoğu şeyi ele alacağız.
RPC, Remote Procedure Call yani “uzak prosedür çağrısı”, isminin de verdiği ipucundan anlaşılacağı üzere bilgisayar ağları üzerinden bir programın başka bir programdaki fonksiyonu yerel bir çağrı yapar gibi çalıştırmasına imkan veren bir yöntemdir. Örneğin, bir istemci uygulaması, sunucu üzerindeki bir fonksiyonu çağırabilir ve sonucu geri alabilir, tıpkı yerel bir fonksiyonu çağırıyormuş gibi. Bu, servisler arası iletişimi kolaylaştırır ve genellikle verimli bir çözüm sunar.
Ancak, RPC'nin kendisi genellikle daha düşük seviyeli bir teknoloji olarak kalır ve onu kullanacak daha gelişmiş sistemlere ihtiyaç duyarız. İşte gRPC, bu noktada devreye girer. Peki bu gRPC nedir?
"gRPC", Google tarafından geliştirilen açık kaynaklı bir RPC framework’üdür. gRPC, ilk bakışta "Google Remote Procedure Call" kelimelerinin kısaltması olarak akla gelebilir fakat değil :D başındaki "g" harfi her bir gRPC sürümünü temsil etmektedir ( bkz. gRPC sürümleri ). gRPC, farklı uygulamalar arasında yüksek performanslı iletişimi sağlar. gRPC'nin en önemli avantajlarından biri, HTTP/2 protokolünü kullanması ve Protocol Buffers (Protobuf) adı verilen ve Google tarafından geliştirlmiş ve halen geliştirilen bir veri serileştirme formatı kullanarak çok hızlı veri iletimi sunmasıdır.
gRPC, mikroservis mimarileri ve dağıtık sistemler için tasarlanmış modern bir iletişim çözümüdür. REST API’leri yerine daha verimli ve esnek bir alternatif sunar.
- HTTP/2 ile Hızlı İletişim: gRPC, HTTP/2'nin sunduğu avantajları kullanarak daha hızlı veri iletimi sağlar. Bu, paralel isteklerin ve veri sıkıştırmasının mümkün olduğu anlamına gelir.
- Çoklu Dil Desteği: gRPC, Java, Python, Go, C++, Ruby gibi birçok popüler programlama dilini destekler. Bu, gRPC’nin farklı platformlarda kullanılabilirliğini artırır.
- Farklı RPC Modelleri: gRPC, Unary, Server Streaming, Client Streaming ve Bidirectional Streaming gibi farklı RPC türlerini destekler. Bu türler, istemci ve sunucu arasındaki iletişim şekillerini çeşitlendirir.
gRPC verimli veri aktarımı ve hızlı iletişim sağlamak için birkaç adım/bileşen içerir.
Protocol Buffers, Google tarafından geliştirilmiş bir serileştirme formatıdır. Veri yapılarını tanımlamak ve verileri hızlı bir şekilde serileştirmek/deserileştirmek için kullanılır. JSON veya XML'e göre daha hızlı ve daha küçük boyutludur.
Protobuf'un Avantajları:
- Hafif ve hızlıdır.
- Kolay okunabilir bir şema tanımı (proto dosyası) kullanır.
- Çeşitli programlama dilleriyle uyumludur.
Her şeyin başlangıcı, gRPC’nin temelini oluşturan bir dosya formatıdır: Proto dosyası. Proto dosyaları, gRPC servislerinin ve veri yapılarını tanımlamak için kullanılan bir format olup, Protocol Buffers (Proto) serileştirme sistemini kullanır. Proto dosyaları, sunucu ve istemci için gerekli sınıfların ve fonksiyonların tanımını içerir.
Bir proto dosyası, genellikle bir servis tanımlar ve bu servisin içinde kullanılacak olan mesaj yapılarını belirler. İşte basit bir proto dosyasının örneği:
syntax = "proto3";
service FileService {
rpc GetFile (FileRequest) returns (FileResponse);
}
message FileRequest {
string file_name = 1;
}
message FileResponse {
bytes file_content = 1;
}Proto dosyalarını anlamak ve kullanabilmek için, Proto Compiler (protoc) adlı bir araç kullanılır. Bu araç, .proto dosyasındaki tanımları alır ve istemci ile sunucu kodlarını üretir. Örneğin, Java için gerekli olan istemci ve sunucu sınıfları oluşturulabilir.
İntelij Idea vb gibi IDE'ler üzerinde bu maven/gradle vs gibi bağımlılık yönetim araçları yardımıyla eklenen pluginler ile sağlanabilirken manuel olarakta oluşturulabilir bunun için yukarıda örnek olarak verilen proto dosyasını derleyen örnek komut:
protoc --java_out=gen --grpc-java_out=gen FileService.protoProto dosyasını derledikten sonra, istemci ve sunucu arasındaki iletişimi başlatabiliriz. İstemci, bir RPC çağrısı yapmak için ilgili stub sınıfını kullanarak gRPC kanalını oluşturur ve istek gönderir. Sunucu ise bu isteği alır, işler ve bir yanıt döner.
gRPC, Unary, Server Streaming, Client Streaming ve Bidirectional Streaming olmak üzere dört farklı RPC modelini destekler. Bu modellerin her biri, istemci ve sunucu arasındaki veri akışını farklı şekillerde yönetir. Aşağıda bu konseptin daha iyi anlayabilmemiz için her bir RPC için bir görsel ve açıklamalar bulunuyor.
Unary RPC, en basit ve en yaygın RPC modelidir. Bir istemci tek bir istek gönderir ve tek bir yanıt alır. Bu, genellikle geleneksel API istekleriyle karşılaştırılabilir.
Örnek Kullanım: Bir kullanıcı girişinde kullanıcı bilgilerini doğrulama işlemi.
Server Streaming, istemcinin tek bir istek gönderdiği ve sunucunun birden fazla yanıt gönderdiği modeldir. Bu, veri akışını uzun süreli bir işlem veya büyük veri transferi için kullanışlıdır.
Örnek Kullanım: Büyük dosyaların sunucudan istemciye parça parça iletilmesi.
Client Streaming, istemcinin birden fazla istek gönderdiği ve sunucunun tek bir yanıt verdiği modeldir. Bu tür, istemcinin birden fazla veri parçası gönderdiği ancak sadece bir yanıt alması gereken durumlarda kullanılır.
Örnek Kullanım: İstemciden gelen birden fazla log kaydını toplama ve analiz etme işlemi.
Bidirectional Streaming, hem istemcinin hem de sunucunun birden fazla istek ve yanıt gönderebileceği modeldir. Bu tür, her iki tarafın da paralel olarak veri gönderip alabileceği durumlar için uygundur.
Örnek Kullanım: Gerçek zamanlı sohbet uygulamaları, video akışı veya canlı veri analizi.
gRPC'nin hızlı ve etkili olmasının temel nedenlerinden biri, Protocol Buffers (Protobuf) kullanarak veri serileştirme ve deserileştirme işlemlerini optimize etmesidir. Bu süreçte, serileştirme işlemi sırasında uygulamanın veri yapıları, Protobuf tanımlarına uygun olarak ikili (binary) bir formata dönüştürülür ve HTTP/2 protokolü üzerinden sunucuya iletilir. Sunucu tarafında ise gelen binary veri, Protobuf şemalarına göre deserileştirilerek anlaşılabilir bir veri yapısına dönüştürülür. Sunucu, bu verileri işleyip yanıtı hazırlar ve yanıtı da serileştirerek istemciye geri iletir. Bu serileştirme ve deserileştirme süreci, veriyi küçülterek daha hızlı bir iletim sağlarken ağ bant genişliğinin de verimli bir şekilde kullanılmasını mümkün kılar.
Serileştirme ve deserileştirme süreçlerinin sunduğu en büyük avantajlardan biri, hız ve performanstır; çünkü ikili (binary) format, JSON veya XML gibi metin tabanlı formatlara kıyasla çok daha hızlıdır. Ayrıca, serileştirilmiş veriler oldukça kompakt bir yapıya sahiptir, bu da ağ üzerinden veri iletiminde düşük bant genişliği kullanımı sağlayarak iletişimi daha verimli hale getirir. Protobuf tanımlarının platform ve dil bağımsızlığı sunması ise farklı platformlar ve programlama dilleri arasında kolay entegrasyon yapılmasını mümkün kılar, böylece uygulamalar arasında sorunsuz bir şekilde veri alışverişi gerçekleştirilebilir.
gRPC ile ilgili temel özellikleri ve adımları incelediğimize göre tüm bu bilgileri bir görsel ile birleştirelim.
gRPC'nin HTTP/2 kullandığını belirtmiştik ve bunun sağladığı yararlara da değindik ama avantajlarını daha iyi anlamak adına HTTP/1 ve HTTP/2'nin karşılaştırmasını da yapalım, daha farklı neler sağladığını da görmüş olmak adına.
| Özellik | HTTP/1.1 | HTTP/2 |
|---|---|---|
| Protokol Formatı | Metin tabanlı | İkili (Binary) |
| İstek-İstek Bağı | Her istek için ayrı TCP bağlantısı gerekebilir | Tek bir TCP bağlantısı üzerinden tüm istekler |
| Multiplexing (Çoklama) | Yok | Var, birden fazla istek aynı anda işlenebilir |
| Header Sıkıştırma | Yok, büyük boyutlu header'lar | Var, HPACK algoritması ile sıkıştırma yapılır |
| Server Push | Yok | Var, sunucu istemciye istenmeden veri gönderebilir |
| Performans | Daha düşük | Daha yüksek, bağlantı sayısı ve veri akışı optimize |
| Veri İletimi | Metin formatında (HTTP başlıkları dahil) | İkili formatta, daha hızlı ve verimli |
| Bağlantı Yönetimi | Bir istek için bir bağlantı (genelde 6 paralel bağlantı sınırı) | Tüm istekler için tek bir bağlantı |
| Güvenlik | Opsiyonel, TLS isteğe bağlı | TLS şifrelemesi varsayılan (çoğu uygulamada) |
| Uyumluluk | Daha yaygın, tüm tarayıcılar destekler | Daha modern tarayıcılarda ve sistemlerde desteklenir |
| Kullanım Alanı | Geleneksel web uygulamaları | Modern, yüksek performanslı sistemler |
Önemli Farklar:
- Performans: HTTP/2'nin ikili formatı ve multiplexing desteği, özellikle çok sayıda paralel istek gönderen uygulamalarda büyük avantaj sağlar.
- Header Sıkıştırma: HTTP/2'nin header sıkıştırma algoritması (HPACK), veri boyutunu küçülterek daha hızlı iletim sağlar.
- Server Push: HTTP/2 ile sunucu, istemcinin talep etmediği ancak gerekli olabilecek verileri önceden gönderebilir.
-
HTTP/2 Desteği ve Streaming:
gRPC, HTTP/2 protokolü sayesinde paralel istekler, stream desteği ve daha hızlı iletişim sunar. -
Yüksek Performans:
Binary serialization (Protobuf) ile REST'e kıyasla daha hızlıdır, ağ yükü düşüktür, ve yüksek talep hacmini rahatça karşılar. Bu sayede text-based mesajlaşmaya nazaran oldukça hızlıdır. -
Çift Yönlü İletişim:
Aynı bağlantı üzerinden istemci ve sunucu arasında gerçek zamanlı veri alışverişi yapılabilir. -
Çoklu Dil ve Platform Desteği:
Protobuf kullanımı sayesinde farklı diller ve platformlar arasında uyumlu çalışır. -
Güvenlik ve Modern Yapı:
TLS ile şifreleme, modern mikroservis ve dağıtık sistem mimarilerine uyumluluk sağlar. -
Otomatik Kod Üretimi:
Proto dosyasıyla hem istemci hem sunucu için kodlar kolayca üretilir.
-
Zor Debugging:
JSON veya XML'e kıyasla, Binary format kullanımı debugging'i zorlaştırabilir ve ek izleme araçları gerekebilir. -
HTTP/2 Desteği Gereksinimi:
HTTP/2 uyumlu olmayan sistemlerde ek konfigürasyon veya geçiş gerektirebilir. -
Tarayıcı Desteği Sınırlamaları:
Doğrudan tarayıcı desteği yoktur, bazı tarayıcılarda uyumluluk sorunu yaşatabilir. -
Zaman Maliyeti ve Karmaşıklık:
Küçük projelerde ya da düşük performans gereksinimlerinde gereksiz karmaşıklık yaratabilir. Aynı zamanda REST gibi servislere göre oluşturulmadaki zaman maliyeti yüksektir.
// Proto dosyamızın hangi syntax a uygun olarak yazıldığını belirtiyoruz
syntax = "proto3";
// Derlenecek dosyaların hangi package altında tutulacağını söylüyoruz
// Derlenen dosyalar maven için target altında > generated source altında > protobuf altında oluşturulur.
package com.vehbiozcan.grpc;
// Oluşturulan her bir yapıyı ayrı ayrı java dosyaları halinde oluşturmayı sağlar
option java_multiple_files = true;
// Service Tanımlaması
service OrderService {
// Unary RPC
rpc PlaceOrder(OrderRequest) returns (OrderResponse);
// Client Streaming RPC
rpc UploadOrderItems(stream OrderItem) returns (OrderSummary);
// Server Streaming RPC
rpc TrackOrder(OrderTrackRequest) returns (stream OrderStatus);
// Bidirectional Streaming RPC
rpc OrderChat(stream ChatMessage) returns (stream ChatMessage);
}
// Unary RPC için Message
message OrderRequest {
string orderId = 1;
string customerId = 2;
repeated OrderItem items = 3;
string paymentMethod = 4;
}
message OrderResponse {
string orderId = 1;
string status = 2; // Örnek: "CONFIRMED", "FAILED"
string estimatedDelivery = 3; // Örnek: "2025-01-20"
}
// Client Streaming RPC için Message
message OrderItem {
string productId = 1;
int32 quantity = 2;
float price = 3;
}
message OrderSummary {
int32 totalItems = 1;
float totalCost = 2;
string confirmationMessage = 3;
}
// Server Streaming RPC için Message
message OrderTrackRequest {
string orderId = 1;
}
message OrderStatus {
string status = 1; // Örnek: "ORDERED", "SHIPPED", "OUT_FOR_DELIVERY"
string timestamp = 2; // Örnek: "2025-01-17T14:00:00Z"
}
// Bidirectional Streaming RPC için Message
message ChatMessage {
string sender = 1; // "client" or "server"
string message = 2;
string timestamp = 3; // Örnek: "2025-01-17T14:10:00Z"
}
-
Senaryo: Müşteri, bir sipariş oluşturur. Sipariş detayları sunucuya gönderilir ve sunucudan bir yanıt alınır.
-
Kullanım: Müşteri sipariş veriyor ve sistem siparişi kaydedip durumu döndürüyor.
-
Senaryo: Müşteri, birden fazla ürünü sırasıyla sunucuya yükler. Sunucu, sonunda toplam sipariş özetini döner.
-
Kullanım: Özellikle büyük siparişlerde ürünlerin parça parça iletilmesi gereken durumlarda uygundur.
-
Senaryo: Müşteri, bir siparişin durumunu takip eder. Sunucu, siparişin durum güncellemelerini sürekli gönderir.
-
Kullanım: Kargoların durum değişikliklerini (ör. "Şipariş alındı", "Yola çıktı", "Teslim edildi") istemciye göndermek için idealdir.
-
Senaryo: Müşteri ile destek ekibi arasında gerçek zamanlı bir sohbet gerçekleştirilir.
-
Kullanım: Siparişle ilgili sorunlar veya sorular için canlı destek sistemi.
Bu verdiğimiz örnekle tüm gRPC servis türlerini de anlamış olduk. Örnek proto dosyamızda da gördüğümüz üzere stream anahtar kelimesinin yerine göre RPC türümüz belli oluyor.
gRPC, modern uygulamalarda yüksek performanslı ve verimli bir iletişim çözümü sağlar. HTTP/2’nin sunduğu hız ve verimlilik, Protocol Buffers ile veri serileştirme, ve çeşitli RPC modelleri ile esneklik, gRPC’yi dağıtık sistemler için mükemmel bir seçenek haline getiririr ayrıca HTTP/2 sayesinde HTTP/1 kullanan yöntemlere göre 2.5 kat daha hızlı bir yöntemdir.(bkz. http2demo) Eğer mikroservisler veya dağıtık sistemlerle haşır neşirsek mutlaka seçenek olarak aklımıza gelmesi gereken bir teknolojidir. :)
Bu endpointe atılan request product servis ile iletişime geçip product servis üzerinden discount servis ile gRPC üzerinden iletişime geçer verilen product id ve code'a göre, sonuç olarak eski fiyat, indirimli fiyat ve code bilgisini geriye döner
Bu endpointe atılan request product servis ile iletişime geçip product servis üzerinden discount servis ile gRPC üzerinden iletişime geçer parametresiz bir istek atılır, sonuç olarak tüm discount türlerinin bilgisini liste olarak geriye döner.





