Mikroservis mimarisi, tek parça (monolit) bir uygulamayı bağımsız geliştirilip dağıtılabilen küçük servislere ayırır. Doğru kurulduğunda ekipler birbirini beklemeden çalışır, sistem parça parça ölçeklenir ve bir hata tüm uygulamayı düşürmez. Yanlış kurulduğunda ise dağıtık bir monolit elde edersiniz: tek parçanın bütün zorlukları, ağın bütün sorunlarıyla birlikte. Bu yazı farkı yaratan uygulamaları sıralıyor.
Neden mikroservis
Monolit büyüdükçe tek kod tabanı geliştirmede, testte ve dağıtımda darboğaza döner: küçük bir değişiklik bütün uygulamanın yeniden test edilip yayınlanmasını ister. Mikroservisler, ekiplerin kendi servislerini diğerlerini etkilemeden geliştirip yayına almasını sağlar. Bedeli dağıtık sistemin karmaşıklığıdır; bu yüzden aşağıdaki uygulamalar isteğe bağlı değildir.
1. Servisleri iş yeteneklerine göre ayırın
Servis sınırını teknik katmanlar değil, iş alanları belirler.
Yanlış: teknik katmana göre
- Veritabanı servisi
- Önbellek servisi
- API servisi
Doğru: iş yeteneğine göre
- Kullanıcı yönetimi
- Sipariş işleme
- Ödeme
Her servis kendi alan mantığının ve verisinin sahibidir. Bu, alan güdümlü tasarımın (Domain-Driven Design) sınırlı bağlam (bounded context) kavramına karşılık gelir. İyi bir sınırın işareti şudur: bir iş kuralı değiştiğinde yalnız bir servis değişir.
2. API sözleşmelerini açık ve sürümlü tutun
Servisler REST, gRPC ya da olaylar üzerinden açıkça tanımlanmış sözleşmelerle konuşur. Sözleşme kodla birlikte bir yerde yazılı durur (OpenAPI, Protocol Buffers) ve baştan sürümlenir:
// orders/v1/order.proto
message Order {
string id = 1;
string customer_id = 2;
OrderStatus status = 3;
int64 total_minor = 4; // kuruş cinsinden
string currency = 5;
}
Alan eklemek geriye uyumludur; alan silmek ya da anlamını değiştirmek yeni sürüm demektir. Böylece bir servisin güncellenmesi diğerlerini kırmaz.
3. Her servis kendi verisinin sahibi olsun
Servisler arasında ortak veritabanı, görünmeyen bağımlılıkların en yaygın kaynağıdır.
İlkeler:
- Bir servis başka bir servisin veritabanına doğrudan erişmez
- Veri paylaşımı API ya da olay üzerinden olur
- Her servis kendi ihtiyacına uyan veritabanını seçebilir
- Servisler arası tutarlılık nihai tutarlılık ve saga kalıbıyla sağlanır
Bir servisin başka bir servisin verisine sık ihtiyacı varsa, her seferinde senkron çağrı yapmak yerine o servisin yayınladığı olaylardan kendi yerel kopyasını (projeksiyon) tutması çoğu zaman daha dayanıklıdır: karşı servis kapalıyken de çalışmaya devam eder.
4. Servis keşfi
Servisler dinamik olarak açılıp kapandığı için birbirini sabit adreslerle bulamaz. Kubernetes bunu yerleşik olarak çözer (Service ve DNS); Kubernetes dışında Consul ya da etcd gibi araçlar kullanılır. Kubernetes kullanıyorsanız ek bir keşif aracına çoğu zaman ihtiyacınız olmaz.
5. Senkron ve asenkron iletişimi ayırın
Her servis çağrısı senkron olmak zorunda değildir.
Senkron (istek-cevap): cevabın o anda gerektiği durumlar; örneğin ekranda gösterilecek bir sorgu.
Asenkron (olay güdümlü): cevap beklenmeyen işler; bildirim göndermek, analitiği güncellemek, başka servislerin durumunu tetiklemek.
from confluent_kafka import Producer
import json
producer = Producer({"bootstrap.servers": "kafka:9092", "enable.idempotence": True})
event = {
"event_type": "order_created",
"order_id": "12345",
"occurred_at": "2026-01-15T10:30:00Z",
}
# Aynı siparişin olayları aynı anahtarla gider: bölüm içinde sıra korunur
producer.produce("orders", key="12345", value=json.dumps(event))
producer.flush()
Olayı veritabanı kaydıyla aynı transaction’da bir outbox tablosuna yazmak, kayıt ile olayın birbirinden kopmasını engeller.
6. Gözlemlenebilirliği baştan kurun
Çok parçalı bir sistemde merkezi kayıt, metrik ve dağıtık izleme olmazsa olmazdır.
- Kayıt: Loki, ELK, bulut sağlayıcısının kayıt servisi
- Metrik: Prometheus ve Grafana
- İzleme: OpenTelemetry ile Jaeger ya da Tempo
Her isteğe bir iz kimliği verin ve bunu servisler arasında taşıyın; kayıtları yapılandırılmış (JSON) yazın:
{
"timestamp": "2026-01-15T10:30:00Z",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"service": "order-service",
"level": "INFO",
"message": "Sipariş işleme başladı",
"order_id": "12345"
}
7. Konteyner orkestrasyonu
Konteynerler ve Kubernetes dağıtımı, ölçeklemeyi ve işletmeyi standartlaştırır:
- Yüke göre otomatik ölçekleme
- Çöken konteynerin kendiliğinden yeniden başlaması
- Kesintisiz kademeli güncelleme
- Kaynak sınırları ve servis ağı entegrasyonu
8. Dayanıklılık kalıpları
Dağıtık sistemde ağ her zaman bir gün hata verir. Bunun için:
- Zaman aşımı: her servis çağrısında; zaman aşımı olmayan çağrı, kaynakları sonsuza dek tutar
- Yeniden deneme: üstel bekleme ve rastgele sapmayla (jitter), yalnız idempotent işlemlerde
- Devre kesici (circuit breaker): sürekli hata veren servise istek göndermeyi bir süre keser
- Bölmeler (bulkhead): bir bağımlılığın sorunu tüm kaynakları tüketmesin diye havuzları ayırır
.NET’te Polly, Java’da Resilience4j bu kalıpları hazır sunar; servis ağı da bir kısmını altyapı düzeyinde uygular.
9. Veri tutarlılığını planlayın
Servisler arası dağıtık transaction pahalıdır ve kırılgandır. Bunun yerine:
Saga: çok adımlı bir iş akışı, her adımın başarısızlıkta geri alınmasını sağlayan telafi adımlarıyla birlikte yürütülür. Koreografi (olaylarla) ya da orkestrasyon (merkezi bir koordinatörle) kurulabilir.
Olay kaynaklama: durum değişiklikleri değiştirilemez olaylar olarak saklanır; tam bir denetim izi verir ama her servis için gerekli değildir.
10. DevOps kültürü
Mikroservisler işletme olgunluğu ister:
- Altyapının kod olarak yönetilmesi (Terraform, OpenTofu)
- Sürekli entegrasyon ve dağıtım
- Her düzeyde otomatik test, özellikle sözleşme testleri
- Kademeli yayın için özellik bayrakları
- Servisin geliştirmeden üretime kadar sahibi olan ekipler
Dikkat edilecekler
Conway yasası: sistemin yapısı, onu kuran kurumun iletişim yapısını yansıtır. Servis sınırlarını ekip sınırlarıyla birlikte düşünün.
Erken bölmeyin: alanınız henüz netleşmediyse iyi modüllere ayrılmış bir monolitle başlayın. Sınırlar oturduktan sonra servisleri ayırmak, yanlış çizilmiş servis sınırlarını birleştirmekten çok daha kolaydır.
Güvenlik: servisler arası kimlik doğrulama (mTLS), istekleri doğrulayan bir API geçidi ve sır yönetimi. Kimlik bilgileri asla koda yazılmaz.
Sonuç
Mikroservisler, düşünülerek kurulduğunda ölçeklenebilir ve bakımı kolay sistemler verir. Başarı net servis sınırlarına, sağlam iletişim kalıplarına, baştan kurulmuş gözlemlenebilirliğe ve işletme olgunluğuna bağlıdır. İş alanından başlayın, temeli sağlam kurun, gerçek deneyime göre geliştirin.
Mikroservis mimarinizi birlikte değerlendirmek isterseniz bize yazın.
ByteGurus
Yazar