~/Ali GÖREN

Go ve gRPC ile Client / Server’ın Arasını Yapalım.

Ali Goren · · 5 dk okuma

Go ve gRPC ile Client / Server’ın Arasını Yapalım.


Selamlar arkadaşlar. Bu yazıda sizlere gRPC ve Go hakkında ufak, minnak örnekler göstermeye çalışacağım.

gRPC Nedir? Bizi Yer Mi?

Arkadaşlar öncelikle gRPC bir yamyam değil. Zombi hiç değil. O nedenle bu yazıyı okurken bir framework tarafından yenmeyeceksiniz. Hadi canım bizi yiyosun esprilerini yapmayın.

gRPC, Google tarafından geliştirilen açık kaynaklı bir RPC frameworktür. RPC’de duymayanlar var ise, Remote Procedure Call’un kısaltması. RPC ile uzakta yer alan bir sunucudaki methodları kolayca kullanabilirsiniz. Tabii Google reyiz bunu gRPC ile bir üst seviyeye çıkararak, developer camiasını mutlu etmiş durumda.

gRPC ile daha ufak boyutlu, daha performanslı istekler oluşturabilirsiniz. Çünkü binary serialize edilen bu datalar tek bir TCP bağlantısı kullanarak birden fazla HTTP 2.0 isteği gerçekleştirirler.

gRPC standartlara sahiptir. Yani şu parametre neydi, bu neydi karmaşasını ortadan kaldırır. Bunu yaparken ortak dil olan proto dosyalarından faydalanır.

gRPC bi-directional istekleri karşılar. Yani bir yandan client istek atarken, aynı anda server client’a cevap döner. Streaming işlemini HTTP 2.0 ile yapar.

gRPC istekleri cancelation destekler. Böylece gereksiz yapılan işlemler anında durdurulur.

gRPC’yi genellikle protocol bufferlar ile görebilirsiniz. Tabii ki protocol buffers şart değil. Ancak neden kendinize eziyet edesiniz? Elinizde böyle basit, kolay bir imkan varken.

Bu Kadar Mükemmel Mi?

Hayır. Ancak, mükemmel olmasını engelleyen faktörler, direkt bu framework’ün eksikliği değil.

  • Mesela tarayıcılar şu anda tamamen bir destek sunmamakta. Tabii ki gRPC-web gibi implementasyonlar mevcut.
  • Daha az okunabilirdir. Yani standart bir rest isteğindeki okunabilirlik burada yoktur. Çünkü protobuf şeklinde serialize edilir. Gerçi bu neden kötü olsun?
  • Uygulanması zordur. Çünkü hem adaptasyonu hem de REST’e olan alışkanlık bu yapıya uymayı biraz zorlaştırır. Gerçi bi kere deneyin seversiniz kesin.

Protofol Buffers Nedir? Ben HTTP Falan Biliyorum :S

Arkadaşlar protocol buffers’ı kullanmak için tarayıcıya protocol:// yazı… durun durun şaka yaptım. Öyle bir şey değil. Protocol buffers, bi IDL yani interface design langauge. Uzantısı *.proto şeklindedir. Yine google tarafından geliştirilmiştir ve binary serialization protokolü olarak da biliriz.

Peki Bunun Bana Faydası Fedir?

İçindeki faydacı yapıyı tanıyorum dostum. Bu IDL’in en büyük faydası, client için generate edilecek olan kodun dil bağımsız şekilde çalışabilmesi. Bir ortak dil olmasının dışında bu dosyaları kullanarak Go, Java, PHP, C# vb. diller için kodlar generate edersiniz.

Evet kafanızda bir şeyler oturuyor dimi. Bir defa oluşan bir protocol buffer dosyası, istenilen dile kod generate eder. Herhangi bir şekilde endpoint vs. bilgisine gerek olmaksızın direkt olarak generate edilen kodlar, kullanıma hazır olur.

Bir proto dosyası aşağıdaki gibi tanımlanır.

