Mikroservis tasarımı, karmaşık uygulamaların daha küçük, bağımsız ve ölçeklenebilir parçalara bölünmesine olanak sağlar. Bu tasarım kalıpları (pattern) mikroservis mimarilerini tanımlar ve çeşitli konulara odaklanır. İşte mikroservisler için bazı yaygın tasarım kalıpları:
1. Decomposition Patterns (Ayrıştırma Kalıpları):
* Decompose by business capability (İş Yeteneklerine Göre Ayrıştırma): Bu kalıp, her mikroservisin belirli bir iş yeteneğini temsil etmesini önerir. Örneğin, e-ticaret uygulaması için envanter yönetimi, kullanıcı yönetimi ve ödeme işlemleri gibi yetenekler olabilir.
* Decompose by subdomain (Alt Alanlara Göre Ayrıştırma): Bu, uygulamanın belirli bir alt alanını (domain) temsil eden mikroservisler oluşturmayı önerir. Bu alt alanlar, genellikle belirli bir işlevsellik veya iş yeteneğini temsil eder.
2. Integration Patterns (Entegrasyon Kalıpları):
* API Gateway: Bu kalıp, genellikle istemcilerin mikroservisleri bir API aracılığıyla çağırmasını sağlar. Bu gateway, genellikle tüm mikroservislerin bir noktadan yönetilmesini ve orkestrasyonunu sağlar.
* Event-Driven Architecture (Etkinlik Temelli Mimariler): Bu kalıp, mikroservislerin birbirleriyle olay tabanlı mesajlaşma sistemleri üzerinden iletişim kurmasını önerir. Bu, her mikroservisin belirli bir olayı yayınlamasını ve diğer mikroservislerin bu olayları dinlemesini ve buna göre tepki vermesini içerir.
3. Database Patterns (Veritabanı Kalıpları):
* Database per Service (Servis Başına Veritabanı): Her mikroservis, kendi veritabanını (ya da tablolarını) yönetir. Bu, her mikroservisin veritabanının diğer mikroservisler tarafından doğrudan erişilemez olmasını sağlar, bu da daha yüksek hizmet izolasyonu sağlar.
* Shared Database (Paylaşılan Veritabanı): Bu kalıp, mikroservislerin aynı veritabanını paylaşmasını önerir. Bu, daha karmaşık senaryolar için kullanılabilir, ancak genellikle servisler arası sıkı bağımlılıklar oluşturabilir.
4. Deployment Patterns (Dağıtım Kalıpları):
* Multiple Service Instances per Host (Host Başına Birden Fazla Servis Örneği): Bu kalıp, bir sunucuda birden fazla mikroservis örneğinin çalıştır
* Multiple Service Instances per Host (Host Başına Birden Fazla Servis Örneği): Bu kalıp, bir sunucuda birden fazla mikroservis örneğinin çalıştırılmasını önerir. Bu genellikle daha verimli bir kaynak kullanımı sağlar ancak örneklere ayrı ayrı izole edilmiş ortamlar sağlamak daha zor olabilir.
* Service Instance per Host (Host Başına Bir Servis Örneği): Bu kalıp, her mikroservis örneğinin kendi sunucusunda çalıştırılmasını önerir. Bu genellikle daha fazla izolasyon ve daha az çakışma sağlar, ancak genellikle daha fazla kaynak gerektirir.
* Serverless Deployment (Sunucusuz Dağıtım): Bu kalıp, sunucusuz bilgi işlem platformları kullanarak mikroservisleri dağıtmayı önerir. Bu, genellikle kaynak kullanımını optimize eder ve operasyonel yükü azaltır.
5. Observability Patterns (Gözlemlenebilirlik Kalıpları):
* Health Check API (Sağlık Kontrolü API): Bu kalıp, her mikroservisine kendi sağlık durumunu raporlayabilen bir API eklemeyi önerir. Bu genellikle hizmetin çalışıp çalışmadığını kontrol etmek için kullanılır.
* Log Aggregation (Log Toplama): Bu kalıp, mikroservislerin loglarını merkezi bir konumda toplayıp analiz etmeyi önerir. Bu, hizmetler arası hataları tanımlamayı ve çözümlemeyi kolaylaştırır.
* Distributed Tracing (Dağıtılmış İzleme): Bu kalıp, bir isteğin mikroservisler arasında nasıl seyahat ettiğini izlemek için kullanılır. Bu, performans sorunlarını belirlemeye ve hizmetler arasındaki etkileşimleri anlamaya yardımcı olur.
6. Resilience Patterns (Dayanıklılık Kalıpları):
* Retry (Yeniden Deneme): Bir mikroservis başka bir servisle iletişim kurmayı başaramazsa, belirli bir süre boyunca yeniden denemeyi içerir.
* Fallback (Yedekleme): Bir mikroservis çağrısının başarısız olması durumunda, bir yedek operasyon gerçekleştirilir.
* Circuit Breaker (Devre Kesici): Tekrarlayan hataların bir servisin tüm sistem üzerinde olumsuz etkisini önlemek için bu kalıp kullanılır. İlk başarısızlıkların ardından, devre kesici gelecek istekleri hızlı bir şekilde reddeder, servisin düzelmesine izin verir ve sonra otomatik olarak normal operasyonlarına döner.
7. Scalability Patterns (Ölçeklenebilirlik Kalıpları):
* Horizontal Duplication (Yatay Çoğaltma): Aynı servisin birden çok örneğini çalıştırarak ve gelen talepleri bu örnekler arasında dağıtarak ölçeklendirme sağlar.
* Partitioning (Bölümlendirme): Büyük veri setlerini küçük parçalara böler ve bu parçaları ayrı mikroservislerde işler. Buna genellikle veri bölümlendirmesi veya şablona göre bölümlendirme de denir.
8. Security Patterns (Güvenlik Kalıpları):
* Access Token (Erişim Token’ı): Kullanıcı kimlik doğrulaması ve yetkilendirmesi için erişim token’ları kullanılır. Tokenlar, bir kullanıcının kimliğini ve yetkilerini temsil eder ve genellikle API isteklerinin bir parçasıdır.
* Secrets Management (Gizlilik Yönetimi): Hassas verilerin (örneğin veritabanı kimlik bilgileri, API anahtarları) güvenli bir şekilde saklanmasını ve yönetilmesini sağlar.
9. Testing Patterns (Test Kalıpları):
* Consumer-Driven Contract Test (Tüketici Tarafından Yürütülen Sözleşme Testi): Tüketici ve sağlayıcı arasındaki iletişim kanallarını test etmeyi önerir. Sağlayıcı, tüketici tarafından beklenen davranışları belirtir ve bu beklenen davranışlar bir test sözleşmesi olarak kullanılır.
* Service Virtualization (Servis Sanallaştırması): Test süresince diğer servislerin taklit edilmesi ve simüle edilmesi. Bu, testin herhangi bir servisin yanıtlarına veya durumlarına bağımlı olmamasını sağlar.
* End-to-End Testing (Baştan Sona Test): Uygulamanın tamamının, gerçek dünya senaryolarını simüle eder şekilde test edilmesi. Bu genellikle kullanıcı deneyimini doğrulamak ve karmaşık işlemleri test etmek için kullanılır.
10. Versioning Patterns (Versiyonlama Kalıpları):
* Semantic Versioning (Semantik Versiyonlama): Yeni özellikler, hata düzeltmeleri veya geriye dönük olmayan değişiklikler yapıldığında mikroservislerin sürüm numaralarının nasıl güncelleneceğini belirler.
* API Versioning (API Versiyonlama): API'nin yeni versiyonlarını oluştururken eski istemcilerin hala çalışmasını sağlar. Bu genellikle URL'de, HTTP başlıklarında veya istek gövdesinde belirtilen bir sürüm numarası kullanılarak yapılır.
Her bir mikroservis tasarım kalıbı, özgül bir amaç için tasarlanmış olup, mikroservislerle çalışırken karşılaşılan çeşitli zorluklara çözüm sunar. İhtimaller dahilinde, tüm bu kalıpların doğru bir şekilde kullanılması, mikroservis mimarisinin genel işlevselliğini, esnekliğini, güvenliğini ve ölçeklenebilirliğini artırabilir. Her mikroservis projesi, projenin özgül gereksinimlerine ve hedeflerine dayalı olarak farklı bir mikroservis kalıpları seti kullanabilir.
Mikroservis kalıplarını tartışırken, özellikle aşağıdaki genel prensipleri ve bu prensiplerle ilgili stratejileri dikkate almak da önemlidir:
- [ ] Independent Deployment (Bağımsız Dağıtım): Her mikroservis, diğerlerinden bağımsız olarak geliştirilmeli, test edilmeli ve dağıtılmalıdır. Bu, hizmetler arasında sıkı bir bağımlılık oluşturmayarak, daha hızlı ve daha esnek güncellemeleri ve ölçeklemeyi mümkün kılar.
- [ ] Service Isolation (Servis İzolasyonu): Her mikroservis kendi özel verilerini ve işlevselliğini yönetmelidir. Bu, her bir hizmetin tek bir işlevsellik parçasına odaklanmasını ve hizmetler arası etkileşimleri sınırlamasını sağlar.
- [ ] Autonomous Services (Özerk Servisler): Mikroservisler, ağdaki diğer hizmetlerden bağımsız olarak çalışabilmelidir. Bu, her bir hizmetin diğerlerinin durumuna veya mevcudiyetine dayanmamasını ve ağdaki bir hizmetin başarısız olmasının diğer hizmetleri olumsuz etkilememesini sağlar.
- [ ] Decentralized Governance (Merkeziyetsiz Yönetişim): Her mikroservis ekibi, teknoloji ve tasarım seçimlerinde özerk olmalıdır. Bu, daha hızlı ve daha esnek kararları ve daha dağıtılmış bir mimariyi teşvik eder.
- [ ] Failure Isolation (Hata İzolasyonu): Bir hizmetin başarısız olması durumunda, bu başarısızlığın diğer hizmetlere yayılmasını önlemek için izolasyon teknikleri kullanılmalıdır. Bu genellikle devre kesici kalıbı ve benzeri stratejiler kullanılarak gerçekleştirilir.
- [ ] Real-Time Monitoring (Gerçek Zamanlı İzleme): Sistemdeki tüm hizmetlerin durumu ve performansı, sorunları tespit etmek ve çözmek için gerçek zamanlı olarak izlenmelidir.
- [ ] Continuous Integration/Continuous Deployment (CI/CD): Mikroservisler, sürekli entegrasyon ve sürekli dağıtım pipeline'ları kullanılarak sık sık ve otomatik olarak güncellenmeli ve dağıtılmalıdır.
Her bir mikroservis tasarım kalıbı, özgül bir amaç için tasarlanmış olup, mikroservislerle çalışırken karşılaşılan çeşitli zorluklara çözüm sunar. Bu genel prensipler ve stratejiler, bir mikroservis mimarisinin etkinliğini ve dayanıklılığını artırmaya yardımcı
Örnek senaryolarla her birini uzunca anlat.
Mikroservisler, daha büyük bir uygulamanın farklı parçalarını bağımsız olarak çalıştırma ve ölçeklendirme yeteneği sunan bir yazılım mimarisi modelidir. Her bir mikroservis, belirli bir işlevi yerine getirir ve diğer mikroservislerle ağ üzerinden iletişim kurar. İşte bazı yaygın mikroservis desenleri ve bunların örnek senaryoları:
1. API Gateway Deseni: Bu desen, clientların mikroservislerle etkileşimini kolaylaştırır. API Gateway, bir uygulamanın dış dünyadan erişim noktasıdır ve genellikle yük dengelemesi, caching, veri dönüştürme, yetkilendirme ve kimlik doğrulama gibi özellikler sunar. Örnek: Bir e-ticaret uygulamasında kullanıcılar, ürün arama, sipariş verme, sipariş durumunu kontrol etme gibi farklı işlevlere ihtiyaç duyarlar. Bu işlevler farklı mikroservisler tarafından sağlanır. Ancak, tüm bu mikroservislerle direkt iletişim karmaşık ve zor olabilir. Burada API Gateway devreye girer. Kullanıcılar, tüm bu işlevlere API Gateway üzerinden ulaşabilirler. API Gateway, gelen istekleri ilgili mikroservise yönlendirir.
2. Client Side Discovery Deseni: Bu desen, bir mikroservisin ağı üzerindeki diğer servisleri bulmasını sağlar. Her bir client, servis örneklerinin konumlarını yöneten bir Service Registry'ye doğrudan sorgu yapar. Örnek: Bir video yayınlama platformunda, Video Yükleme ve Video İzleme gibi iki mikroservis olduğunu düşünelim. Bir kullanıcı bir video yüklediğinde, Video İzleme servisi bu videonun varlığını öğrenmek ister. Bunun için, Video İzleme servisi bir Service Registry'ye sorgu yapar ve Video Yükleme servisinin konumunu öğrenir.
3. Server Side Discovery Deseni: Bu desen de bir mikroservisin ağı üzerindeki diğer servisleri bulmasını sağlar. Fakat bu desende, servis konumları API Gateway veya benzeri bir bileşen tarafından yönetilir. Örnek: Yukarıdaki video yayınlama platformunda, Video Yükleme servisi bir video yükledikten sonra, Video İzleme servisi bu videoyu kullanıcıya sunmak için videoyu bulmalıdır. Ancak bu durumda, Video İzleme servisi doğrudan bir Service Registry'ye sorgu yapmaz. Bunun yerine, bir API Gateway'ye istek yapar ve bu Gateway, Video Yükleme servisinin konumunu bulup isteği yönlendirir.
4. Circuit Breaker Deseni: Bu desen, bir mikroservisin başka bir mikroservis ile iletişim kurarken hata durumlarını daha iyi yönetmesini sağlar. Bir hizmet arızalandığında veya aşırı yüklendiğinde, Circuit Breaker devreye girer ve başarısız olan hizmetin tekrar normal duruma gelmesini beklemeden başarısızlık yanıtı döner. Bu, tüm sistem üzerinde domino etkisi yaratabilecek hataların önlenmesine yardımcı olur. Örnek: Bir hava durumu tahmin uygulamasını düşünelim. Uygulama, bir dış API'den hava durumu bilgilerini alır ve kullanıcılara sunar. Ancak, bu dış API'nin yavaşlaması veya düşmesi durumunda, hava durumu uygulaması da etkilenecektir. Bu tür bir durumu yönetmek için Circuit Breaker deseni kullanılabilir. Circuit Breaker, belirli bir süre içinde çok fazla başarısız istek algıladığında "açık" duruma geçer ve daha fazla isteği engeller. Bu, hava durumu uygulamasının aşırı yüklenmesini ve potansiyel olarak çökmesini önler.
5. Saga Deseni: Bu desen, mikroservisler arasında bir dizi yerel işlem gerçekleştirilmesi gerektiğinde kullanılır. Saga deseni, her bir işlemin bir sonrakini tetiklediği bir dizi adımı tanımlar. Eğer herhangi bir adımda bir hata olursa, Saga deseni tüm işlemleri geri almak için bir dizi tazminat işlemini tetikler. Örnek: Bir e-ticaret uygulamasında bir sipariş işlemi düşünelim. Bu işlem genellikle stok kontrolü, ödeme işlemi ve nakliye bilgilerinin güncellenmesi gibi bir dizi adımı içerir. Eğer ödeme işlemi sırasında bir hata oluşursa, stoktaki ürün geri alınmalı ve kullanıcıya bir hata mesajı gösterilmelidir. Bu senaryoda Saga deseni, bu tür tazminat işlemlerini yönetebilir.
6. Event Sourcing Deseni: Örnek: Bir bankacılık uygulamasında bir kullanıcının hesap bakiyesi düşünelim. Bir kullanıcı bir dizi para yatırma ve çekme işlemi gerçekleştirir. Her işlem, belirli bir olay olarak kaydedilir ve bu olaylar tüm işlem geçmişi boyunca biriktirilir. Bu sayede, hesap bakiyesi her zaman olay geçmişinden hesaplanabilir. Ayrıca, herhangi bir anlaşmazlık durumunda, banka tüm işlem geçmişini inceleyerek ne olduğunu doğrulayabilir. Bu, bir hata veya anlaşmazlık durumunda durumun önceki bir noktaya geri alınmasına olanak sağlar.
7. Decomposition Deseni: Bu desen, büyük bir uygulamanın birden çok mikroservise nasıl ayrılacağını belirler. Her mikroservis genellikle bir iş işlevini temsil eder ve bağımsız olarak geliştirilip ölçeklendirilebilir. Örnek: Bir e-ticaret platformunu düşünelim. Bu platform, kullanıcılar için ürün arama, sipariş oluşturma, ödeme işleme ve sipariş takibi gibi çeşitli işlevlere sahip olabilir. Decomposition deseni, bu işlevlerin her birinin ayrı bir mikroservis tarafından yönetilmesini sağlar. Bu, her mikroservisin bağımsız olarak geliştirilip ölçeklendirilebileceği anlamına gelir. Örneğin, Black Friday gibi yoğun alışveriş dönemlerinde, sipariş oluşturma ve ödeme işleme mikroservisleri ölçeklendirilebilir.
8. Data Caching Deseni: Bu desen, sık kullanılan verilerin mikroservisler tarafından daha hızlı erişilebilir hale getirilmesi için kullanılır. Veri önbellekleme, bir mikroservis için gerekli olan verinin hızlı bir şekilde sağlanmasını sağlar ve böylece veriye erişim gecikmesini azaltır. Örnek: Bir haber uygulamasında, kullanıcılar genellikle en son haberleri görüntülerler. Bu haberler, veri tabanından sık sık sorgulandığında, bu veritabanına yönelik yükü artırabilir ve performansı düşürebilir. Veri önbellekleme deseni, bu sorunu çözebilir. En son haberler, daha hızlı erişim için önbelleğe alınabilir. Bu, veritabanına olan talebi azaltır ve uygulamanın performansını artırır.
9. Bulkhead Deseni: Bu desen, bir mikroservis hata durumunda diğerlerini etkilememesi için uygulanır. Bulkhead deseni, hizmetlerin birbirlerinden izole edilmesini ve her birinin belirli bir kaynak havuzunu kullanmasını sağlar. Örnek: Bir video akışı uygulamasında, video dönüştürme ve video akışı gibi farklı mikroservisler olabilir. Eğer video dönüştürme servisi yoğun bir iş yükü altında ve tüm kaynakları kullanırsa, bu durum video akışı servisinin performansını olumsuz etkileyebilir. Bulkhead deseni, her iki servisin ayrı kaynak havuzlarına sahip olmasını sağlar, böylece bir servis diğerinin performansını olumsız etkilemez.
10. Strangler Fig Deseni: Bu desen, büyük bir monolitik uygulamanın mikroservislerine dönüştürülmesi için kullanılır. Strangler Fig deseni, büyük uygulamanın belli bir kısmını ayrı bir mikroservis olarak oluşturmayı ve zamanla diğer kısımların da mikroservislere dönüştürülmesini sağlar. Örnek: Bir online alışveriş uygulaması düşünün. Başlangıçta, bu uygulama büyük bir monolitik yapıda olabilir, ancak zamanla bakımı ve ölçeklendirilmesi zorlaşır. Bu durumda, Strangler Fig deseni kullanılabilir. İlk olarak, uygulamanın belirli bir özelliği, örneğin kullanıcı yönetimi, ayrı bir mikroservis olarak oluşturulabilir. Sonrasında diğer özellikler de aynı şekilde ayrı mikroservisler haline getirilir.
11. Sidecar Deseni: Bu desen, mikroservislerin ölçeklendirilmesini ve yeniden kullanılmasını kolaylaştırır. Sidecar deseni, mikroservis ile birlikte çalışan ve ortak işlevselliği sağlayan başka bir servisi (sidecar) içerir. Sidecar, ana servisin işlevselliğini genişletebilir veya değiştirebilir. Örnek: Bir loglama hizmetini düşünün. Birçok farklı mikroservis, işlemleri sırasında log oluşturabilir. Ancak, her bir mikroservis için ayrı ayrı loglama kodları yazmak yerine, bir sidecar hizmeti kullanılabilir. Bu sidecar hizmeti, tüm mikroservislerin loglarını toplar ve merkezi bir konuma yazar. Bu, kodun yeniden kullanılabilirliğini artırır ve mikroservislerin daha temiz ve daha odaklanmış olmasını sağlar.
12. CQRS (Command Query Responsibility Segregation) Deseni: Bu desen, bir uygulamanın okuma ve yazma işlemlerinin ayrı ayrı ele alınmasını önerir. CQRS deseni, özellikle okuma ve yazma işlemlerinin farklı ölçeklendirme gereksinimleri olduğu durumlarda faydalıdır. Örnek: Sosyal medya uygulamasını düşünelim. Kullanıcıların gönderileri görüntüleme (okuma) ve yeni gönderiler oluşturma (yazma) işlemleri farklı ölçeklendirme gereksinimlerine sahip olabilir. Örneğin, bir milyon kullanıcı aynı gönderiyi görüntüleyebilirken, yalnızca birkaç yüz kullanıcı aynı anda yeni bir gönderi oluşturabilir. CQRS deseni, okuma ve yazma işlemlerini ayrı mikroservisler olarak ele almayı önerir, böylece her biri kendi ölçeklendirme gereksinimlerine göre ayarlanabilir.
13. Event-Driven Deseni: Bu desen, bir mikroservisin, bir olayın gerçekleştiğini bildirmek için olayları yayınlamasını ve diğer mikroservislerin bu olayları dinlemesini ve tepki vermesini sağlar. Örnek: Bir e-ticaret uygulamasında, bir siparişin oluşturulduğu zaman bu bir olay olabilir. Sipariş mikroservisi, bu olayı yayınlar ve diğer mikroservisler (stok mikroservisi, nakliye mikroservisi vb.) bu olayı dinler ve uygun şekilde tepki verirler. Bu yaklaşım, mikroservisler arasındaki bağımlılığı azaltır ve daha dinamik bir uygulama sağlar.
14. API Gateway Deseni: Bu desen, mikroservislerin nasıl erişileceğini ve tüketicilere nasıl sunulacağını belirler. API Gateway, tüm mikroservislerin tek bir giriş noktası oluşturur ve talepleri doğru mikroservislere yönlendirir. Örnek: Bir müzik streaming uygulamasını düşünelim. Bu uygulamada, farklı mikroservisler, kullanıcıları yönetmek, müzik parçalarını yönetmek, çalma listelerini yönetmek vb. için kullanılabilir. Kullanıcılar ve diğer uygulamalar, bu mikroservislerle doğrudan iletişim kurmak yerine API Gateway üzerinden iletişim kurarlar. API Gateway, gelen talepleri alır ve onları ilgili mikroservislere yönlendirir.
15. Backends for Frontends (BFF) Deseni: Bu desen, farklı kullanıcı arayüzleri (örneğin mobil, web, masaüstü) için farklı backendlerin oluşturulmasını önerir. Her arayüz için oluşturulan backend (BFF), o arayüzün belirli ihtiyaçlarını ve gereksinimlerini karşılar. Örnek: Bir haber uygulamasını düşünelim. Bu uygulamanın bir web sürümü ve bir mobil sürümü olabilir. Web sürümü, geniş bantlı bir bağlantıya sahip olduğunu ve büyük ekranlı bir cihazda görüntülendiğini varsayar. Ancak, mobil sürüm, sınırlı bir mobil veri bağlantısı ve küçük bir ekrana sahip bir cihazda çalıştığını varsayar. Bu iki arayüzün farklı ihtiyaçları ve gereksinimleri vardır, ve bu nedenle, her biri için ayrı bir BFF oluşturulabilir.
Mikroservislerle çalışırken bu ve diğer benzeri desenler, hizmetlerin birbirleriyle daha etkili bir şekilde nasıl etkileşim kuracağı ve birbirlerine nasıl bağlanacağı konusunda yol gösterir. Hangi desenlerin kullanılacağı, geliştirme ekibinin ihtiyaçlarına, uygulamanın gereksinimlerine ve hedeflerine bağlıdır.