<

Mikroservis mi Monolit mi? Orta Ölçekli Projeler İçin Dürüst Bir Değerlendirme

Geçen sonbaharda bir e-ticaret altyapısı devraldık: beş kişilik geliştirici ekibi, on beş ayrı mikroservis. Sepete ürün eklerken ortaya çıkan basit görünümlü bir hatayı bulmak üç günümüzü aldı; çünkü hata tek bir kod parçasında değil, dört servisin arasındaki mesaj trafiğinin kimsenin loglamadığı bir köşesinde saklanıyordu. Üçüncü günün akşamında müşteriyle karşılıklı oturduk ve açık konuştuk: sorun ekibinizde değil, mimarinizde.

Bu yazı, o akşamki konuşmanın uzun hâli. 2010'dan beri irili ufaklı beş yüzü aşkın projeye dokunmuş bir ekip olarak mikroservisin parlattığı işler de gördük, batırdığı işler de. Vardığımız yargı yıllar içinde netleşti: orta ölçekli projelerin büyük çoğunluğunda erken mikroservis kararı, verilebilecek en pahalı mimari hatadır.

Konferans sahnesiyle makine dairesi arasındaki mesafe

Mikroservis anlatılarının çoğu Netflix, Amazon, Uber gibi devlerin deneyiminden geliyor. O şirketlerde yüzlerce ekip, binlerce geliştirici ve her servise ayrılabilecek özel operasyon kadroları var. Mimari orada organizasyonun aynası: ekipler zaten bağımsız çalışıyor, servisler de o bağımsızlığı takip ediyor. Sahnedeki sunum bu bağlamı pek anlatmaz; dinleyicinin aklında kalan cümle "servisleri böl, ölçeklen" olur.

Beş kişilik bir ekip o cümleyi uyguladığında Netflix'in organizasyonunu değil, yalnızca dağıtık sistemin karmaşıklığını kopyalamış olur. Kaç kere gördük: herkes zaten her servise dokunuyor, yani mikroservisin vaat ettiği ekip bağımsızlığı ortada yok; buna karşılık ağ gecikmesi, sürüm uyumsuzluğu ve dağıtık hata ayıklama fazlasıyla var. Üstelik bu servisler birbirini senkron çağırıyorsa elinizdeki şeyin adı mikroservis bile değil; biz buna "dağıtık monolit" diyoruz — iki dünyanın da kötü taraflarını tek pakette sunar.

Bu kararların bir de az itiraf edilen psikolojik boyutu var. Mikroservis deneyimi özgeçmişte iyi duruyor, konferansta anlatması keyifli, yeni teknoloji denemesi heyecanlı. Anlıyorum; ben de mühendisim. Ama müşterinin bütçesiyle özgeçmiş süslemek bizim meslekte kabul edilebilir bir gerekçe değil. Bir mimari kararın tek meşru dayanağı, projenin bugünkü ve öngörülebilir ihtiyacıdır — mülakatlarda vereceğiniz cevaplar değil.

Servisler arası sözleşmelerin zamanla kaymasını da hesaba katın: A servisi alanın formatını değiştirdi, B servisi haberdar olmadı, hata ancak üretimde patladı. Monolitte derleyicinin bedavaya yakaladığı bu sınıf hatalar, dağıtık dünyada sözleşme testleri, şema kayıtları ve sürüm koordinasyonu ister — yani yine insan gücü, yine masraf.

Monolitte bedava olanın mikroservisteki fiyat etiketi

İşin en az konuşulan tarafı bu. Monolitte tek transaction ile çözdüğünüz "sipariş oluştur, stok düş, ödeme kaydet" akışı, mikroservis dünyasında saga desenine dönüşür: her adım için telafi mantığı yazarsınız, "kısmen başarılı" durumların her biri için ayrı senaryo kurarsınız, gece üçte yarıda kalmış siparişi elle düzeltecek yönetim aracını da unutmazsınız. Sıradan bir fonksiyon çağrısı, yerini timeout ayarlarına, retry politikalarına ve circuit breaker'lara bırakır. Ağ, fonksiyon çağrısının aksine ne hızlıdır ne de güvenilir; bu gerçeği kabullenmek, kodun her katmanına belirsizlik yönetimi eklemek demektir.

Operasyon tarafı da faturaya yazılır. Her servis ayrı deploy hattı, ayrı log akışı, ayrı izleme paneli ve ayrı alarm seti demek. Kubernetes'i hakkıyla işletmek başlı başına bir uzmanlık alanı; küçük ekipte bu yük ya bir kişinin omzuna biner (o kişi izne çıkana kadar her şey güllük gülistanlıktır) ya da hiç taşınmaz ve sistem karanlıkta koşar. Entegrasyon testleri de ayrı dert: on beş servisi lokalde ayağa kaldırıp uçtan uca senaryo koşturmak, çoğu ekipte "kimsenin yapmadığı şey" kategorisine düşer ve hatalar üretimde keşfedilir.

