Servisler Arası İletişim

Emeltemakcay
riseconsulting
Published in
7 min readJul 28, 2023

By Halil İbrahim Araç, Kubilay Kenan, Serhan Altug, Emre Gazel

Robert C. Martin

“gather together those things that change for the same reason, and separate those things that change for different reasons.”

“Aynı amaç için bir araya getirin, farklı amaçlar için parçalayın”

Robert C. Marting’in Single Responsibility prensibi için ortaya koyduğu bu ilke aslında mikroservis mimarisinin de çıkış noktası olarak değerlendirilebilir.

Mikroservis mimarisi bir projenin birbirinden izole edilebilecek bileşenlerini küçük projeler olarak parçalamak ve belirlenecek ilkelerler bu servisleri haberleştirmek olarak ele alınabilir.

Mikroservis mimarisinde, bu iletişim genellikle HTTP tabanlı API’ler (Application Programming Interface) kullanılarak sağlanır. İletişim, iki ana yöntemle gerçekleştirilir:

  • Synchronus (Senkron) İletişim: Bu yöntemde, bir hizmet diğer bir hizmetten bir işlemi tamamlamasını bekler ve sonucu doğrudan alır. Synchronous iletişimde, çağıran hizmet, cevap alana kadar bekler ve cevabı aldıktan sonra işlemine devam eder. Bu durum, çağrılan hizmetin tepki verememesi durumunda çağıran hizmetin performansını da olumsuz etkileyebilir.
  • Asynchronus (Asenkron) İletişim: Bu yöntemde, bir hizmet diğer bir hizmetle doğrudan iletişim kurmaz. İletişim için olay tabanlı mesajlaşma veya kuyruk sistemleri kullanılır. Bir hizmet, işlemi tamamladığında, diğer hizmetlere veya kuyruğa bir mesaj gönderir ve işlemi başarıyla tamamlanmış olarak kabul eder. Diğer hizmetler bu mesajı alarak gerekli işlemleri gerçekleştirirler. Asenkron iletişim, daha esnek bir yapı sunar ve hizmetlerin daha az birbirine bağlı olmasını sağlar. Ancak, durum izleme ve hataların yönetimi gibi unsurlar daha karmaşık olabilir.

Mikroservis mimarisinden önce kullandığımız monolithic mimaride projede merkezi bir data sunucusu üzerinde tüm business ervislerimiz aynı proje içerisinde yer alıyordu. Tüm bileşenlerin aynı proje olması yönetimi kolaylaştırıyor ve servisler arasında yaşanacak iletişim problemlerine ilişlkin çok komplike tasarımlar yapmamız gerekmiyordu. Kapsamı çok geniş olmayan dört beş kişilik ekiplerin yeterli olduğu projelerde monolithic mimari işimizi fazlasıyla görüyordu. Bu nedenle farklı bir yapı arayışına girilmedi.

Ancak business operasyonları daha komplike bir hale geldikçe bu operasyonların daha küçük parçalara ayrılması ihtiyacı ortaya çıktı. Her proje sistemden tamamen izole bir proje olarak modellendi ve diğer projelerle arasındaki iletişimi yönetecek mekanizmalar kurgulandı. İşte bu mimarinin ismi mikroservis mimarisidir.

Şimdi aynı projenin monolithic ve microservice mimarisi ile nasıl tasarlandığını bir örnekle ifade etmeye çalışalım.

Monolithic Architecture

Resimde tipik bir monolithic uygulama mimarisi görülmektedir. İşin yapıldığı katman (business) katmanı Application Layer katmanıdır. Örneğimizde Order ve Payment olarak iki farklı business süreci gösterilmiştir.

Bu süreçlere ait operasyonlar ilgili servisler içerisinde yazılan metodlar yardımıyla ele alınmaktadır. Bu süreçler kodlanırken ihtiyaç duyulduğunda uygulamaya ait diğer katmanlara ait bileşenler kullanılabilmektedir.

Örneğin bir sipariş verildiğinde daha önceki siparişlere erişmek ve kullanıcıya uygulanacak ek indirim miktarını belirlemek için Data Layer üzerinde yer alan ve merkezi veritabanına erişim sağlayan metodlar kullanılabilir.

Bu mimaride katmanlar arasında paylaşılacak kaynaklar ortak bir katmandan referans alınmakta ve kod tekrarı en aza indirilebilmektedir. Genellikle merkezi bir veritabanı kullanılarak tüm servislerin aynı veri kaynağından faydalanması tercih edilir.

Mikroservis Mimarisi

Bu yapıda karmaşık iş süreçleri küçük projelere ayrılarak bu projelerin http üzerinden birbiri ile haberleşmesi kurgulanmaktadır.

Servisler genellikle yaygın bir kullanıma sahip rest protokolü ile haberleşir. Buradaki Api Gateway katmanı da aslında ayrı bir projedir. Gelen talebi ilgili mikroservise yönlendirmekten sorumludur.

