Nedir bu Mikro Servisler (Microservices) ?

Merhaba,

Son dönem çok defa ismini duyduğumuz, neredeyse herkesin ya yeni uygulama geliştirmeye başlarken ya da mevcut uygulamalarını bu yapıya güncellemek için düşüncelere daldığı mikro servis konusunu inceleyeceğiz. Öncelikle mevcut durumun ardından mikro servis konusunu inceledikten sonra API Gateway modeli üzerinden bir örneklendirme yapacağız.

O zaman ? Buyursunlar.

Mikro Servis Yapısı Hakkında

Monolitik Mimari Yapılar
Mikro servislerden bahsetmeden önce biraz mikro servis öncesi durumları incelemek yararlı olacak diye düşünüyorum. Nereden ? Nereye ? Büyük ihtimalle şimdiye kadar hatta şu an bile geliştirdiğimiz uygulamalar monolit yapıdaki uygulamalar. (Benim öyle şu an) Peki nedir bu monolitik yapı?

Monolitik mimari geniş bir kitle tarafından kullanılan geleneksel bir mimari aslında. Geliştirdiğimiz uygulamanın tüm parçalarının aynı proje içinde olması diyebiliriz. Peki, biz zaten gevşek bağlanmış (loosely coupled) uygulamalar geliştiriyoruz. Monolitik mimari burada neyi değiştiriyor diyebilirsiniz. Açıklamaya çalışayım efendim.

Uygulama içerisinde kullandığımız tüm bileşenlerimiz birbirleri ile gevşek bağlı olabilir fakat uygulamamızın içerisinde bulunan her şey uygulamanın kendisi ile sıkı sıkıya bağlı durumda. Bunun en güzel örneği dağıtım (deployment) aşamasında karşımıza çıkıyor. Eğer biz uygulamamız içerisinde bir güncelleme yaparsak ve bunu üretim (production) ortamında yayınlamak istersek o zaman tüm uygulamayı baştan yayınlama aşamasına göndermemiz gerekiyor. Aynı durum üretim ortamında çalışan uygulamalarımızda oluşan sorunlar karşısında da ortaya çıkıyor.

Örnek vermek gerekirse bir bankacılık uygulaması içerisinde kullanıcıların varlıkları ile ilgili işlemler yapılıyor. Hesap bilgileri, kredi kartı bilgileri, yatırım bilgileri vb. Eğer kart işlemleri modülü ile ilgili bir hata oluşursa uygulamamız kartların bilgileri çekerken hata alacak durumda.

“Ne var? O noktada hata alırsa bir yolla hatayı fırlatmaz log olarak sisteme yazabilirim. Veya yumuşak bir geçiş ile kullanıcının mutluluğunu bozmam.” Evet olası bir durum, yapılabilir fakat ne kadar doğru? Tabii uygulamamız için yapacağımız yeni geliştirmelerde de bu sorun mevcut. Kart ekstreleri ile ilgili bir geliştirme yaptınız. Bunun üretim ortamına çıkması gerekiyor. O zaman tüm uygulamanın üretim ortamına alınması, hatta farklı yerlerin etkilenip / etkilenmediği kontrolleri vs. vs. Sadece kart modülü için yapılan bir değişiklik için sizi uzun bir yolculuk bekliyor aslında.

Mikro Servis Mimarisi
Bu mimaride uygulamamızı her birinin farklı bir hizmet verdiği bileşenlere ayırıyoruz. Her bileşen ayrı bir uygulama olarak yaşam döngüsünü sürdürüyor. Bankacılık uygulaması örneğimize geri dönecek olursak hesaplar, kartlar ve yatırım ürünlerinin ayrı birer küçük uygulama olduklarını düşünelim. Bu küçük uygulamalara bölmenin bize kattıkları konusunu inceleyelim.

Hesap bilgilerini dönen servisimiz gayet güzel çalışırken, kartları dönen servisimizde bir hata olması durumunda sistemin geneli etkilenmeden akışlarımız devam edebilir.

Bu küçük uygulamalardan herhangi birinde bir yük artışı olduğu zaman (küçük olmalarından dolayı) hızlı bir şekilde yatay olarak ölçeklendirilebilir. (horizontal scale). Daha sonrasında eğer yük azalırsa ölçeklendirme sonucunda oluşan yeni makinelerin kapatılması da söz konusu. (Docker ve Kubernetes)

