30 Mikroservis Tasarım Kalıbı



Bu belge, mikroservis mimarisinde yaygın olarak kullanılan 30 tasarım kalıbını açıklamaktadır. Her kalıp için bir açıklama, gerçek dünya senaryosu ve mümkün olduğunda basit bir kod örneği verilmiştir.

1. API Gateway

Açıklama: Tüm istemci isteklerini tek bir giriş noktasından yöneten ve uygun mikroservislere ileten bir ara katman.

Senaryo: Bir e-ticaret uygulamasında, mobil ve web istemcilerinin farklı mikroservislere (ürün, sipariş, kullanıcı vb.) erişmesi gerekiyor.

Örnek (Node.js ile Express kullanarak):

javascript
const express = require('express'); const httpProxy = require('http-proxy'); const app = express(); const proxy = httpProxy.createProxyServer(); app.use('/products', (req, res) => { proxy.web(req, res, { target: 'http://product-service:3000' }); }); app.use('/orders', (req, res) => { proxy.web(req, res, { target: 'http://order-service:3001' }); }); app.listen(8080, () => console.log('API Gateway başlatıldı'));

2. Service Discovery

Açıklama: Mikroservislerin dinamik olarak birbirlerini bulmasını ve iletişim kurmasını sağlayan mekanizma.

Senaryo: Bir bulut ortamında çalışan mikroservislerin IP adreslerinin sürekli değiştiği bir sistem.

Örnek (Spring Cloud Netflix Eureka kullanarak):

java
@SpringBootApplication @EnableEurekaServer public class ServiceRegistryApplication { public static void main(String[] args) { SpringApplication.run(ServiceRegistryApplication.class, args); } }

3. Circuit Breaker

Açıklama: Hatalı bir servise yapılan çağrıları engelleyerek sistemin geri kalanını koruma mekanizması.

Senaryo: Ödeme servisi geçici olarak kullanılamadığında, siparişlerin tamamlanmasını engellemek.

Örnek (Netflix Hystrix kullanarak):