Bu mimaride her mikroservis sadece kendi yapacağı işle ilgilenmektedir. Bu anlamda single responsibility prensibinin başarılı bir şekilde uygulanmasını sağlamaktadır. Ayrıca servisler arası iletişim http üzerinden sağlandığından her servis farklı bir teknoloji ile geliştirilebilmektedir.

Ancak servisler arası iletişimi yönetmek, özellikle hata durumlarında alınacak tedbirleri planlamak ve bir isteğin başından sonuna kadar bütünlüğünü doğrulamak (transaction yönetimi) için çok iyi planlama yapılması gerekir.

.NET Core’da servisler arası iletişim için kullanabileceğiniz bazı yaygın yöntemler:

1. HTTP İstekleri (API Tabanlı İletişim):

.NET Core, HTTP tabanlı API’ler oluşturmanıza ve istemcilerin bu API’lerle iletişim kurmasına olanak tanır. Bu yöntem, farklı uygulamalar veya bileşenler arasında veri alışverişinin temel bir yoludur. ASP.NET Core web API’leri oluşturarak, farklı servisler arasında veri alışverişi sağlayabilirsiniz. API’ler, JSON, XML veya diğer veri biçimleriyle veri alışverişine izin verir.

2. Mesaj Kuyrukları (Message Queues):

Mesaj kuyrukları, uygulamaların birbirleriyle asenkron bir şekilde iletişim kurmasına izin veren bir iletişim mekanizmasıdır. Mesaj kuyrukları, gönderen uygulamaların mesajları bir kuyruğa yerleştirmesine ve alıcı uygulamaların bu mesajları kuyruktan alıp işlemesine izin verir. Bu, uygulamalar arasında esnek ve gevşek bağlı bir iletişim sağlar. .NET Core’da, Azure Service Bus, RabbitMQ ve Kafka gibi mesaj kuyruğu çözümleri kullanabilirsiniz.

3. Web Soketleri (WebSockets):

Web soketleri, istemci ve sunucu arasında tam dubleks, sürekli bir iletişim bağlantısı kurmaya olanak tanır. Bu, gerçek zamanlı uygulamalar veya durum güncellemeleri gerektiren senaryolar için idealdir. .NET Core, WebSocket protokolünü destekleyen ASP.NET Core Middleware’ı ile web soketlerini uygulamalara entegre etmeyi sağlar.

4. WCF (Windows Communication Foundation):

WCF, .NET Framework’ün eski bir bileşeni olsa da, .NET Core ile hala bazı senaryolarda kullanılabilir. WCF, farklı platformlar ve protokoller arasında iletişimi kolaylaştırmak için kullanılan kapsamlı bir teknolojidir. Ancak, .NET Core ile WCF’nin bazı sınırlamaları ve platform desteği eksiklikleri olabilir.

5. RESTful Servisler:

RESTful servisler, HTTP protokolünü kullanarak kaynaklar üzerinde işlem yapmaya dayalı bir iletişim yaklaşımıdır. .NET Core, ASP.NET Core Web API’leri kullanarak RESTful servisler oluşturmayı destekler. Bu tür servisler, genellikle JSON formatında veri alışverişi yapar ve HTTP metodları (GET, POST, PUT, DELETE vb.) kullanarak kaynaklar üzerinde işlemler gerçekleştirir.

Unutmayın ki her senaryo için en uygun iletişim yöntemi, uygulamanızın gereksinimlerine bağlı olarak değişebilir. Bu nedenle, kullanacağınız iletişim yöntemini seçmeden önce, projenizin ihtiyaçlarına ve gereksinimlerine uygun olduğundan emin olmalısınız.

.NET Core’da HttpClient kullanarak bir API’ye istek göndermek için aşağıda basit bir örnek kod bulunmaktadır. Bu örnekte, bir JSON API’ye GET isteği yapılacaktır.

Yukarıdaki kod örneği, HttpClient sınıfını ve asenkron metotları kullanarak bir API’ye GET isteği yapar ve yanıtı alır. Eğer yanıt başarılıysa, JSON içeriği ekrana yazdırılır. Aksi takdirde, hata durumunda uygun mesajlar ekrana yazdırılır.

Kodun çalışabilmesi için proje dosyasında `System.Net.Http` paketinin eklenmiş olması gerektiğini unutmayın. Bu, .NET Core uygulamasında HttpClient’ı kullanabilmek için gerekli olan pakettir. Proje dosyanızdaki `.csproj` dosyasında paketi eklemek için aşağıdaki örneği kullanabilirsiniz:

<ItemGroup>
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>

Versiyon numarası güncel olabilir, en son sürümü kontrol ederek ekleyin. Bu örnek, sadece temel kullanımı göstermektedir. Gerçek uygulamalarda hata işleme, güvenlik ve performans gibi diğer unsurları da göz önünde bulundurmanız önemlidir.

Api projesini Windows Servis olarak host etmek