Yine, bu küçük uygulamalardan herhangi birinde yapacağımız bir kod güncellemesini diğer uygulamalar etkilenmeden üretim ortamına alabilme yeteneğimiz de oluyor.

O zaman genel olarak baktığımız zaman mikro servis mimarisi, uygulamanın kendisinin çeşitli bileşenlere bölündüğü ve her bileşenin belirli bir amaca hizmet ettiği bir mimaridir. Bileşenler artık uygulamanın kendisine bağımlı değildir. Bu bileşenlerin her biri tam anlamıyla ve fiziksel olarak bağımsızdır. Bu şekilde kurulmuş olan bir mimari ile uygulamalarımız ayrı ayrı veri tabanlarına sahip olabildikleri gibi ayrı makinelerde de barındırılabilirler.

Avantajları

  • Mikro servislerin her biri ayrı uygulama olarak çalıştıklarından dolayı ayrı programlama dili ile de yazılabilir.
  • Ekibe yeni katılan bir geliştiricinin (developer) tüm yapıya hakim olması için geçecek olan zamanı azaltarak belirli mikro servisler üzerinde hızlı bir şekilde çalışmaya başlaması sağlanabilir.
  • Dağıtım (deployment) aşaması her mikro servis için ayrı ayrı yapılabilir. Bu da deploy sürelerini kısaltmış olur.
  • Mikro servislerin çalıştıkları konteynır (container) üzerinde yüke göre ölçeklendirme uygulanabilir.
  • İstenildiği zaman farklı veri tabanlarında çalışacak mikro servisler geliştirilecek yapıya dahil edilebilir. Örnek olarak MongoDb ile çalışacak ve Go ile yazılmış bir mikro servisi de yapınıza sonradan dahil edebilir ve ortak çalışma alanında bu mikro servis üzerinden faydalanabilirsiniz.

Dezavantajları

  • Transaction bütünlüğünün sağlanmasındaki zorluklar.
  • Servisler arası iletişim ve bütünlük zorlayıcıdır.
  • Integration testlerin hazırlanması zordur.
  • Genel olarak iş mantığına iyi derecede hakim olmamız gerekmektedir.
  • Dağıtım (deployment) sonrası kontrol, güvenlik ve yönetim işlemlerinin iyi bir şekilde yapılması gerekmektedir. Servis sayımız çoğaldıkça bu konularda da zorluklar ortaya çıkmaktadır.

Şimdi de ufak bir mikro servis örneği ile devam edelim. Bu çalışmada bir yazar ve bir kitap servisimiz olacak. Bu servislerimiz bize sadece kendi konuları ile ilgili bilgileri verecekler.

Burada bir soru işareti ortaya çıkıyor. Bu servisleri çağıracak olan client hepsinin adresini bilmesi mi gerekiyor? Hayır, buna gerek yok. Biz bir API Gateway ekleyerek client uygulamanın bu adrese gelmesini sağlayacağız. Client API gateway üzerinden hangi işlemi isterse gateway bizim için yönlendirme (routing) işlemini yapacak ve uygun servis cevaplarını dönecek. Bunun için Ocelot kütüphanesini kullanacağız.

İlk olarak yeni bir boş çözüm (blank solution) oluşturarak ismin MyMicroServices vererek projemize başlıyoruz.

Oluşturacağımız mikro servisleri ayırabilmek için MicroServices isimli bir klasör oluşturuyoruz.

Şimdi oluşturduğumuz klasörümüze iki adet ASP.NET Core Web API projesi oluşturacağız. İsimlerini Author.Microservice ve Book.Microservice olarak vereceğiz.

Son olarak da API Gateway olarak görevlendireceğimiz MyGateWay.WebApi isimli projemizi oluşturacağız. Bu projemizi ASP.NET Core Empty proje temasını (template) kullanarak oluşturuyoruz.

Son durumda projemin yapısı aşağıdaki gibi olacaktır.

Author.Microservice isimli projeme Entities isminde bir klasör ekleyerek AuthorInformation.cs isimli sınıfımı (class) ekliyorum.

Ardından Controllers klasörüne AuthorController isminde API Controller sınıfımızı ekleyerek bize yazar listesi döndürecek olan metodumuzu ekliyoruz.