Tabii ki farklı şekillerde tasarlanan proto dosyaları da göreceksinizdir. Ancak bu örnekten konuşacaksak, service bilgisi implement edilecek servisi sunar. Gördüğünüz gibi rpc keywordü ile bunun RPC’de implement edilmesi gereken bir method olduğuınu tanımlarız.

Bu dosyada bütün işler mesajlar olarak görülebilir. Mesajları class’lar gibi düşünün. Değişken adlarını da propertyler. Bu yapıda property’den daha çok verdiğiniz 1 gibi değerler önemlidir. Birine 1 derken sonraki gelene 2 dersiniz.

Yukarıdaki örnekler bize unary bir yapıyı sunarken, istersek server streaming, client streaming ya da hem client hem de server’ın stream yaptığı bi-directional (bidi) işlemlerini de yapabiliriz. Bunu büyük veri işlemlerinde kullanmak isteyebilirsiniz. Streaming işlemi için stream keywordünü kullanırız.

Bu örnekler üzerinden bir protocol buffer dosyası kullanarak go dosyalarını şöyle generate edebiliriz.

Şimdi bir örnekle go dilinde bu client-server iletişimini hem unary hem de bi-directional yapıyı nasıl sağlarız görelim.

protoc ve Gerekli Pluginlerin Kurulumu

Öncelikle protoc dosyasının indirilip path’e eklenmesi gerekiyor. Bu dosyaya şu adresten ulaşabilirsiniz.

Releases · protocolbuffers/protobuf

Daha sonra şu komutlarla hem generator hem de go dili için olan plugin’i sistemimize kuralım.

Her şey tamam ise go projemizin olduğu dizinde client, server, gen, protos adında klasörler açalım.

Daha sonra protos klasörüne health.proto adında bir dosya oluşturalım.

Bu bizim proto dosyamız. Bir de bunlar için kod generate edeceğimiz, server’ı ve client’ı çalıştıracağımız Makefile dosyasını oluşturalım. Bu şart değil. Ancak o build komutunu her defasında vermek istemeyebilirsiniz.

Şimdi ilk komutumuz şu olacak

make create-code

Eğer sizde make yok ise, ilgili blokları manuel yapabilirsiniz. Yukarıdaki komut proto dosyamızı kullanarak go komutlarını oluşturacaktır.

Şimdi server klasörüne gidelim. Ve server’ımızı şöyle implement edelim.

Öncelikle şu komutla gRPC paketini kuralım.

Sonra kodumuzu şöyle implement edelim.

Server tarafında hem unary (GetSystemHealth) hem de bi-directional(GetCpuData) yapıya ait fonksiyonları görmektesiniz.

Fark ettiyseniz, basit bir TCP portu dinliyoruz. Daha sonra kurduğumuz gRPC paketi ile healthServer adında bir struct’ı gRPC Server’ımıza register ediyoruz.

Daha sonra da gRPC server’ımız bu TCP bağlantısı üzerinden serve ediliyor. Tarayıcıdan açarak kullanabileceğiniz bir şey değil tabii bu. Bu işlem bu kadar :)

Artık client’ı implement edebiliriz. Bu işlem için client klasörüne gidelim ve client.go adında bir dosya açalım. İçeriği de şöyle olsun;

Bu, client tarafında hem unary çağrıları yapan hem de bir streamden verileri dinleyen kodu görmektesiniz.

Gördüğünüz gibi, stream datası Recv() fonksiyonu ile sürekli veri almakta. Eğer veri yok ise yani EOF dönüyor ise ya da bir hata var ise döngüyü break ederiz. Sistem sürekli olarak çalışıyorsa da zaten server tarafındaki GetCpuData() içerisindeki fonksiyonda yer alan loop devam ediyor.

Hepsi bu kadar :) Okuduğunuz için teşekkür ederim.

Bu yazıda yer alan kodların olduğu repoya şuradan ulaşabilirsiniz;

GitHub - aligoren/grpc-example-2

Kaynaklar