İçeriğe geç
← Blog

Microservice nedir ve avantajları nelerdir ?

22 Ocak 2020, 22:45 Architecture 7 dk 1.6k 0

Bir süredir microservice olarak geliştirmeler yaptığımız bir projede çalışıyorum. Gördüğüm ve banada anlamlı gelen bir durum olarak microservice’leri tercih etmemizin temel nedeni, monolith olan uygulamalar üzerinde artık esnekliğimizi kaybetmiş olmamız, bugün büyük bir monolith uygulamada çalışıyorsanız, bunun ne demek olduğunu bir takım hatırlatmalardan sonra anlayacağınızı ya da fark edeceğinizi düşünüyorum;

  • Gelen yeni bir feature’ı implement ettiğinizde tüm uygulamanın yeniden deploy edilmesi, herhangi bir hatada bu süreci en baştan işletmeniz.
  • Nereyi değiştireceğiniz konusunda tedirginlik yaşamanız, implementation konusunda artık zorlanıyor olmanız. Sonuç itibariyle elinizde milyon satırdan oluşan bir uygulama mevcut.
  • Akıl almaz deployment zamanları.
  • Artan trafik ve performans gerektiren işlemlere göre monolith uygulamayı scale etmenin maliyeti.
  • Öngörülemeyen ve düzgün test edilemeyen bir kod parçasının runtime’da monolith uygulamayı tümüyle down edebilmesi.

Yukarıda bahsettiğim teknik açıdan görebildiklerim bir de bunun uygulamaya değer katacak geliştirmelerin eklenmesi gibi domain tarafını ilgilendiren gecikmelerde var. Sonuç itibariyle yazılımcının teknik detay içinde kaybolduğu ve kimi zaman farkına varamadığı bir konu var bir uygulama müşteri için geliştirilir sizin teknik yeteneklerinizi arttırmak için değil en azından birinci öncelik bu değil. Size para kazandıran değer oluşturmak.

Biz yazılımcılar bir application geliştirirken beklentimiz; kodumuzun olabildiğince cohesion (tutarlı) ve loosely coupled (sıkı sıkıya bağlı olmama) olmasıdır. Her zaman mimariyi böyle kurgulamayız ki uygulamamız stabil olsun.

Larry Constantine bu konuyu şu şekilde tanımlamış. “A structure is stable if cohesion is high, and coupling is low”.

Bir uygulamamızı microservice’lere bölmek istiyorsak, Robert C. Martin’nin dediği gibi “Aynı nedenle değişen şeyleri bir arada toplamalıyız, farklı nedenlerle değişenleri ise ayırmalıyız”. Böylece kendi servisimize bir sınır (service boundary) çizmiş oluruz. Böylece kendi içinde tutarlı ve bağımsız servisler oluşturabiliriz.

Bu yazının ilk satırlarında microservice’i tanımlarken otonom olduğunuda vurguladım, hemen bir üstteki paragrafta bahsettiğim olgunluğa servisiniz eriştiğinde yani demem o ki servisinizde bir değişiklik gerçekleştiğinde consumer herhangi bir değişiklik yapmadan, kırılmadan yoluna devam edebiliyorsa, bu servisi artık istediğiniz gibi istediğiniz zaman aralığında deploy edebilirsiniz demek.

Başlık başlık biraz microservice mimarisinin avatanjlarından bahsedeyim tabi ki yazının sonunda dezavantajlarından ve monolith’i çokta aşağılamayın onunda güzellikleri var diyeceğim.

Technology Agnostic

Microservice ile birlikte artık nur topu gibi bir distributed sisteme sahip oluyoruz. Bu minik minik servisler kendi işlerini küçük kod parçaları halinde yaparken, tabi ki bir biriyle konuşmak zorundalar bunu yukarıda belirttiğimiz gibi network üzerinden yapıyorlar, servis size belli network end-point’leri sunuyor, diğer servislerde bu endpointler üzerinden bir birleri ile konuşuyorlar. Yani servislerin bildikleri tek şeyler bu endpointler, bu endpointlerin arkasında ne var bilmek zorunda değiller. Bu nedenle servisleri hangi teknoloji ile yazdığınızın bir önemi yok Java olabilir Go olabilir ne olursa olsun.

Şimdi kendiniz şu soruyu sorabilirsiniz peki neden ?

Burda düşünmeniz gereken tek şey bana göre; doğru işi doğru teknoloji ile yapmanız gerektiği. Yaptığınız bir iş çok iyi performans gerektirebilir ve siz Java’nın bu konuda iyi olmadığını düşünebilirsiniz Go dilinde yazmaya karar verirsiniz.

Monolith uygulamada bunu yapmayı düşünsenize ?

Bunun yapamayacağınızı anladığınıza göre; diğer bir katkıda yeni teknolojileri deneme fırsatı oluşturması, microservice’leri kısa süreler içinde yeniden yazacak boyutlarda böldüğümüz için çok kısa süreler içerisinde yeni teknolojileri test edebiliriz. Burada aslında daha iyi bir mimari konsepti var Evolutionary Architecture, bu kısmı okuyup araştırmakta fayda var.

Resilience

Monolith bir uygulamanın bir yerinde hata oluştuğunda, tüm sistemin durmasına neden olursunuz. Diyebilirsiniz ki uygulamam monolith olsada zaten birden fazla node üzerinde çalışıyor, diğer nodelar çalışmaya devam eder. Evet bu sizi bir zaman aralığında koruyacaktır fakat şöyle bir durum düşünün memory leak oluşturduğunuz bir kod parçasını canlı ortama kaçırdınız ve tüm node’lar üzerine dağıttınız. İlk node down olduğunda bu node için tüm uygulama artık request’lere karşılık veremeyecek konuma gelecektir ve tüm nodelar sıra ile down olacaktır.