Postman üzerinden API metodumuzu test ettiğimiz zaman aşağıdaki şekilde bilgileri döndürdüğünü görebiliriz.

Aynı şekilde Book.Microservice uygulaması içinde bir Entities klasörü açarak BookInformation.cs sınıfını ekleyeceğiz. Ardından Controllers klasörüne BookController.cs sınıfımızı ekleyerek kitap bilgilerini dönecek metodu yazacağız.

Ocelot API Gateway hakkında biraz daha
Ocelot open source olarak dağıtılan .NET/Core platformları için geliştirilmiş bir API Gateway ürünüdür. Arkasında bulunan mikro servislerin adreslerini bir konfigürasyon dosyasına kayıt ederek gelen isteğin hangi mikro servise gitmesi gerektiğini tanımlayacağız. Böylelikle client bir istekte bulunduğu cama Ocelot bizim için yönlendirmeyi yapacak ve uygun cevabı dönecek.

Konfigürasyon dosyası json formatındadır. Burada rotalarımızı (route) tanımlarken karşımıza iki terim çıkıyor. Bunlar; UpStream ve DownStream UpStream client’ın geleceği adresi tarif ederken DownStream ise Ocelot’un çağıracağı iç servis bilgisini tanımlamaktadır.

Ocelot API Gateway olarak servislerin rotalarının oluşturulması haricinde kimlik doğrulama (Authentication), yetki (Authorization) ve yük dengeleme (Load Balance) işlemlerini de bizim için yapabilmektedir.

MyGateWay.WebApi projesine Ocelot paketini ekliyoruz. Bunun için isterseniz Install-Package Ocelot komutunu isterseniz de Nuget Packet Manager üzerinden paketin yüklemesini yapabilirsiniz.

Daha sonrasında Program.cs sınıfımız içerisinde aşağıdaki değişikliği yapıyoruz.

Buradaki amacımız uygulamamızın açılışında ocelot.json isimli dosya içerisinden Ocelot konfigürasyon bilgilerinin alınması.

Şimdi de Startup.cs isimlii sınıfın içerisinde bulunan ConfigureServices metoduna Ocelot’u ekleyelim. Ardından yine aynı sınıf içinde bulunan Configure metodunda da Ocelot kullanımı için tanım yapacağız.

Şimdi de sıra Ocelot üzerinde rota bilgilerini tanımlama kısmına geldi. Öncelikle burada iki adet mikro servisin hangi portlar üzerinden çalıştığının kontrol etmemiz. Daha sonrasında ise VS üzerinden uygulamalardan birini çalıştırdığımız zaman hepsinin ayağa kalkması için bir değişiklik yapmamız gerekecek.

Önce servis portları. Bunun için Author.Microservice ve Book.Microservice projelerine tek tek sağ tuşal tıklayarak açılan Properties penceresinde sol bölümde bulunan Debug menüsünü açıyoruz. Port bilgisi sayfa üzerinde gelecektir.

Burada port bilgisini Book.Microservice için 1360 Author.Microservice için 1361 olarak değiştiriyoruz. Bu değişikliği isterseniz projelerin her birinde bulunan launchSettings.json dosyası üzerinden de yapmanız mümkün.

Uygulamaların hepsinin aynı anda çalıştırılması için Solution Explorer üzerinden Solution dosyasına sağ tuşla tıklayarak Properties menüsü üzerinden açılan sayfada değişiklikleri aşağıdaki gibi yapabilirsiniz.

Şimdi Ocelot üzerinde rota tanımlarımızı yapabiliriz. Bunun için daha önceden tanımını yaptığımız ocelot.json isimli dosyayı MyGateway.WebApi projemizin root’una tanımlıyoruz. Ardından aşağıdaki şekilde rota (route) tanımlarının yapıyoruz.

Burada yaptığımız tanımlamaları biraz açıklamak gerekiyor.

Routes altında tanımladığımız;

DownstreamPathTemplate: Ocelot’un gideceği API rotası olarak açıklanabilir. 
DownstreamScheme: http olarak veya https olarak gidileceğinin tanımı. 
DownstreamHostAndPorts: Author servisi için kullanılacak olan Ocelot arkasındaki adres bilgisi.