java
public class PaymentService { @HystrixCommand(fallbackMethod = "fallbackPayment") public boolean processPayment(Order order) { // Ödeme işlemi } public boolean fallbackPayment(Order order) { // Yedek ödeme işlemi veya hata mesajı } }

4. Load Balancer

Açıklama: Gelen istekleri mevcut servis örnekleri arasında dengeli bir şekilde dağıtan sistem.

Senaryo: Yoğun trafiğe sahip bir web uygulamasında, istekleri birden fazla uygulama sunucusuna dağıtmak.

Örnek (NGINX konfigürasyonu):

nginx
http { upstream backend { server backend1.example.com; server backend2.example.com; server backend3.example.com; } server { listen 80; location / { proxy_pass http://backend; } } }

5. Database per Service

Açıklama: Her mikroservisin kendi veritabanına sahip olması prensibi.

Senaryo: E-ticaret uygulamasında ürün kataloğu ve sipariş yönetimi için ayrı veritabanları kullanmak.

Örnek (Spring Boot uygulaması için konfigürasyon):

yaml
# product-service.yml spring: datasource: url: jdbc:mysql://product-db:3306/productdb username: product_user password: product_pass # order-service.yml spring: datasource: url: jdbc:postgresql://order-db:5432/orderdb username: order_user password: order_pass

6. Event Sourcing

Açıklama: Uygulama durumunu bir dizi olay olarak saklamak ve bu olayları yeniden oynatarak durumu yeniden oluşturmak.

Senaryo: Banka hesap hareketlerini her işlemi bir olay olarak kaydederek takip etmek.

Örnek (Basit bir Java uygulaması):

java
public class BankAccount { private List<Event> events = new ArrayList<>(); private double balance = 0; public void deposit(double amount) { events.add(new DepositEvent(amount)); apply(events.get(events.size() - 1)); } public void withdraw(double amount) { events.add(new WithdrawEvent(amount)); apply(events.get(events.size() - 1)); } private void apply(Event event) { if (event instanceof DepositEvent) { balance += ((DepositEvent) event).getAmount(); } else if (event instanceof WithdrawEvent) { balance -= ((WithdrawEvent) event).getAmount(); } } }

7. CQRS (Command Query Responsibility Segregation)

Açıklama: Veri okuma (query) ve yazma (command) işlemlerini ayrı modellerde gerçekleştirmek.

Senaryo: Yüksek okuma performansı gerektiren bir blog platformu.

Örnek (Basit bir Java uygulaması):

java
public class BlogService { private WriteRepository writeRepo; private ReadRepository readRepo; public void createPost(Post post) { writeRepo.save(post); // Event bus aracılığıyla okuma modelini güncelle } public Post getPost(String id) { return readRepo.findById(id); } }

8. Saga

Açıklama: Dağıtık işlemleri yönetmek için kullanılan bir dizi yerel işlem.

Senaryo: E-ticaret uygulamasında sipariş oluşturma, ödeme alma ve stok güncelleme işlemlerini koordine etmek.

Örnek (Pseudo-kod):

java
public class OrderSaga { public void process(Order order) { try { createOrder(order); processPayment(order); updateInventory(order); sendConfirmation(order); } catch (Exception e) { compensate(order); } } private void compensate(Order order) { // Hata durumunda geri alma işlemleri } }

9. Bulkhead

Açıklama: Uygulamayı izole bölümlere ayırarak, bir bölümdeki hatanın diğerlerini etkilemesini önleme.

Senaryo: Çoklu kiracılı (multi-tenant) bir SaaS uygulamasında, bir kiracının yoğun kullanımının diğerlerini etkilememesini sağlamak.

Örnek (Java ile ThreadPoolExecutor kullanarak):

java
public class BulkheadExample { private Map<String, ExecutorService> tenantExecutors = new HashMap<>(); public void processForTenant(String tenantId, Runnable task) { ExecutorService executor = tenantExecutors.computeIfAbsent(tenantId, k -> new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(100))); executor.submit(task); } }

10. Sidecar

Açıklama: Ana uygulamaya ek işlevsellik sağlayan, ancak ana uygulamadan bağımsız çalışan yardımcı servis.

Senaryo: Legacy bir uygulamaya modern bir API Gateway eklemek.

Örnek (Docker Compose ile sidecar konfigürasyonu):

yaml
version: '3' services: legacy-app: image: legacy-app:latest sidecar: image: nginx:latest volumes: - ./nginx.conf:/etc/nginx/nginx.conf ports: - "80:80"

11. Strangler Fig

Açıklama: Eski bir sistemi kademeli olarak yeni bir sistemle değiştirme stratejisi.

Senaryo: Monolitik bir e-ticaret uygulamasını mikroservislere geçirirken, önce ürün kataloğunu ayrı bir servise taşımak.

Örnek (Proxy sunucu konfigürasyonu):

nginx
server { listen 80; server_name example.com; location /products { proxy_pass http://new-product-service; } location / { proxy_pass http://legacy-monolith; } }

12. Backend for Frontend (BFF)

Açıklama: Belirli bir kullanıcı arayüzü veya istemci türü için özelleştirilmiş backend API'si.

Senaryo: Mobil uygulama için optimize edilmiş bir API oluşturmak.

Örnek (Node.js Express uygulaması):

javascript
const express = require('express'); const app = express(); app.get('/mobile/dashboard', async (req, res) => { const userData = await getUserData(req.user.id); const notifications = await getNotifications(req.user.id); res.json({ user: userData, notifications: notifications.slice(0, 5) // Sadece son 5 bildirim }); }); app.listen(3000, () => console.log('Mobile BFF started'));

13. Externalized Configuration

Açıklama: Uygulama yapılandırmasını koddan ayırarak, dışarıdan yönetilmesini sağlama.

Senaryo: Farklı ortamlar (geliştirme, test, üretim) için farklı veritabanı bağlantı bilgileri kullanmak.

Örnek (Spring Boot uygulaması için application.yml):

yaml
spring: profiles: active: ${SPRING_PROFILES_ACTIVE:dev} --- spring: config: activate: on-profile: dev datasource: url: jdbc:mysql://localhost:3306/devdb username: devuser password: devpass --- spring: config: activate: on-profile: prod datasource: url: jdbc:mysql://prod-db-server:3306/proddb username: ${DB_USERNAME} password: ${DB_PASSWORD}

14. Service Mesh

Açıklama: Mikroservisler arasındaki iletişimi yöneten, güvenliği sağlayan ve izleme yapan altyapı katmanı.

Senaryo: Büyük ölçekli bir mikroservis uygulamasında, servisler arası iletişimi yönetmek ve izlemek.

Örnek (Istio service mesh konfigürasyonu):

yaml
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews-route spec: hosts: - reviews.prod.svc.cluster.local http: - route: - destination: host: reviews.prod.svc.cluster.local subset: v1 weight: 75 - destination: host: reviews.prod.svc.cluster.local subset: v2 weight: 25

15. Event-Driven Architecture

Açıklama: Sistemdeki bileşenlerin birbirleriyle olaylar aracılığıyla iletişim kurduğu mimari.

Senaryo: Bir e-ticaret sisteminde, sipariş oluşturulduğunda stok yönetimi, faturalama ve kargo servislerinin bilgilendirilmesi.

Örnek (Java ile Apache Kafka kullanarak):

java
@KafkaListener(topics = "order-created") public void handleOrderCreated(OrderCreatedEvent event) { // Sipariş oluşturuldu olayını işle updateInventory(event.getOrderItems()); createInvoice(event.getOrderId()); initiateShipment(event.getOrderId()); }

16. Health Check API

Açıklama: Servisin durumunu kontrol etmek için bir API endpoint'i sağlama.

Senaryo: Bir load balancer'ın hangi servis örneklerinin sağlıklı olduğunu belirlemesi.

Örnek (Spring Boot ile):

java
@RestController public class HealthController { @GetMapping("/health") public ResponseEntity<String> healthCheck() { // Veritabanı bağlantısı, bağımlılıklar vb. kontrol edilebilir return ResponseEntity.ok("UP"); } }

17. Log Aggregation

Açıklama: Farklı mikroservislerden gelen logları merkezi bir sistemde toplama ve analiz etme.

Senaryo: Dağıtık bir sistemde hata ayıklama ve performans izleme.

Örnek (Docker Compose ile ELK stack kullanımı):

yaml
version: '3' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.10.0 logstash: image: docker.elastic.co/logstash/logstash:7.10.0 volumes: - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf kibana: image: docker.elastic.co/kibana/kibana:7.10.0 ports: - "5601:5601"

18. Distributed Tracing

Açıklama: Bir isteğin mikroservisler arasındaki yolculuğunu izleme ve analiz etme.

Senaryo: Karmaşık bir işlem akışında performans darboğazlarını tespit etmek.

Örnek (Java ile Spring Cloud Sleuth ve Zipkin kullanarak):

java
@SpringBootApplication @EnableZipkinServer public class ZipkinServerApplication { public static void main(String[] args) { SpringApplication.run(ZipkinServerApplication.class, args); } } // Mikroservis uygulamasında @Autowired private Tracer tracer; public void processOrder(Order order) { Span span = tracer.nextSpan().name("process-order").start(); try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) { // İşlem adımları } finally { span.finish(); } }

19. Blue-Green Deployment

Açıklama: Yeni sürümü (blue) canlı ortama almadan önce mevcut sürümle (green) yan yana çalıştırma stratejisi.

Senaryo: Bir e-ticaret sitesinin yeni sürümünü risk almadan yayına almak.

Örnek (Kubernetes ile):

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-app-ingress annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: myapp.example.com http: paths: - path: / pathType: Prefix backend: service: name: my-app-green port: number: 80 --- # Yeni sürüm hazır olduğunda apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-app-ingress annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: myapp.example.com http: paths: - path: / pathType: Prefix backend: service: name: my-app-blue port: number: 80

20. Feature Toggle

Açıklama: Uygulama özelliklerini dinamik olarak açıp kapatma mekanizması.

Senaryo: Yeni bir özelliği sadece beta kullanıcılarına açmak.

Örnek (Java ile Togglz kütüphanesi kullanarak):

java
public enum Features implements Feature { @Label("New Payment Gateway") NEW_PAYMENT_GATEWAY; public boolean isActive() { return FeatureContext.getFeatureManager().isActive(this); } } @RestController public class PaymentController { @PostMapping("/process-payment") public ResponseEntity<?> processPayment(@RequestBody PaymentRequest request) { if (Features.NEW_PAYMENT_GATEWAY.isActive()) { return processWithNewGateway(request); } else { return processWithOldGateway(request); } } }

21. Consumer-Driven Contract Testing

Açıklama: Servis tüketicilerinin beklentilerine göre servis sağlayıcıların test edilmesi.

Senaryo: Bir ödeme servisinin, e-ticaret uygulamasının beklentilerine uygun çalıştığından emin olmak.

Örnek (Java ile Spring Cloud Contract kullanarak):

groovy
// src/test/resources/contracts/shouldProcessPayment.groovy Contract.make { request { method 'POST' url '/payments' body([ amount: 100.00, currency: 'USD' ]) headers { contentType('application/json') } } response { status 200 body([ id: anyUuid(), status: 'PROCESSED' ]) headers { contentType('application/json') } } }

22. API Versioning

Açıklama: API'lerin farklı sürümlerini yönetme ve geriye dönük uyumluluğu koruma stratejisi.

Senaryo: Mevcut müşterileri etkilemeden bir API'yi güncellemek.

Örnek (Spring Boot ile URL tabanlı versiyonlama):

java
@RestController @RequestMapping("/api/v1/users") public class UserControllerV1 { @GetMapping("/{id}") public UserV1 getUserV1(@PathVariable Long id) { // V1 kullanıcı verisi döndür } } @RestController @RequestMapping("/api/v2/users") public class UserControllerV2 { @GetMapping("/{id}") public UserV2 getUserV2(@PathVariable Long id) { // V2 kullanıcı verisi döndür } }

23. Backends for Frontends (BFF)

Açıklama: Her farklı istemci türü için özelleştirilmiş backend API'leri oluşturma.

Senaryo: Mobil uygulama, web uygulaması ve IoT cihazları için farklı API'ler sunmak.

Örnek (Node.js Express ile):

javascript
// Mobile BFF app.get('/mobile/dashboard', (req, res) => { // Mobil için optimize edilmiş dashboard verisi }); // Web BFF app.get('/web/dashboard', (req, res) => { // Web için tam kapsamlı dashboard verisi }); // IoT BFF app.get('/iot/status', (req, res) => { // IoT cihazları için minimal durum verisi });

24. Throttling

Açıklama: Bir servise yapılan istekleri sınırlayarak aşırı yüklenmeyi önleme.

Senaryo: Ücretsiz API kullanıcılarının dakikada yapabileceği istek sayısını sınırlamak.

Örnek (Express.js ile rate-limiter-flexible kullanarak):

javascript
const express = require('express'); const { RateLimiterMemory } = require('rate-limiter-flexible'); const app = express(); const rateLimiter = new RateLimiterMemory({ points: 10, // 10 istek duration: 60 // 60 saniye içinde }); app.use((req, res, next) => { rateLimiter.consume(req.ip) .then(() => { next(); }) .catch(() => { res.status(429).send('Too Many Requests'); }); });

25. CQRS (Command Query Responsibility Segregation)

Açıklama: Veri okuma (query) ve yazma (command) işlemlerini ayrı modellerde gerçekleştirme.

Senaryo: Yüksek okuma performansı gerektiren bir blog platformu.

Örnek (C# ile):

csharp
public class BlogService { private readonly ICommandRepository _commandRepo; private readonly IQueryRepository _queryRepo; public BlogService(ICommandRepository commandRepo, IQueryRepository queryRepo) { _commandRepo = commandRepo; _queryRepo = queryRepo; } public async Task CreatePost(CreatePostCommand command) { await _commandRepo.CreatePost(command); // Event bus aracılığıyla okuma modelini güncelle } public async Task<PostDto> GetPost(int id) { return await _queryRepo.GetPostById(id); } }

26. Event Sourcing

Açıklama: Uygulama durumunu bir dizi olay olarak saklama ve bu olayları yeniden oynatarak durumu yeniden oluşturma.

Senaryo: Banka hesap hareketlerini her işlemi bir olay olarak kaydederek takip etmek.

Örnek (C# ile):

csharp
public class BankAccount { private List<Event> _events = new List<Event>(); public decimal Balance { get; private set; } public void Deposit(decimal amount) { var @event = new DepositEvent(amount); Apply(@event); _events.Add(@event); } public void Withdraw(decimal amount) { var @event = new WithdrawEvent(amount); Apply(@event); _events.Add(@event); } private void Apply(Event @event) { switch (@event) { case DepositEvent depositEvent: Balance += depositEvent.Amount; break; case WithdrawEvent withdrawEvent: Balance -= withdrawEvent.Amount; break; } } public void Replay(IEnumerable<Event> events) { foreach (var @event in events) { Apply(@event); } } }

27. Saga Pattern

Açıklama: Dağıtık işlemleri yönetmek için kullanılan uzun ömürlü işlem modeli.

Senaryo: E-ticaret uygulamasında sipariş oluşturma, ödeme alma ve stok güncelleme işlemlerini koordine etmek.

Örnek (Pseudo-kod):

java
public class OrderSaga { public void process(Order order) { try { createOrder(order); processPayment(order); updateInventory(order); sendConfirmation(order); } catch (Exception e) { compensate(order); } } private void compensate(Order order) { // Hata durumunda geri alma işlemleri if (order.isCreated()) cancelOrder(order); if (order.isPaid()) refundPayment(order); if (order.isInventoryUpdated()) restoreInventory(order); } }

28. Sidecar Pattern

Açıklama: Ana uygulamaya ek işlevsellik sağlayan, ancak ana uygulamadan bağımsız çalışan yardımcı servis.

Senaryo: Legacy bir uygulamaya modern bir API Gateway eklemek.

Örnek (Docker Compose ile):

yaml
version: '3' services: legacy-app: image: legacy-app:latest ports: - "8080:8080" sidecar: image: nginx:latest volumes: - ./nginx.conf:/etc/nginx/nginx.conf ports: - "80:80" depends_on: - legacy-app

29. Strangler Fig Pattern

Açıklama: Eski bir sistemi kademeli olarak yeni bir sistemle değiştirme stratejisi.

Senaryo: Monolitik bir e-ticaret uygulamasını mikroservislere geçirirken, önce ürün kataloğunu ayrı bir servise taşımak.

Örnek (Nginx konfigürasyonu):

nginx
http { upstream legacy_app { server legacy_app:8080; } upstream product_service { server product_service:8081; } server { listen 80; server_name example.com; location /products { proxy_pass http://product_service; } location / { proxy_pass http://legacy_app; } } }

30. Bulkhead Pattern

Açıklama: Uygulamayı izole bölümlere ayırarak, bir bölümdeki hatanın diğerlerini etkilemesini önleme.

Senaryo: Çoklu kiracılı (multi-tenant) bir SaaS uygulamasında, bir kiracının yoğun kullanımının diğerlerini etkilememesini sağlamak.

Örnek (Java ile ThreadPoolExecutor kullanarak):

java
public class BulkheadExample { private Map<String, ExecutorService> tenantExecutors = new HashMap<>(); public void processForTenant(String tenantId, Runnable task) { ExecutorService executor = tenantExecutors.computeIfAbsent(tenantId, k -> new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(100))); executor.submit(task); } public void shutdownTenant(String tenantId) { ExecutorService executor = tenantExecutors.remove(tenantId); if (executor != null) { executor.shutdown(); } } }

Bu 30 mikroservis tasarım kalıbı, modern dağıtık sistemlerin karşılaştığı çeşitli zorlukları ele almaktadır. Her kalıp, belirli bir problemi çözmek için tasarlanmıştır ve uygun şekilde uygulandığında, mikroservis mimarisinin esneklik, ölçeklenebilirlik ve dayanıklılık gibi temel faydalarını artırabilir.

Junior geliştiriciler için önemli olan, bu kalıpları anlamak, hangi durumlarda kullanılacaklarını bilmek ve projenin gereksinimlerine göre uygun kalıpları seçebilmektir. Ayrıca, bu kalıpların her birinin kendi karmaşıklıkları ve trade-off'ları olduğunu unutmamak önemlidir. Bu nedenle, bir kalıbı uygulamadan önce, o kalıbın getireceği faydaları ve olası dezavantajları dikkatle değerlendirmek gerekir.

Please Select Embedded Mode To Show The Comment System.*

Daha yeni Daha eski

نموذج الاتصال