Microservice’de bunu izole etme şansınız var, çünkü kendi makinasında çalışan bir uygulamadan bahsediyoruz.(Buraya bir dipnot koymak gerekirse; özellikle bu mimaride servislerinizi ayrılmış makinelerde koşturun denmektedir. Temel neden budur.) X microservice’simiz down olsada diğer servisler bu durumdan etkilenmeyecektir. Microservice’de fault tolerance yapmanıza yardımcı olacak bazı stratejiler mevcut ama bunu başka bir blog konusu yapabiliriz.

Scaling

Kurumsal bir firmada çalışıyorsunuz ve elinizde o devasa EAR dosyası var, deployment’lar node node yapılıyor. Allah bilir içinde kaç tane modül var component var.

Ben size bir ödeme sistemi üzerinden scaling olayını anlatmaya çalışayım. Temel olarak iki modül olsun; birisi ödemeyi gerçekleştiren ve diğeri faturayı görüntüleyen modül. Tahmin edebilirsiniz ki ödeme modülü çok büyük miktarda request alacak modül diğeri ise kullanıcı isterse gidip faturasını sorgulayacak modül. Elinizde bir EAR olduğunu düşünün ve bu monolith uygulamayı deploy ettiniz ve öyle bir an geldi ki ön göremediğiniz bir zaman aralığında çok ciddi miktarda yük altında kaldınız, tabiki ödeme modülü yüzünden ne yaparsınız ?

Monolith bir uygulama için yapabileceğiz en hızlı çözüm, donanımı güçlendirip uygulamayı ayağı kaldırmak. Peki neden fatura modülünüde deploy etmek zorundayız kısmını düşünüyorsanız, doğru düşünüyorsunuz. Etmek zorunda değildik ama bu devasa uygulamayı bölemediğimiz için kaynak israfı yaptık ve deploy ettik.

Şimdi microservice mimarisi açısından düşünün, kendi makinasında çalışan uygulaman yük altında kaldı, yapmam gereken ve scale etmem gereken tek şey bağımsız microservice’imi scale etmek olacaktır. Kaynaklarımızı doğru yere yönlendirerek cost reduction yaptık.

Nasıl cost reduction yaptık peki ? Şöyle ki bir EAR için deploy edilmesi gereken güçlü bir makina yerine çok ucuz bir hardware ile bu işi çözdük.

Easy Deployment

Kurumsal firmalarda çalışan bir çok yazılımcı için kabus olan release günlerini tahmin ediyorsunuzdur. Nöbete kalanlar, onların sistemi izlemesi hatta test etmesi, bir hata çıktığında hotfix için saatlerce onayların alınması, yeni EAR oluşmasını beklemek, milyon satır uygulama içinde hatayı düzeltmek ciddi derecede bir risk içermektedir. Peki microservice’de bunu nasıl yapıyoruz?

Kendi service boundary’lerine sahip cohesion yüksek loosely coupled bir microservice’siniz artık bağımsız bir şekilde deploy edilebilir. Bunun için X bir grubun deploy etmesini beklemek zorunda değilsiniz hatta bir release sürecine dahil olmak zorunda bile değilsiniz. Burada da belli stratejiler mevcut bu da başka bir blog konusu aslında blue-green deployment gibi down-time yaratmayacak şekilde fix yapabileceğiniz stratejiler kurarak kimseye bağımlı olmadan Continues-Delivery yapabilirsiniz. Bu benim favori başlığım. Çünkü avantaja istinaden çok hızlı bir şekilde uygulamama değer kazandıracak işler yapıp, hatalarımı tüm sistemi riske atmadan düzeltebilir. Hızlı bir şekilde geliştirdiğim yeni feature’ları canlı ortama alabilirim.

Monolithic uygulamaların avantajlarınıda unutmayın

Mimari bir tercihtir ama bu tercihi bir çok faktöre göre doğru yapmalısınız. SOA kötü diyemeyiz, oda başka bir problemin çözümü için ortaya atıldı ve yıllardır kullanıldı, kullanılıyor. Bana kalırsa ilk bakış açım ile basit uygulamalar veya karmaşıklığı artmayacak uygulamalar için microservice’i tercih etmem. Çünkü microservice operasyonel yükleride birlikte getiriyor hatta organizasyonunuzu yeniden şekillendirmek zorunda kaldığınız bir mimari.

Microservice ile artık elinizde, distributed bir sistem olacak ve bu konudaki zorlukları çözmek zorundasınız. Mesela transaction, benim en çok takıldığım konu aslında, artık geleneksel transaction mantığı ile sistemi yönetemeyeceksiniz bunun farkında olmalısınız. Nedeni olarak CAP teoremi ve ACID konusunu okumalısınız.

Bunun yanında elinizde bütünüyle bir uygulama varken deploy etmek çok basitti. Belki bir EAR dosyası vardı ve dört güçlü makinaya bir EAR’ı yaymak insan gücü ile olabiliyordu ama artık böyle düşünemezsiniz. Burada onlarca uygulamanın deployment sürecini yönetmek zorunda kalacaksınız, fail olma stratejileri kurmak zorundasınız.

Ve dahası bir tek uygulamayı trace etmek kolay iken artık distributed tracing yapmak zorundasınız, artık aynı JVM üstünde koşan uygulamalarınız olmayacak ve bir birlerini call eden onlarca servisten bahsetiyoruz bunları monitör etmek zorundasınız bunlar için stratejiler oluşturmalısınız.

Bu mimariye neden geçmelisiniz kazançlarınız ne olacak, requirement’larınız gerçekten sizi bunamı zorluyor. Bu metrikleri gerçekten iyi değerlendirerek buna karar vermelisiniz.

Kaynaklarım;