UpstreamPathTemplate: Client uygulamanın gateway’e geleceği API rota bilgisi. 
UpstreamHttpMethod: Client uygulamanın hangi HTTP Verb için bu adrese geleceğini tanımladığımız yerdir.

Ardından tanımlarımızı ve servislerimizi test edebiliriz. Daha önceden Project Properties penceresinden tüm uygulamalar beraber çalışmaya başlasın dediğimiz için F5 dememiz servislerin hepsinin çalışması için yeterli olacaktır.

Eğer pencere üzerinden bir değişiklik yapmadıysanız hepsini tek tek çalıştırmanız gerekmektedir.

Postman ile API Gateway uygulamamıza hem kitaplar hem de yazarlar için çağrılarımızı yapalım. Bakalım nasıl bir bilgi gelecek.

Gördüğünüz gibi hem http://localhost:5000/gateway/Book hem de http://localhost:5000/gateway/Author adresleri API Gateway uygulamamız içerinden çağırılan adresler. Bu adresleri Postman uygulaması ile çağırdığımız zaman Ocelot bizim için uygun olan servise gidiyor ve o servis sonucu alarak bize geri iletiyor.

Böylelikle client’ın hangi servisi nasıl çağırması gerektiğini bilmesine gerek kalmıyor. Client sadece API Gateway adresini biliyor ve oraya geliyor.

Umarım mikro servis mimarileri ve temel çalışma prensiplerini anlama konusunda yararlı bir makale olmuştur.

Görüşmek üzere…

Kaynaklar:

http://mustafabas.me/tr/mikroservis-mimarisi-nedir-avantajlari-dezavantajlari-nelerdir–b-1006

Microservice Architecture in ASP.NET Core with API Gateway

RabbitMQ İle İlk Adımlar

İmaj adresi : https://www.rabbitmq.com/img/home/banner/webinar/RabbitMQ-Hero-queues-desktop.svg

RabbitMQ’ya bağlanma, kanal ve kuyruk oluşturma, mesajlarımızı gönderip, okuma işlemlerini incelemeye çalıştım. Umarım anlaşılır olmuştur.

Projenin Github bağlantısı aşağıdaki gibidir.
https://github.com/onurkarakus/RabbitMQMessageApplication

Merhaba,

Çocukluğundan kalan bir anı sanırım. Büyüdüğüm zamanlarda artık çok gitmediğim şehrimizde olan fuarlar hep aklımda. Kalabalık olmasının yanı sıra farklı türde ve tarzda bir sürü eğlence yerinin olmasından dolayı seslerin siz gezerken kulağınızda zorlayıcı etkileri. Bir yandan çalan rock müziğin yanında diğer yandan gelen türkü seslerinin karışması. Tabii bunlara eklenen insanların konuşmaları, birbirlerine seslenmeleri ve çocukların neşeli sesleri. Aslında tam bir kaos ortamı. fuar alanından çıktıktan sonra aklınızda kalan tek şey karışıklığın verdiği yorgunluk oluyordu.

Uygulamalarımızda aslında bu şekilde bir yapıya sahip diye düşünüyorum. Bir sürü mesajın düzensiz bir şekilde gönderip alınması ile birlikte ciddi performans sorunlarının oluşması olası. Bu mesajların bu mesajları işleyen yapıların bu işlemlerini asenkron ve sırayla yapmasının sağlamak için de yapılar mevcut. Bunlardan son dönem en çok kullanılanı ise RabbitMQ.

Bir önceki yazımda RabbitMQ hakkında genel bilgileri vermeye ve kurulum işlemlerinin hem OnPremise hem de Docker üzerinde nasıl yapılacağını anlatmaya çalıştım. Bu yazıya aşağıdaki bağlantıdan ulaşabilirsiniz.

https://onnurkarakus.medium.com/nedir-bu-rabbitmq-28e3e9296ecd

Bu yazıda ise C# ile RabbitMQ’yu nasıl kullanacağız? konusunu incelemeye ve sizlere anlatmaya çalışacağım. C# ile iki Console uygulaması oluşturarak birinden gönderdiğimiz mesajların diğer uygulama üzerinden okunmasını sağlayacağız. Böylelikle temel olarak RabbitMQ işleyişini kontrol edebileceğiz. Uygulamamız için bir önceki yazımda anlatmaya çalıştığım Docker kurulumunu yaptığımız RabbitMQ yapısını kullanacağız.