Bildiğimiz gibi .net core api projesi derlendiği zaman bir dll ve exe dosyaları üretiyor. Api projesi bu iki dosya ile ayağa kalkıyor.

İşte tam bu noktada aklıma exe dosyasını Windows service olarak kaydetmek geldi. Bir api projesi oluşturuyorum.

Bunun için Program.cs dosyasına WindowsService’i eklememiz gerekiyor. Bunun için

Microsoft.Extensions.Hosting.WindowsServices

Paketini nuget üzerinden eklememiz gerekiyor. Portumuzu sabitliyoruz. Biz 5000 olarak düzenledik.

Api projesinin demo için hazır gelen WeatherForecast controller üzerinden test edeceğiz.

Projemizi publish etmek için aşağıdaki ayarları yapıyoruz.

Show all settings kısmını da şu şekilde ayarlıyoruz.

*Produce single file ve Enable ReadyToRun compilation seçili gelmediği için eksik dosya hatası ile karşılaştık.

Şimdi sıra geldi servisimizi kurmaya.

Publish yaptığımız klasörde şu dosyalar bulunuyor.

Tüm dosyaları C:\ApiAsWindowsService kopyaladım. Şimdi servisimizi kurabiliriz.

Bunun için komut satırını yönetici olarak açıp aşağıdaki komutu yazıyoruz.

sc.exe create “ApiAsWindowsService” binpath=”C:\ApiAsWindowsService\ApiAsWindowsService.exe”

sc start ApiAsWindowsService ile servisimizi başlatıyoruz.

Chrome üzerinden http://localhost:5000/weatherforecast ‘i açınca aşağıdaki görüntüyü alıyoruz.

Artık windows servisimize controller ekleyip istediğimiz parametreleri göndererek tetikleyebiliriz.

Servisi silmek için;

sc delete ApiAsWindowsService

Örneğin RaporController ekleyip içine PrepareReport(DateTime startdate,DateTime enddate) şeklinde çalışan bir endpoint ile istediğimiz tarih aralığında rapor alabiliriz.

Java da HttpClient ile Json

Javada Httpclient ile istek atıp json cevap almak .net ile çok benzerlik göstermektedir. Java’da da bulunan HttpClient classı ile istek atılır.

Get

Örnek;

public CompletableFuture<Map<String,String>> GetJSON(URI uri) {
//Json parse edecek classımızı çağırdık
JsonMapper jsonMapper = new JsonMapper();

//HttpRequest sınıfımızı HttpClient ta kullanmak için oluşturduk HttpRequest request = HttpRequest.newBuilder(uri) .header("Accept", "application/json").build();

//İsteğimizi gönderdik daha sonra json objesini jsonmapper classıyla parse edilmesini istedik
return HttpClient.newHttpClient().sendAsync(request, BodyHandlers.ofString()).thenApply(HttpResponse::body) .thenApply(jsonMapper::readValue);}

// Gelen Response objesini parse ettireceğimiz classı parse eden kütüphaneden extend ettikclass JsonMapper extends
com.fasterxml.jackson.databind.ObjectMapper {
Map<String,String> readValue(String content) {
try {
return this.readValue(content, new TypeReference<>(){});
} catch (IOException ioe) {
throw new CompletionException(ioe);
}}

Post

Örnek;

public CompletableFuture<Map<String, String>> PostJSON(URI uri, Map<String,String> map) throws IOException{ 

//Request body objemizi JsonMapper classımızı kullanarak json olarak hazırladık
JsonMapper jsonMapper = new JsonMapper ();
String requestBody = jsonMapper.writerWithDefaultPrettyPrinter() .writeValueAsString(map);
HttpRequest request = HttpRequest.newBuilder(uri) .header("Content-Type", "application/json") .POST(BodyPublishers.ofString(requestBody)).build();
return HttpClient.newHttpClient().sendAsync(request, BodyHandlers.ofString()) .thenApply(HttpResponse::statusCode) .thenApply(HttpResponse::body).thenApply(jsonMapper::readValue)}
// Bir önceki get örneğinde olduğu gibi json parse işlemlerimizde bu classı kullanacağızclass JsonMapper extends com.fasterxml.jackson.databind.ObjectMapper {
Map<String,String> readValue(String content) {
try {
return this.readValue(content, new TypeReference<>(){});
} catch (IOException ioe) {
throw new CompletionException(ioe);
}}

Java ile WCF

WCF servisini import etmek için Eclipse de New -> Web Service adımları izlenerek servis import edilir. Eclipse servis proxy ve interface dosyalarını oluşturacaktır. Oluşan referanslardan servis çağırmak için yapmamız gereken;

public String GetWcfDataValue(){ 

//Servisimizi çağırdık
IMyServiceProxy service = new IMyServiceProxy();
String response = service.GetMyString(); // WCF tarafında oluşturduğumuz metodu çağırıyoruz.}

Bu yazı Rise Teknoloji “Dream Team” tarafından hazırlanmıştır.

--

--