Kısacası: monolitte ücretsiz gelen ne varsa — transaction, tip güvenliği, tek log dosyası, tek deploy — mikroserviste tek tek satın alınır.

Bizim varsayılan cevabımız: modüler monolit

Peki alternatif, herkesin korktuğu spagetti monolit mi? Değil. Bizim projelerde varsayılan olarak kurduğumuz yapı modüler monolit: tek deploy edilebilir uygulama, içeride sınırları keskin çizilmiş modüller — üyelik, sipariş, ödeme, bildirim — ve modüller arası iletişimin yalnızca tanımlı arayüzlerden akması. Sipariş modülü, üyelik modülünün tablosuna doğrudan sorgu atamaz; ihtiyacı olan veriyi arayüzden ister. (Bu kuralı koymak kolay, korumak disiplin ister; kod incelemelerinde en çok kovaladığımız ihlal budur.)

Bu yapının güzelliği çift yönlü. Bugün monolitin bütün basitliğini yaşarsınız: tek pipeline, tek log, transaction'lar yerli yerinde, hata ayıklamak için tek stack trace. Yarın bir modül gerçekten ayrılmayı hak ederse, sınırlar baştan net çizildiği için onu bağımsız servise dönüştürmek haftalar değil günler meselesidir. İç içe geçmiş bir monoliti bölmekse aylarca süren açık kalp ameliyatına benzer; farkı yaratan şey, bugünden gösterilen modül disiplinidir.

Ölçek endişesine de değinelim, çünkü mikroservis kararlarının çoğu bu korkuyla veriliyor. Dikey büyütme, okuma replikaları ve akıllıca kurgulanmış önbellekleme ile tek uygulamanın taşıyabileceği yük, çoğu işletmenin hayalindeki trafiğin epey üzerindedir. Projelerimizin büyük kısmı bu desenle koşuyor ve ölçek duvarına çarpan yok. Yaşanmamış bir ölçek sorununu bugünden çözmeye çalışmak, olmayan hastalığa ameliyat olmaya benzer.

Pratikte modüler monoliti nasıl kurduğumuzu da bir paragrafla anlatayım. Her modülün veritabanında kendi şema alanı olur; başka modülün tablosuna JOIN atmak yasaktır. Modüller arası çağrılar tek bir arayüz katmanından geçer, böylece hangi modülün kime bağımlı olduğu her an haritalanabilir. Ortak çekirdek (auth, loglama, konfigürasyon) bilinçli olarak küçük tutulur; çekirdek şişerse modülerlik lafta kalır. Bu kuralları birkaç mimari testle CI hattına bağlıyoruz — ihlal, insan gözüne değil pipeline'a takılıyor.

Mikroservise geçmenin meşru sinyalleri

Yanlış anlaşılmasın: mikroservis kötü demiyoruz, yanlış zamanda pahalı diyoruz. Sahada üç sinyal ararız. Birincisi, ekiplerin birbirinin deploy'unu bekleyerek yavaşlaması; iki-üç otonom ekip aynı kod tabanında sürekli çakışıyorsa sınırları fiziksel olarak ayırmanın vakti gelmiş olabilir. İkincisi, radikal biçimde farklı ölçekleme ihtiyaçları; rapor motoru CPU canavarıyken uygulamanın kalanı tüy gibi hafifse, o motoru ayırıp bağımsız ölçeklemek gayet meşrudur. Üçüncüsü, organizasyonun kendisinin bölünmesi; şirket gerçekten ayrı ürün ekiplerine ayrıldıysa mimari eninde sonunda o çizgiyi takip eder.

Bu üçünden hiçbiri masada yoksa, mikroservis çözdüğünden çok daha fazlasını sırtınıza yükler.

Devraldığımız o e-ticaret projesinin sonunu merak edenler için: on beş servisi altı ayda dört modüllü bir monolitte topladık. Deploy süresi kırk beş dakikadan altı dakikaya indi, gece alarmları görünür biçimde azaldı, ekip yeniden özellik geliştirmeye vakit bulur oldu. Ciro düşmedi, aksine kampanya dönemini ilk kez alarmsız atlattılar.

Mimari tartışması moda tartışması değildir; ihtiyaç tartışmasıdır. Kendi projenizde bu ikilemi yaşıyorsanız bir kahve içimi konuşalım — bazen dışarıdan bakan bir çift göz, aylarca sürecek yanlış bir yatırımı daha başlamadan engelliyor.

📅 Yayınlanma:  ·  Yakup Zengin