O zaman başlayalım.

İlk önce Visual Studio üzerinden yeni bir Solution dosyası oluşturuyoruz. Daha sonrasında Console uygulamalarımızı bu Solution içerisinde oluşturacağız.

Uygulamalarımız Sender ve Receiver isminde iki console uygulaması olacak. Şimdi ilk olarak Sender uygulamamızı solution içerisinde oluşturalım. Uygulamamızın adı RabbitMQMessageApplication.Sender olsun.

Uygulamamızda RabbitMQ üzerinde oluşturacağımız kuyruğa bir sınıftan oluşturduğumuz nesnemizi göndereceğiz. Bu nesneyi RabbitMQ’ya göndermeden önce de Json ile serileştirmemiz gerekecektir.

Bu işlemleri yapabilmek için uygulamamıza aşağıda bulunan iki Nuget paketini eklememiz gerekmektedir.

Visual Studio içerisine bulunan Nuget Package Manager ile paketlerimizi ekleyebiliriz.

Şimdi uygulamamızı RabbitMQ üzerinde oluşturacağımız bir kuyruğa mesaj göndermesi için kodlarımızı ekleyelim.

İlk önce mesaj nesnemizi tanımlayalım. Bu nesnemiz kuyruğa gönderilecek ve başka bir uygulama üzerinden okunacak olan nesnemiz olacaktır. Sınıf ismini MessageInformation olarak veriyorum.

Daha sonrasında RabbitMQ için tanımları yaptığımız, kuyruk bilgilerini belirlediğimiz ve mesajımızı bu kuyruğa gönderdiğimiz kodları ekliyoruz.

Satır 12 : RabbitMQ bağlantımızı oluşturuyoruz. Burada kurulu olan adresimizi, kullanıcı adımızı ve şifremizi yazmamız yeterli olacaktır.

ConnectionFactory() RabbitMQ host uygulamasına bağlanmak için kullanılır.

Satır 13-14 : Burada RabbitMQ için bağlantımızı ve kanalımızı hazırlıyoruz.

CreateConnection() ConnectionFactory() ile tanımlarını yaptığımız host bağlantımızı oluşturuyor.

CreateModel() RabbitMQ üzerinden yeni bir kanal oluşturmak için kullanılır. Bu kanal sayesinde kuyruk bilgisi oluşturulacak ve mesajımız bu kuyruğa bırakılacaktır.

Satır 16 : Kanal tanımımız üzerinden kuyruk bilgilerimizi giriyoruz ve yeni bir kuyruk oluşturuyoruz.

QueueDeclare() Oluşturduğuz RabbitMQ tanımları içinde bir kuyruk oluşturmamızı sağlayacaktır.

durable : Kuyruğa gönderilecek mesajların saklama yöntemini belirler. Mesajlar InMemory olarak hafızada saklanabilirken istenirse fiziksel olarak da makine içerisinde saklanabilmektedir. Tabii burada hız, performans ve bilgilerin durumu önemli ölçüm değerleri olmaktadır. OnMemory kullanım eğer makine kapanırsa verilerin kaybolacağı anlamına gelmektedir. Bu yüzden kuyruk içinde iletilecek verilerin durumlarına göre bu tanım dikkatli bir şekilde kullanılmalı diye düşünüyorum.

exclusive : Kuyruğun bizim oluşturduğumuz bağlantı haricinde diğer Connectionlar ile de kullanılabileceğini belirler.

autodelete: Eğer kuyrukta bulunan mesaj bilgisini tüm tüketiciler (consumer) almış ise o zaman kuyruğun otomatik olarak silinmesi sağlanır. Yalnız burada dikkat edilmesi gereken konu eğer kuyruk içerisinden bilgiyi alacak bir consumer işlemi iptal edildi veya hata aldı ise o hakkının kaybedecektir. Bunun için autodelete özelliğini kapatıp kuyruk silme işlemi bir metot ile de yapılabilmektedir.

Satır 25 : Mesaj nesnemizi oluşturup gerekli bilgileri dolduruyoruz.

Satır 29 : Mesajımızı serileştirerek kuyruğa gönderilebilecek yapıya getiriyoruz.

Satır 32 : Mesajımızı RabbitMQ üzerinde oluşturduğumuz kuyruğa gönderiyoruz.

