Herkese merhaba. Bu yazımda biraz daha teorik bir konu ile ilgili bildiklerimi sizlere aktarmaya çalışacağım. Son dönemlerde özellikle büyük uygulamalar içerisinde sıkça duyduğumuz Mikroservis mimarisi nedir, karakteristik özellikleri nelerdir bunları inceleyeceğiz. Bu yazımı oluştururken özellikle Martin Fowler‘ın yazısından faydalandım, sizin de incelemenizi tavsiye ederim. Mikroservis mimariye giriş yapmadan önce karşıtı olan monolitik uygulama nedir onu bir inceleyelim.

Monolitik Uygulama Nedir?

Monolitik uygulamalar, genellikle 3 ana kısma sahip olan ve bu kısımları tek bir uygulama içerisinde birleştiren uygulamalardır. Bahsettiğim 3 ana kısım ise client-side, server-side ve database parçalarından oluşur. Burada HTTP isteklerini yöneten kısım server-side tarafıdır ve uygulamadaki iş kurallarının yönetildiği katmandır. Eğer güncellenmesi, eklenmesi ya da gösterilmesi gereken bir data varsa server-side bu isteği veritabanına iletir. Veritabanı tarafında data ile ilgili işlem gerçekleşir. Server-side üzerindeki işleri bitirdikten sonra uygun HTML sayfasını seçerek client-side’a yönlendirir. Kısaca uygulamanın bütün mantıksal işlemlerinin yürütüldüğü yer server-side tarafıdır.

Cloud teknolojisi gelişmeye ve popülerleşmeye başladığından beri monolitik uygulamalar gözümüze biraz daha hantal görünmeye başladılar. Çünkü monolitik uygulamalarda değişiklik döngüleri iç içe geçmiş durumdadır. Uygulamanın küçük bir kısımı etkileyecek bir değişiklik yapmış olsanız bile bütün uygulamayı rebuilt ve redeploy yapmanız gerekiyor. Bunun sonucu olarak da mikroservis mimarisini daha çok duymaya başladık.

Mikroservis Mimarisi Nedir?

Mikroservis mimarisi aslında yeni bir tasarım değil, köklerini Unix sisteminin tasarım ilkelerinden alıyor. Tek başına tek sorumluluğu olan ve sadece o sorumluluğa ait işleri yürüten modüler servisler bütünüdür. Servisler iş yetenekleri kapsamında geliştirilir ve birbirlerinden bağımsız olarak deploy edilebilirler. Servisler farklı programlama dilleri kullanılarak geliştirilebilirler. Bu mimaride bir servis içerisinde değişiklik yaptığımızda sadece o servisin build ve deploy edilmesi yeterlidir. Monolitik uygulamalarda yatay ölçeklendirme yapılırken, mikroservis mimaride çok kullanılan servislere göre ölçeklendirme yapılmaktadır.

Monolitik ve Mikroservis Ölçeklendirmesi

Monolitik uygulamada bütün süreçler eş sayıda ölçeklendirilmektedir. Mikroservis uygulamalarında ise süreçleri kullanım sıklığına göre ölçeklendirebiliriz.

Mikroservis mimarisinde belli başlı tasarım ilkeleri bulunmamaktadır. Ancak, ortaklaşmış karakteristik özelliklerden bahsedebiliriz. Bu özelliklerin tamamının bir mikroservis uygulamasında olmasını beklemeyiz ancak çoğunun uygulanması gerekir.

1. Servisleri Bileşenlerine Göre Ayırmak

Bağımsız olarak değiştirilebilen veya upgrade edilebilen yazılım birimine bileşen -ya da component- denir. Mikroservis mimaride bileşenleştirme işlemi yazılımın servislere bölünmesiyle sağlanır. Servisin bileşenleştirilmesi monolitik uygulamalarda kütüphane oluşturularak yapılmaktadır. Bu yöntemde kütüphaneler programa bağlı olduğu için, kütüphanede güncelleme yapıldığında uygulamanın da güncel kütüphane versiyonu ile tekrar build edilmesi gerekir. Microservis mimarisinde ise bileşenlere ayrılan servis HTTP istekleri ile erişilebilir hale gelir. Bu sayede servis birden çok uygulama içerisinden çağırılır. Bazı durumlarda bu şekilde remote çağırımlar bellek içi çağırımlardan daha maliyetli olabilir ya da bir data tipinin birkaç servis içerisinde kullanılması gerekebilir. Uygulamanızın içerisinde bu durumlara neden olan servisleri kütüphane oluştururak kullanabilirsiniz.

