Microservice Mimarisinde Haberleşme Teknikleri #2(gRPC)

Furkan Güngör
Devops Türkiye☁️ 🐧 🐳 ☸️
5 min readMay 16, 2020

--

“Durgun denizin minik dalgacıkları üzerinde, güneşin altın gibi ışıldadığı pırıl pırıl bir sabahtı.

Sahilden bir mil uzaklıkta, denizi kucaklarcasına ilerleyen bir balıkçı teknesi, martılara kahvaltı zamanının geldiğini haber veriyordu. Binlerce martı, bir lokma yiyecek için mücadeleye girmişti bile. İşte zor bir gün daha başlıyordu.”

Bu yazıma Martı Jonathan Livingston kitabından bir alıntı yaparak başlamak istedim, eğer okumadıysanız şiddetle tavsiye ederim, bir geliştirici olarak mesleğime ve hayata karşı bakış açımı zenginleştirdi.

Microservice mimarisinde en önemli konulardan biri olan haberleşme tekniklerine bir önceki yazımda küçük bir giriş yapmıştım.

(Microservice Mimarisinde Haberleşme Teknikleri #1(RabbitMQ — .Net Core — CAP))

Bu yazımda ise .Net dünyasında .Net Core 3.0 versiyonundan itibaren gittikçe popülerliğini artıran gRPC ile servisler arasında iletişimi nasıl sağlarız incelemiş olacağız.

.Net 5 Preview 3 versiyonunda HTTP/2 için performans iyileştirmeleri yer alırken ve .Net 5 ile birlikte hayatımızdan çıkacak teklonojiler arasında yer alan WCF’i göz önünde bulundurduğumda gRPC ile ilgili şimdiye kadar neler yaptığımı anlatmaya karar verdim.

Bu satıra geldiğinizde gRPC Nedir ? sorusu akıllarınızda bir soru işareti olarak duruyorsa size gRPC ile ilgili temel bir giriş için şöyle alalım :)

Şu anda görev aldığım MobiRoller App Maker şirketinde her sprint planlama toplantısında şahsıma atanan görevleri incelerken acaba nerelerde gRPC kullanabilirim diye düşünüyorum :)

gRPC kullanmak istememin sebebi, enterprise bir projede nasıl çalıştığını görmek ve davranışlarını test etmek, yani savaş alanında neler yapabildiğini canlı olarak deneyimlemek. Henüz bu fırsatı yakalayamadım ancak gRPC teklonojisini yakından takip ederek güncel kalmaya çalışıyorum.

Kahvemden bir yudum aldıktan sonra gRPC Service şablonunu kullanarak yeni bir proje oluşturdum.

Başlangıç için ;

Basic level database configuration

Product nesnesi üzerinden haberleştirmek istediğim olayları protobuf dosyası içerisinde rpc olarak tanımladım ve kullandıkları message objelerini protobuf dosyasına ekledim.

Protobuf file

*.csproj içerisinde eklenen bu protobuf dosyasını Server olarak belirledikten sonra Startup.cs içerisinde bu servisi mapping’e eklemek gerekecektir.

endpoints.MapGrpcService<ProductService>();

Artık logic katmanını yazabiliriz.

Product Service for Grpc

Object mapping için AutoMapper kullanabilirsiniz, protobuf dosyasında oluşturduğunuz message objelerini AutoMapper ile istediğiniz objeye convert edebilirsiniz.

Logic tarafında dikkatinizi Authorize attribute ve IServerStreamWriter çektiyse hemen üzerinde konuşmaya başlayalım.

Geliştirilen servislerde Authentication ve Authorization olmazsa olmazlarımızdan, bu sebeple Jwt ile Authentication sağlamaya çalıştım ve hepimizin aşina olduğu Authorize attribute method tepesine ekledim, client tarafını oluşturduktan sonra test ettiğim ilk yer Jwt Bearer Token ile Authentication nasıl davranıyor konusu oldu sonuçları sizlerle paylaşacağım.

Startup.cs içerisinde klasik Authentication ayarlarımızı yapalım.

Authentication Settings on Startup.cs

IServerStreamWriter gRPC’nin en önemli vaadlerinden birisi olarak Stream özelliğinin kodunuzda vücut bulmuş hali, klasik Rest çağrılarında Response alabilmek için Request’in tamamiyle bitmesini beklerken, gRPC ile Request devam ederken işi bitmiş olan dataları Response olarak toplayabilirsiniz.