BasitPublish() : Hazırladığımız mesajın bir veya daha fazla kuyruğa aktarılmasını sağlar. Bir kuyruk tamam fakat birden fazla kuyruk konusu? Bu işlem için ExchangeType bilgileri kullanılmaktadır. ExchangeType bilgilerinin isimlerini aşağıda bulabilirsiniz. Kendileri ile ilgili yazıları da detaylı bir şekilde araştırdıktan sonra yazmaya çalışacağım.

  • Direct
  • Fanout
  • Headers
  • Topic

Uygulamamızı çalıştırdığımız zaman kullanıcıdan aldığımız mesaj bilgisinin RabbitMQ kuyruğuna gönderildiğini görebilmekteyiz.

Yine aynı şekilde RabbitMQ yönetim paneli içerisinden de kuyruk bilgilerimizi ve bu kuyruk içerisinde bulunan mesajların sayısal bilgilerine ulaşmamız mümkündür. Bunun için http://localhost:1360 adresine gidiyoruz ve guest@guest kullanıcı bilgileri ile login oluyoruz.

Burada da görebileceğiniz gibi MessageTest isminde bir kuyruğumuz ve onun içinde de Ready durumunda bekleyen bir adet mesajımız bulunmaktadır.

O zaman şimdi bu mesajı RabbitMQ üzerinden nasıl okuyacağımıza bakalım. Bunun için yine aynı solution içerisine RabbitMQMessageApplication.Receiver adından yeni bir console uygulaması ekliyoruz.

Projemize RabbitMQ işlemlerini yapabilmek için ve aldığımız mesajları geri açabilmek için aşağıdaki iki paketi Nuget ile ekliyoruz.

Şimdi yapmamız gereken RabbitMQ’ya bağlanarak Sender uygulaması ile oluşturduğumuz ve bir nesnemizi gönderdiğimiz kuyruğa bağlanarak mesajımızı almak. Serileştirilmiş bir şekilde bize gelen bu mesajı açarak artık istediğimiz yerde kullanabileceğiz.

Öncelikle Sender uygulaması içinde kullandığımız sınıfımızı buraya da tanımlayalım. Ortak bir proje içinden de alabilirdik ama benim tembelliğim oldu biraz.

Ardından Receiver uygulamamız için kuyruk bilgisini okuyan kod bloğumuz aşağıdaki gibi olacaktır.

Burada yine Sender uygulamamızdaki gibi ConnectionFactory üzerinden bağlantımızı oluşturduk. Kanal ve kuyruk tanımlarımızı yaptık.

Sender uygulamasından farklı olarak burada farklı olarak Received olayını (event) kullanıyoruz. Bu eventin kullanılma amacı sürekli olarak tanımlarının verdiğimiz kuyruğu dinleyerek yeni mesajların eklenmesi durumunda bu mesajları yakalayabilmektir.

BasicConsume() ile de gelen mesajımızı yakalayabiliriz. Burada kullandığımı autoAck parametresi uygulama içerisinden mesajı okuduktan sonra bu mesajın silinmesini sağlamaktadır.

İlk önce Receiver uygulamasının çalıştıralım ve Sender uygulamasının test ettiğimiz sırada eklediğimiz mesajın kuyruk üzerinden geldiğini görelim.

Şimdi isterseniz hem Sender hem de Receiver uygulamalarını aynı anda çalıştırarak gönderilen mesajın nasıl iletildiği kontrol edelim.

Kuyrukların Silinmesi
Oluşturduğumuz kuyrukların belirli durumlar karşısında silinmesini kendimiz metot kullanarak yapabiliriz. Daha önce de anlatmaya çalıştığım gibi otomatik bir silme mekanizması mevcut fakat bu consumer olan uygulamaların hataları karşısında mesajları almak haklarını kaybetmelerine sebep olabiliyor.

Kuyruk silme işlemini QueueDelete() ile yapabiliyoruz.

queue : Silmek istediğimiz kuyruk adıdır. 
ifUnused : Eğer kuyruk kullanılmıyor yani herhangi bir consumer yok ise o zaman silinsin anlamına gelmektedir. 
ifEmpty : Eğer kuyruk boş ise silinsin anlamına gelmektedir.