2. Ekiplere Göre İş Bölünümü

Monolitik bir uygulamada ekipler genellikle ilgilendikleri teknolojilere odaklanırlar. (UI, Backend, DB Admins gibi…) Çalışan ekiplerin bütün uygulamayı ya da en azından kendi ekibinin sorumlu olduğu modülü bilmesi gerekir. Takımlar bu şekilde izole gruplara ayrıldığında uygulama üzerinde yapılan küçük bir değişiklik bile çok fazla vakit kaybı yaratmaktadır.

Conway's Yasası

Conway’s yasasına göre izole ekipler izole bir uygulama mimarisine neden olur.

Mikroservis yaklaşımında ekipler servislerin iş yetenekleri kapsamında bölünmesi hedeflenmektedir. Sonuç olarak ekip geliştirme yapmak için gereken bütün üyeleri bir arada barındırır. Büyük monolitik uygulamalarda da ekipler iş yeteneklerine göre bölünebilmektedir. Çünkü, monolit çok fazla sayıda modül içeriyorsa ekip üyelerinin kısa zamanda bütün yapıyı öğrenmesi zor olabilir.

Fonksiyonel Ekip Organizasyonu

Çapraz fonksiyonel ekipler yetenekleri etrafında organize olur.

3. Proje Ürün Değildir

Birçok uygulama geliştirme süreci, ilk önce küçük bir parçanın teslim edilmesi zamanla da tamamlanmasını hedefler. Proje tamamlandığında genellikle proje bakım ekibine teslim edilir ve geliştiren ekip dağıtılır. Mikroservis mimarisinde genellikle bu modelden kaçınılır. Bunun yerine ekibin projenin kullanım ömrü boyunca geliştirme yapması hedeflenmektedir. Bu sayede geliştiriciler yazılımın destek yükünün bir kısmını üzerlerine alırlar. Kullanıcı ile birebir temas da arttığı için daha sağlıklı bir geliştirme süreci sağlanır. Mikroservis mimaride yazılıma tamamlanması gereken bir dizi işlemler olarak bakmak yerine kullanıcıların iş geliştirmede nasıl yardımcı olabileceğini soran bir bakış açısı vardır.

4. Merkezi Olmayan Yönetim

Monolit uygulamalar çoğunlukla tek bir teknoloji platformunda standartlaşmaya eğilimlidir. Bu yaklaşım pek çok açıdan kısıtlayıcı olabilmektedir. Bu nedenle mikroservis yaklaşımında iş için doğru teknoloji seçimi tercih edilmektedir. Mesela rapor sayfasında Node.js kullanırken daha büyük bir yapı için C# tercih edilebilir.

Ekipler de birbirleriyle standart yaklaşımlar yerine farklı bir yaklaşım sergilemektedirler. Bir yerlere yazılmış tanımlı standart kurallar yerine geliştiriciler benzer sorunlar yaşadıklarında diğer ekiplerle paylaşabilecekleri toolar geliştirirler. Bu toollar genellikle açık kaynaklı ve tüm ekiplerin görüntüleyebileceği bir platformda toplanır.

5. Merkezi Olmayan Veri Yönetimi

Veri yönetiminde yaşanan en yaygın sorun gerçek dünya modellerinin servisler arasında farklılık göstermesidir. Örneğin, bir alışveriş sitesinin satış sayfasında kullanılan verilerle destek sayfasında kullanılan veriler birbirinden farklı olacaktır. Satış sayfasında gösterilen ürünler destek sayfasında gösterilmeyebilir. Domain Driven Design kavramını uygulayarak bu sorunu aşabiliriz. Domain Driven Design kompleks bir yapıyı birbirine bağımlı contextler olarak böler ve aralarında ilişki kurar. Bu yaklaşım hem monolitik hem de mikroservis uygulamaları için uygundur.

Mikroservis mimaride data saklama yöntemi olarak monolitik uygulamanın aksine birden fazla veritabanı kullanımı olabilmektedir. Mikroservis yaklaşımı her servisin kendi veritabanını yönetmesini veya aynı veritabanının farklı instancelarını ya da tamamen farklı veritabanı sistemlerini yönetmesini destekler. Bu yönteme Polygot Yaklaşımı denir. Bu yaklaşım monolitik uygulamalarda da kullanılabilir; ancak mikroserviste daha yaygındır.

Merkezi Olmayan Veri Yönetimi