Stream özelliği yoğun hesaplamalar yapan servisler arasında şüphesiz hız kazandıracaktır.

Geliştirdiğimiz servislerde validation ile datanın istenilen formatta olup olmadığını kontrol edersiniz. Bu konuyu düşünmeye başladım, protobuf dosyasında validation nasıl sağlanabilir ?

Araştırmalarım doğrultusunda dökümanlarda protobuf dosyası içerisinde her property için validation yazabileceğimizi gördüm, biraz inceleyelim.

https://github.com/envoyproxy/protoc-gen-validate
Message validation

Bu library ile bir şekilde her property için validation rule yazabilirsiniz ancak biraz düşünelim, geliştirdiğimiz servislerde message nesnemiz büyüyebilir ve message sayısı çok fazla olabilir, inline bir şekilde validation tanımlamak bence protobuf dosyasınızı karmaşık bir hale getirecektir.

Derin düşünmeye başladım, gRPC configuration için GrpcServiceOptions isimli bir class kullanıyordu ve içinde Interceptor olduğunu görünce aklıma bir fikir geldi, request işlenirken araya girip kendi kurallarımı message üzerine uygulayabilir miydim ?

Cevap evet, ama benden önce başka bir arkadaş bunu düşünmüş olmalı :) aşağıda paylaşacağım library Fluent validation ile entegre çalışan bir middleware.

Install-Package GrpcExtensions.AspNetCore.Validation -Version 2.25.2

Fluent Validation ile entegre çalıştığı için validation rule setlerinizi daha okunaklı bir şekilde yazabilirsiniz.

Server tarafında işim bitti, client olarak bir web application projesi oluşturup iletişimi gerçekleştirmeye karar verdim ancak kahvem bittiği için enerjim tükenmişti :)

Photo by Alex on Unsplash

Yeni bir kahve yaptıktan sonra enerjimi topladım ve bilgisayar başına Client projesini oluşturmak için oturdum.

İletişimi gerçekleştirmek için server ve client aynı protobuf dosyasını kullanmalıdır.

Bu sebeple aynı protobuf dosyasını Client tarafına eklemeyi ve *.csproj içerisinde Client olarak konfigüre etmeyi unutmayın.

Startup.cs içerisinde client nesnemizi initilaze ettikten sonra Authentication davranışı test edelim.

Authentication Error (Status Code : 401)

Bu resimden çıkarmamız gereken sonuç gRPC Authentication için alışık olduğumuz Authorize attribute kullanabiliriz.

Acaba validation nasıl davranacak ?

Validation Error

Demek ki kullandığımız library Interceptor mantığı ile araya girip yazdığımız rule setleri başarılı bir şekilde uygulayabiliyor.

ProductsController.cs

Authentication, Authorization, Object Mapping, Validation, Stream gibi birçok özelliğini test ettiğimize göre neden ve ne zaman gRPC kullanmalıyız sorusuna bilgilerim doğrultusunda cevap verdikten sonra yazımı sonlandırayım.

gRPC Rest ile kıyaslandığında en önemli farklardan biri serialization ve deserialization maliyetlerinin olmaması, diğeri ise stream özelliği ile Request işlenmeye devam ederken Response alabilmemiz.

Kağıt üzerinde ve servisler arasında ki iletişimi gRPC ile sağlayan bazı şirketlerin performans sonuçlarını incelediğimizde yoğun yük altında gRPC daha performanslı görünüyor.

Henüz bu iletişim tekniğini savaş alanında gözlemleme fırsatı yakalayamadığım için performans ile ilgili cümlelerimi, araştırmalarım sonucunda edindiğim bilgiler doğrultusunda kurabilmekteyim.

Bora Kaşmer’in dediği gibi, “Mümkün ise NewtonSoftric yerine :) Protobuf kullanalım.” :) (https://twitter.com/CoderBora/status/1247660747229999109)

Martı Jonathan Livingston kitabından son bir alıntı ile yazımı sonlandırıyorum.

“Cehaletimizi kırabiliriz,becerilerimizi, yeteneklerimizi ve zekamızı kullanarak kendimizi bulabiliriz, kendimiz olabiliriz. En önemlisi, özgür olabiliriz! Uçmayı öğrenebiliriz!”

Hepiniz #EvdeKal’ın.

Kaynaklar

--

--

Furkan Güngör
Devops Türkiye☁️ 🐧 🐳 ☸️

Solution Developer — I want to change the world, give me the source code.