Evet bu yazımda RabbitMQ ile temel işlemlerin nasıl yapılacağı konusunu anlatmaya çalıştım. Umarım açıklayıcı olmuştur.

Bir başka makalede görüşmek üzere.

Kaynaklar :
https://www.rabbitmq.com/documentation.html
https://www.borakasmer.com/rabbitmq-nedir/
https://www.rabbitmq.com/dotnet-api-guide.html

Nedir bu RabbitMQ?

Merhaba,

Öğrenme isteği hem işimizin hem de hayatımızın önemli bir parçası. Bilgileri kovalamak, kovalayıp yakaladıkça işimize ve hayatımıza yenilikler katmak ve en önemlisi başarma duygusu. Bunların yeri çok önemli insan hayatında.

Tabii son yıllarda bilgiye ulaşmak özellikle internetin de yardımıyla kolaylaşmış durumda. Aradığımızı okumak için, okumak zor geliyorsa birilerinin anlatması için bir vidyo olarak bulmak artık çok kolay. Eskilere baktığımız zaman bir bilgiye ulaşmak, bir veriye ulaşmak o kadar kolay değildi. Yaşlıyım kabul edelim.

Benden büyüklerle (fakat çok büyüklerle) konuştuğum zaman bu bilgi alışverişinin zorluğunu bir nebze de olsa anlayabiliyorum. Örnek vermek gerekirse dedem. Aslında kendisi öğretmen fakat okuma aşkı yüzünden dışarıdan posta ile bir üniversite daha bitirmiş. Posta? Evet kitapların, sınavların ve diğer dokümanların posta ile gönderildiği bir üniversite yapısı.

Hem okuyan için zor bir süreç hem de okul için zor bir süreç aslında. Özellikle sınavlar konusu biraz karışık. Öğrencilere gönderilecek sınavların hazırlanması, bu sınavların öğrenciler tarafından tamamlandıktan sonra gönderilmesi ve okulda görevli kişiler tarafından kontrol edilip notlarının verilmesi. Şimdi baktığımız zaman elektronik ortamlarda bu işlemler kolay oluyor.

Fakat yazılımlarımız içerisinde de bu sorunlar yaşanmıyor mu? Yazılımların mesajlaşmaları, bu mesajların işlenmesi ve geriye cevaplarının dönülmesi tıpkı mektup ile yapılan sınavlar gibi zor olabilir mi? Dilerseniz bugün bu konuyu ve bu konu için sunulan güzel bir çözümü inceleyelim.

Geliştirdiğimiz uygulamalar, verilerin işlenmesinden sorumlu temel olarak. En küçük noktada düşünürsek uygulama genelinde mesajların işlenmesi (alınması ve cevaplanması) uygulama performansını etkileyen bir durumdur. Bu noktada bazı kullanılan işlemlerin anlık yapılması ihtiyacının olmadığının düşünerek bu işlemleri asenkron olarak yapmak isteyebiliriz. Bir örnekle konuyu açıklamaya çalışayım. Loglama. Bir API uygulamamızda gelen istek (request) ve cevapların (response) loglanması için middleware katmanın yazdığımız loglama işlemi her request ve response için uygulamıza bir yük oluşturacaktır. Peki, bu işlemleri asenkron bir şekilde yapsak? O zaman işte bize yardım için devreye RabbitMQ giriyor.

RabbitMQ açık kaynak kodlu bir mesaj kuyruk sistemidir. Şu an kullanılan RabbitMQ gibi farklı uygulamalar da mevcuttur. (Apache Kafka, Microsoft Azure Service Bus veya MSMQ)

Genel Özellikleri ile RabbitMQ?

  • Erlang dili üzerinde geliştirilmiştir.
  • Açık kaynak kodlu olduğu için yaygın bir kullanım alanına ulaşmıştır.
  • Cross platform yapısından dolayı farklı işletim sistemlerinde de kullanılabilmektedir.
  • Web arayüzü ile kullanım kolaylığı sağlamaktadır.

RabbitMQ Pusblish ve Subscriber mantığı ile çalışmaktadır. Bunun anlamı ise bir uygulamadan mesajı alıp sırası geldiği zaman bu mesajı başka bir uygulmaya iletmek olarak açıklanabilir.

RabbitMQ Genel Çalışması

Burada bazı terimlerin açıklamasına ihtiyaç olacağı için onları da açıklamaya çalışalım.