Mikroservislerde merkezi yönetim olmaması güncellemelerin yönetilmesi üzerinde bir takım zorluklara neden olabilir. Çoklu kaynaklarda güncelleme yaparken veri tutarlılığını garanti altına almak için transactions kullanılmaktadır. Bu yaklaşım monolitik uygulamalarda da sıklıkla kullanılmaktadır. Transaction yapısını bu şekilde kullanmak veri tutarlılığını garanti altına alır; ancak birden çok serviste sorun oluşturan zamansal eşlemeyi dayatır. Dağıtılmış transactionların kullanımı da zordur. Sonuç olarak mikroservis mimarileri, sorunların telafi edici işlemlerle ele alındığını açıkça kabul ederek, servisler arasında transactionless koordinasyonu vurgular.

Tutarsızlıkları bu şekilde yönetmeyi seçmek, birçok geliştirme ekibi için yeni bir zorluktur; ancak genellikle iş kurallarıyla eşleşir. Çoğu zaman uygulamalar, talebe hızlı bir şekilde yanıt vermek için bir dereceye kadar tutarsızlıkla başa çıkarken, hatalarla başa çıkmak için bir tür tersine çevirme süreci yaşarlar. Hataları düzeltmenin maliyeti, daha fazla tutarlılık altında kaybedilen iş maliyetinden daha az olduğu sürece, ödün vermeye değer.

6. Altyapı Otomasyonu

Altyapı otomasyon teknikleri özellikle bulut sistemlerin gelişmesiyle beraber çok gelişti. Mikroservislerle oluşturulan ürün ve sistemlerin birçoğu Continuous Delivery ve Continuous Integration (CI/CD) süreçlerini kullanıyor.

CI/CD Süreçleri

Yazılımımız çalışırken olabildiğince kendinden emin olmasını isteriz bu yüzden bir sürü automated testler çalıştırırız. Yeni ortamlara çıkartmak için automate deployment pipelinelar kullanırız. Monolitik uygulamalarda da bu testleri ve ortam süreçlerini başarılı bir şekilde yürütebiliriz.

7. Başarısız Tasarımlar Oluşturmak

Mikroservis mimaride en başta servislerin componentlarına (bileşenlerine) göre tasarlanması başarısız olma ihtimalini azaltır. Ancak herhangi bir servisin unavailability (erişilemezlik) durumunda kullanıcının mümkün olduğunca kötü etkilenmemesi gerekir. Bu nedenle mikroservis ekipleri sürekli olarak servislerin failurelarının kullanıcı deneyimini nasıl etkilediğini gözlemler ve önlem alırlar. Örneğin Netflix’in Simian Army ekibi uygulamanın hem dayanıklılığını arttırmak hem de izlemeyi test etmek için gün boyunca servislerde ve hatta veri merkezlerinde arızalara neden oluyorlar.

Servisler herhangi bir zamanda fail olabileceğinden failurelerı hızlıca tespit etmek ve mümkünse otomatik bir şekilde onarılmasını sağlamak çok önemlidir. Bu nedenle real-time monitoring tooları kullanılır. Aynı zamanda business geliştirmeleri için semantic monitoring tooları da kullanılmaktadır.

8. Evrimsel Tasarım

Ne zaman bir yazılımı componentlara ayırmaya çalışırsanız, parçaları nasıl böleceğiniz sorunuyla yüzleşirsiniz. Uygulamamızı parçalara ayırmaya karar verdiğimiz ilkeler nelerdir? Bir componentın temel özelliği bağımsız bir şekilde değişebilme ve upgrade edilebilmesidir. Bu da bir componentin collabratorlarını etkilemeden yeniden yazmayı hayal edebileceğimiz noktaları aradığımız anlamına gelir.

The Guardian websitesi monolitik mimaride tasarlanmış ve oluşturulmuş ancak mikroservis yönünde değişim gösteren sitelere güzel bir örnek. Sitenin core kısmı hala bir monolitik ancak yeni özellikleri monolitik API’I kullanarak mikroservis olarak geliştiriliyor. Bu yaklaşım doğası gereği geçici olan özellikler için çok kullanışlı olabilir. Örneğin özelleştirilmiş bir spor etkinliği sayfası. Websitesinin bir bölümü hızlı bir araya getirilebilir geliştirme dilleri kullanılarak oluşturulabilir ve etkinlik sona erdiğinde kaldırılır.

Mikroservis mimarinin mantığını ve ilkelerini elimden geldiğince anlatmaya çalıştım. Bir sonraki yazıya kadar kendinize çok iyi bakın! 😊