Publisher : Kuyruğa mesaj gönderen uygulamadır. 
Consumer : Kuyruktan gönderilmiş olan mesajı okuyan uygulamadır.
Queue : RabbitMQ içerisinde kullanılan mesajların alıp / verildiği kuyruk adıdır. 
Exchange : Routing Key bilgisine göre mesajların ilgili kuyruklara gönderilmesini sağlayan bilgidir. 
Exchange Type : Routing Key bilgisine göre mesajları hangi kuyruğa nasıl yönlendirilmesi gerektiğini belirleyen yapıdır.

RabbitMQ Kuralım

Ben iki farklı şekilde kurulum işlemlerini anlatmaya çalışacağım. İlk olarak her yerde karşımıza çıkan onpremise kurulumdan bahsetmek istiyorum.

RabbitMQ Erlang dilinde yazıldığından dolayı öncelikle bilgisayarımıza Erlang kurmamız gerekmektedir. Bunun için aşağıda bulunan bağlantıyı kullanabilirsiniz.

http://www.erlang.org/downloads

Erlang kurulumlarımızı tamamladıktan sonra RabbitMQ kurulum dosyaları için de aşağıdaki bağlantıyı kullanabilirsiniz.

http://www.erlang.org/downloads

Kurulumların ardından http://localhost:15672 adresi ile de RabbitMq yönetim panelini açabilirsiniz.

Bir başka kurulum yöntemi ise Docker kullanmak. Ben genellikle Docker üzerinde bu tarz uygulamalarımı kullanıyorum ve OnPremise kuruluma göre bir hayli avantajlı olduğunu düşünüyorum.

Gelin şimdi hep beraber Docker üzerinde RabbitMQ’yu nasıl kuracağımıza bakalım.

İlk olarak tabii ki Docker kurulumlarını tamamlamak gerekecek. Bu konu ile ilgili aşağıda bulunan makaleye bakabilir, kurulum işlemlerinin nasıl yapıldığını görebilirsiniz.

http://www.erlang.org/downloads

Docker kurulum işlemlerimizi tamamladıktan sonra RabbitMQ imajını indirmemiz gerekmektedir. Bunun için Powershell üzerinden aşağıdaki komutu yazmamız yeterli olacaktır.

docker pull rabbitmq

RabbitMQ imajını indirdikten sonra Container’ı hazırlamak ve çalışır hale getirmemiz gerekmektedir. Bunun için aşağıdaki komut satırının Powershell üzerinde çalışmamız yeterli olacaktır.

docker run -d -p 1360:15672 -p 5672:5672 — — name MyRabbitMQContainer rabbitmq:3-management

Bu komut ile iki farklı konfigürasyon düzenlemesi yapmaktayız. Bunlardan ilki Docker içerisinde çalışacak olan RabbitMQ 5672 portunun kendi lokal bilgisayarımızın 5672 portu ile eşliyoruz.

Yönetim uygulaması için de kullanılacak olan 15672 portunu da yine lokal bilgisayarımızın 1360 numaralı portuna eşiliyoruz. Böylelikle lokal bilgisayarımız üzerinden http://localhost:1360 adresine girdiğimiz zaman RabbitMQ yönetim paneline ulaşabileceğiz.

Daha sonra Docker Desktop uygulaması üzerinden çalıştırdığımız komutların hem imaj hem de container için çalıştığının görebiliriz.

RabbitMQ yönetim paneline giriş için ise lokal bilgisayarımızdan http://localhost:1360 adresine gitmemiz yeterli olacaktır. Açılan giriş ekranına aşağıdaki bilgiler ile giriş yapabilirsiniz.

Kullanıcı Adı: guest
Şifre: guest

Genel olarak RabbitMQ’nun ne olduğu ve kendi bilgisayarımız nasıl kurulacağı konusunda bilgiler aktarmaya çalıştım. Bir sonraki yazımda ise RabbitMQ ile mesajlarımızı nasıl yöneteceğimiz konusuna bakacağız.

Bir başka makalede görüşmek üzere.

Kaynaklar:
https://www.rabbitmq.com/
https://www.gencayyildiz.com/blog/dockerda-rabbitmq-ayaga-kaldirma/
https://www.borakasmer.com/rabbitmq-nedir/