5 puan yazan GN⁺ 2023-10-31 | 1 yorum | WhatsApp'ta paylaş
  • Backend genelde bir monolit olarak başlar, ancak birden fazla özellik ekibi aynı kod tabanına dokunmaya başladığında bağlılık artabilir ve değişim hızı yavaşlayabilir
  • Mikroservisler, servisleri işlevlerine göre bölerek bağımsız dağıtım ve küçük ekiplerin özerkliğini elde etme yaklaşımıdır
  • Servisler aşırı küçük olduğunda avantajlardan çok operasyonel yük artar; bu yüzden “micro” adı aslında muhakemeyi bulanıklaştırabilir
  • Tam kapsamlı geçiş; standardizasyon, kaynak sağlama, uzak çağrı savunması, CI/CD, operasyon ve nihai tutarlılık dahil geniş bir maliyet getirir
  • Genelde monolit içinde sınırlar yeterince öğrenildikten sonra büyüme sancıları arttığında servisleri teker teker ayırmak daha güvenlidir; mikroservis öncelikli yaklaşım ise deneyim ve platform hazırlığı olduğunda uygundur

Monolit büyüdüğünde ortaya çıkan sınırlar

  • Modern tek sayfalı JavaScript uygulamalarının backend'i genelde RESTful HTTP API sunan ve ilişkisel veritabanı kullanan tek bir stateless web servisi olarak başlar
  • Bu servis, farklı iş fonksiyonlarını gerçekleştiren bileşenler veya kütüphanelerden oluşur
  • Aynı kod tabanına katkı veren özellik ekipleri arttıkça bileşenler arası bağlılık yükselir ve ekiplerin çalışma alanları daha kolay çakışır
    • Verimlilik düşer ve bir değişikliğin etki alanını öngörmek zorlaşır
  • Kod tabanı yeterince karmaşık hale geldiğinde artık kimse tamamını tam olarak anlayamaz; bu da yeni özellik geliştirmeyi ve hata düzeltmeyi yavaşlatır
  • Backend ekip bazlı kütüphanelere bölünmüş olsa bile, kütüphane değişiklikleri sonuçta servisin yeniden dağıtılmasına yol açar
    • Bellek sızıntısı gibi bir hata girerse tüm servis etkilenebilir
    • Hatalı bir build geri alındığında, sadece hatayı yapan ekibin değil tüm ekiplerin hızı etkilenebilir

Servis sınırlarının sağladığı özerklik

  • Monolitik backend'in büyüme sancılarını azaltmanın bir yolu, backend'i bağımsız dağıtılabilen servisler topluluğuna bölmektir
  • Servisler API'ler üzerinden haberleşir ve API'ler, aynı süreç içindeki bileşen sınırlarına göre ihlal edilmesi daha zor sınırlar oluşturur
  • Bu mimariye mikroservis mimarisi denir, ancak micro ifadesi yanıltıcı olabilir
    • Servislerin mutlaka küçük olması gerekmez
    • İşlevi fazla az olan servisler, avantajdan çok operasyonel yük yaratabilir
  • Daha uygun bir ad service-oriented architecture olabilir, ancak bu isim de eski yüklerini taşır

Küçük ekipler ve bağımsız servislerin yarattığı hız

  • Backend'i iş fonksiyonlarına göre servislere böldüğünüzde, her servis tek ve küçük bir ekip tarafından geliştirilebilir ve işletilebilir
  • Küçük ekipler daha etkilidir çünkü iletişim maliyeti ekip büyüklüğüne göre kare olarak artar
  • Her ekibin kendi yayın takvimini belirlemesi ve kendi kod tabanını kontrol etmesi, ekipler arası koordinasyonu azaltır ve karar almayı hızlandırır
  • Servis kod tabanı küçükse geliştiricilerin anlaması kolaylaşır ve yeni çalışanların uyum süresi kısalır
    • Küçük kod tabanları, IDE yavaşlamasını azaltarak geliştirici verimliliğine de katkı sağlar
  • Güçlü servis sınırları sayesinde geliştiricilerin backend'in bir bölümünü değiştirirken tüm sistemi değil sadece küçük bir kısmı anlaması yeterlidir
  • Her servis bağımsız ölçeklenebilir ve kendi ihtiyaçlarına uygun teknoloji yığınını seçebilir
    • API tüketicileri, işlevin içeride nasıl uygulandığıyla ilgilenmez
    • Sistemin diğer alanlarını etkilemeden yeni teknolojileri denemek ve değerlendirmek daha kolaydır
  • Her mikroservis kendi veri modeline ve veri deposuna sahip olabilir
    • Geliştiriciler, diğer servisleri etkilemeden şemayı değiştirebilir

Mikroservislerin eklediği gerçek maliyet

  • Mikroservisler tüm sisteme daha fazla hareketli parça ekler ve bunun maliyeti bedava değildir
  • Mikroservisleri tamamen benimsemenin maliyeti, ancak onlarca geliştirme ekibine yayılıp dağıtık biçimde amorti edilebildiğinde ödemeye değer olur
  • Geliştirici deneyimi

    • Her serviste farklı diller, kütüphaneler ve veri depoları kullanmak mümkündür, ancak bu uygulamanın bakımını zorlaştırabilir
    • Yazılım yığınları tamamen farklıysa, geliştiricilerin bir ekipten diğerine geçmesi zorlaşır
    • Loglama gibi tüm servislerde gereken ortak işlevleri sunmak için, benimsenen her dilde kütüphane desteği sağlamak gerekir
    • Belirli bir düzeyde standardizasyon gereklidir
    • Önerilen dil ve teknoloji portföyünü izleyen ekiplere iyi bir geliştirici deneyimi sunarak, belirli teknolojilerin kullanımı gevşek biçimde teşvik edilebilir
  • Kaynak sağlama

    • Çok sayıda bağımsız servisi desteklemek için sunucuların, veri depolarının ve diğer genel kaynakların kolayca oluşturulabilmesi gerekir
    • Her ekibin kaynak oluşturma yöntemini kendince tasarlamasına izin verilmemelidir
    • Sağlanan kaynakların tekrar yapılandırılması gerekir ve bunu yönetmek için önemli ölçüde otomasyon gerekir
  • İletişim

    • Uzak çağrılar maliyetlidir ve sistemin çökebileceği yeni yollar ortaya çıkarır
    • Arızalara karşı timeout, retry ve circuit breaker gibi savunma mekanizmaları gerekir
    • Ağ iletişiminin performans kaybını azaltmak için asenkron işleme ve batch yöntemleri de kullanılmalıdır
    • Bu unsurlar sistem karmaşıklığını artırır
    • Monolitler de uzak istemci erişimi ve üçüncü taraf API kullanımı nedeniyle benzer sorunlar yaşayabilir, ancak ölçekte daha küçüktür
  • Sürekli entegrasyon, teslimat ve dağıtım

    • Sürekli entegrasyon, otomatik build ve testler çalıştıktan sonra kod değişikliklerinin ana branch'e birleştirilmesini sağlar
    • Kod değişikliği birleştirildiğinde, production benzeri bir ortama otomatik olarak yayımlanmalı ve deploy edilmelidir
    • Bu ortamda entegrasyon testleri ve uçtan uca testler çalıştırılarak mikroservisin bağımlı olduğu diğer servisleri bozmadığı doğrulanır
    • Tek tek mikroservisleri test etmek, monolit testlerinden daha zor değildir; ancak tüm mikroservislerin entegrasyon testleri çok daha zordur
    • Bireysel servisler etkileşime girdiğinde son derece ince ve beklenmedik davranışlar ortaya çıkabilir
  • Operasyon

    • Monolitten farklı olarak, her servisten sorumlu ekip için ayrı operasyon ekipleri bulundurmak çok daha maliyetlidir
    • Servisi geliştiren ekip genelde o servisin on-call sorumluluğunu da üstlenir
    • Ekipler her sprint'te geliştirme işi ile operasyonel yük arasında hangisine öncelik vereceğine karar vermek zorundadır ve bu da sürtüşme yaratır
    • Sistem arızalarını debug etmek de daha zordur
    • Tüm uygulamayı yerel makineye kaldırıp debugger ile adım adım çalıştırmak mümkün değildir
    • Hareketli parça sayısı arttıkça başarısızlık biçimleri de artar
    • Her seviyede iyi loglama ve izleme kritik hale gelir
  • Nihai tutarlılık

    • Uygulama birden fazla servise bölündüğünde, veri modeli artık tek bir veri deposunda bulunmaz
    • Farklı veri depolarındaki kayıtları atomik olarak güncellemek ve güçlü tutarlılığı garanti etmek yavaş, pahalı ve uygulanması zor bir iştir
    • Bu tür mimariler genelde nihai tutarlılığı kabul etmek zorundadır

Ne zaman ayırmalı?

  • Uygulamayı servislere bölmek, tüm sistemin karmaşıklığını önemli ölçüde artırır
  • Genel olarak monolitle başlamak ve ancak ayırmak için yeterli neden olduğunda parçalamak daha iyidir
  • Servisler arası sınırları doğru belirlemek zor olduğu için, monolit içinde sınırları kaydırarak doğru noktayı bulmak daha kolaydır
  • Monolit yeterince olgunlaşıp büyüme sancıları belirginleştiğinde, mikroservisler birer birer ayrılabilir
  • Mikroservis öncelikli yaklaşım ancak hâlihazırda deneyim varsa ve bunun için bir platform kurulmuşsa ya da platform kurma süresi hesaba katılmışsa uygundur

1 yorum

 
GN⁺ 2023-10-31
Hacker News yorumları
  • Yazıya genel olarak katılıyorum ama tersinden bakınca, bu maliyete katlanmaya değen durumlar da var: eski üçüncü taraf bağımlılıkları ile uyumluluk sorunlarını ayrı bir servise ayırarak acı verici refactoring ya da baştan kendi uygulamanı yazma işinden kaçınabilirsiniz; yüksek erişilebilirlik gerektiren çekirdek sistemlerin dağıtım kısıtlarının diğer sistemlerin dağıtımını engellemesini önleyebilirsiniz; büyük müşterilerin değiştiremediği tasarım kısıtlarını izole edebilirsiniz
    Bunun bedava olduğu anlamına gelmiyor; basit bir monoliti çöp yığınına çevirmemek, riskli dağıtımlarla sarsılmamasını sağlamak ya da daha kötü bir teknoloji yığınına sahip iş ortaklarına bağımlı kalmamak için ödenmeye değer bir maliyet olduğu anlamına geliyor

    • Bu daha çok sadece bir iki servis bulundurmak gibi değil mi? Bunun “mikroservis” ile aynı şey olduğunu düşünmüyorum
      Mikroservis, iç bileşenleri varsayılan olarak kütüphane ya da sınıf yerine servis olarak kurma yaklaşımı değil mi?
    • Bir şey daha ekleyeyim: farklı programlama dillerini rahatça kullanabilme avantajı var. Her dil her probleme iyi uymaz
      Makine öğrenmesi çıkarım servisini Python, sunucu tarafı render edilen UI'ı Rails, yoğun G/Ç ve eşzamanlılık gerektiren servisleri Go ile yazmak istiyorsanız, bu üçünü ayrı servisler olarak bölmenin ek yükü haklı görülebilir
    • İyi tasarlamanın birçok yolu var, ama bu mikroservisleri düşünmeden uygulamaya almalısınız anlamına gelmiyor
      Mikroservisleri seven biriyim ama erken optimizasyon ve erken ölçekleme, sonradan bambaşka bir yöne optimize etmek gerektiğinde oluşan teknik borç kadar kötü olabilir
      1. maddede neden ayrı bir servise çıkarmanın, net bir API’ye sahip bir arayüz ile sarmalamaktan daha iyi olduğunu anlamıyorum
    • Bu tür durumlar herhalde tüm kod tabanının %10’undan azı için geçerlidir
  • Bir şeyi ayrı bir servise çıkarmanız gereken an, bunu yapmadan sorunu yönetilebilir bir şekilde çözemediğiniz andır
    Sınırları zorla dayatmak için mimari karmaşıklığı artırmak, kurumsal disiplin eksikliğinin çözümü olamaz; ama orta ölçekli teknoloji şirketleri buna sürekli böyle davranıyor. Alan sınırları zayıf olduğu için sorun çıkıyorsa, servisi ayırmak da muhtemelen bunu iyi çözmez

    • Son sorumlu an, kararı erteleme stratejisidir; ta ki daha fazla ertelemenin maliyeti, şimdi karar vermenin maliyetinden yüksek olana kadar”
      Alıntı: https://www.oreilly.com/library/view/software-architects-han...
    • Sınırları zorla dayatmak için mimari karmaşıklığı artırmanın örgütsel disiplin eksikliğinin çözümü olmadığı söyleniyor ama pratikte hep bunu yapıyoruz
      Testler geçene kadar PR’ları engelleyen CI/CD de örgütsel disiplin sorununu çözmek için kullanılan pahalı bir teknik çözümdür
    • Bu, çözüm arayan problem anlamındaki SISP gibi geliyor. Ya da temel nedeni anlamadan bir probleme çözüm fırlatmaya benziyor
    • HN’de mikroservislerin asla haklı gösterilemeyeceğine dair bir meme yaygınlaşmış gibi görünüyor, ama sektörün tamamı böyle düşünmüyor; bu da garip
      Alan adı çözümlemesini dış bir servisin yapmasının mantıklı olduğunu herkes kabul ediyor ve özyinelemeli DNS çözümleyicisini ve önbelleği monolite entegre eden neredeyse kimse yok. Ama bu kadar eski bir sorumluluk ayrımı nedense iyi bir örnek olarak kabul edilmiyor
    • Bunu hep ertelenmiş uygulamanın en iyi örneği olarak gördüm. Şirketlerin bunu ne kadar sık yanlış yaptıklarına şaşırıyorum
      Sorun galiba “iyi” çalışanların, değer göstermek için aşırı istekli olmaları ve bunun aşırı tasarıma, oradan da cehenneme dönüşmesine yol açması
  • Mikroservisler
    grug, büyük beyinlerin bir sistemi doğru şekilde bölmenin zaten en zor problemine neden bir de ağ çağrılarını eklediğini merak ediyor
    grug’a çok kafa karıştırıcı görünüyor
    https://grugbrain.dev/#grug-on-microservices

    • Grug sanki büyük ekiplerin birbirlerinin alanlarına ve veri modellerine müdahale ettiği, belli uygulamalara sıkışıp kaldığı ve ekip bazlı özellik yayınları için devasa kurumsal çaba gerektiği durumları hiç yaşamamış gibi. Mikroservisler ve her ekibin kendi veri deposunu kontrol etmesi, ekip hızını artırır
      “SCALE_REASONS yüzünden FOO_TABLE yaklaşımını modernize etmek için MySQL’den DynamoDB’ye geçmek istiyoruz ama 59 ekipten 32’si FOO_TABLE’a doğrudan erişiyor ya da sınıfımızın private metodlarını doğrudan çağırıyor. Öncelikleri farklı olduğu için bu ekipler FOO_SERVICE kullanmaya geçemiyor ya da sharded tabloları kullanacak şekilde sorgularını değiştiremiyor. Sonuç olarak FOO_TABLE’ı ölçeklemek çok çeyrekli bir işe dönüşüyor ve ekiplerin yavaş yavaş güncellenmesine izin vermek zorunda kalıyorsunuz. 1-2 yıl sonra, şu an yanan eski yaklaşımı emekliye ayırabiliriz belki. O zamana kadar on-call keyfini çıkarın”
      Mikroservis olsaydı ekip tablonun ölçeklenmediğini fark ederdi ama veri API ile sunulmaya devam ederdi. Sonraki sprintte migration planlanır ve uygulanırdı; API kullanıcıları ise işlerin çok hızlandığını hissederdi
    • Otomatik tamamlama için statik tipler şart değil. JetBrains’in Ruby ya da Python gibi dillerde de otomatik tamamlama sunan IDE’leri var
      Modern Ruby REPL’i açarsanız, otomatik tamamlama ve sözdizimi kontrolü açısından statik tipli dil IDE’lerinden beklediğiniz şeylerin büyük kısmını alabilirsiniz
    • Ağ çağrıları eklemek güçlü bir şeydir. Gerçekten fiziksel olarak dayatılan, aşılamaz bir sınır ortaya çıkar ve iki servis birbirini yalıtılmış yapılar olarak ele almak zorunda kalır
      Yalıtım hafife alınmamalı; yazılıma eklenebilecek en güçlü özelliklerden biridir. Performansı artırabilir, arıza sınırları oluşturabilir ve güvenlik sınırları sağlayabilir
      Bu, aktör modelinin temel kavramıyla aynıdır. İki bileşenin birbirinin belleğini paylaşması ve değiştirmesi yerine, aktörler ya da mikroservisler gibi iki yalıtılmış sistem yalnızca tanımlı bir protokol üzerinden iletişim kurar
  • İnsanların modülerliği yanlış anladığını düşünüyorum. Modülerlik önemli, ama bir başka önemli mimari ilkenin daha olduğunu düşünmeye başladım: tek girdap ilkesi
    Yazılım sistemlerinde girdap, veri akışındaki döngüdür. Veriyi bir yere gönderip işlenmiş sonucu geri alıyorsanız ya da bir şekilde o verinin etkisini yeniden görüyorsanız, ortada bir girdap vardır. Değiştirilebilir değişkenler bunun çok küçük bir örneğidir
    Tek girdap ilkesi, ideal olarak bir yazılım sisteminde yalnızca tek bir girdap olması gerektiği ya da başka bir deyişle tüm bileşenlerin kendi girdaplarının hangi yönde döndüğünü bilmesi gerektiği anlamına gelir
    İki ayrı girdap oluşturan modülleri birleştirirken, girdap yönleri uyuşuyorsa bileşim kolay olur; ters yönlülerse yeni girdabın yönünün ne olacağına karar vermek gerektiği için iş zorlaşır. Bu yüzden en iyisi, tüm modüllerin aynı yönde dönen girdaplara sahip olup tek bir girdap oluşturmasıdır
    Bu ilke, Flux pattern, CQRS, event sourcing ve immutability gibi fikirlerin genelleştirilmiş halidir

    • Çok iyi bir nokta; sadece bu konu üzerine bile birkaç yazı çıkabilir. Servis A, B'yi çağırabilir, B, C'yi çağırabilir ve C de tekrar A'yı çağırabilir; bu durumda sorun çıkar
      Ya da A'da beklenmedik bir şey olur ve bunun sonucunda C tıkanabilir. İdeal durumda ebeveyn sadece çocukları çağırmalı ve çocuklar ebeveyne bağımlı olmamalıdır; bu başarısız olursa mimari de başarısız olmuş demektir
    • Bu kavram hoşuma gitti
      Mimari diyagramlara bakarken mücadelenin yarısı neyin asenkron/senkron olduğunu, itme/çekme olduğunu, akışın yönünü ve sırasını anlamaktır
      Enterprise Service Bus ve mesaj kuyrukları, iki tarafın yönlerinin uyuşmadığı yerlerde girdap üretmeye yönelik bir çözüm gibi görünüyor
    • Bu girdap kavramı ilginç. İncelemeye değer kitaplar ya da çevrimiçi kaynaklar olup olmadığını merak ediyorum
    • Sondan bir önceki paragrafı, özellikle de gerekçesini tam anlayamadım. Biraz daha açabilir misiniz, merak ediyorum
  • “Benimsediğiniz her dil için bir tane olmak üzere, logging gibi tüm servislerin ihtiyaç duyduğu ortak işlevleri sağlamak adına desteklemeniz gereken kütüphane sayısı”nın sorun olduğundan bahsediliyor
    Bu, bizim mikroservisleri bırakmamızın en büyük nedeni oldu. 2023'ün araçlarıyla, özellikle saf cloud-native ya da sonsuz ölçeklenen FaaS ortamlarında, bu kaygılar için zihinsel bant genişliği harcamak tam bir israf. Banka ve finans kurumu gibi müşteri gruplarında bu daha da geçerli; çünkü üçüncü taraf bağımlılıkların her birini aşırı sıkı biçimde inceliyorlar
    Şu anda gzip ile yaklaşık 250MB olan tek bir monolitik .NET binary dağıtımıyla çalışıyoruz ve hiçbir çatlama belirtisi yok. 10~100MB'lık SaaS dağıtımları için “exe dosyam artık L2'ye sığmıyor” gibi titiz kaygılar taşıyorsanız, rahat olun. Monolitik yazılım yolculuğunuz daha yeni bile başlamadı
    Bu çöp yığınlarından birini yeniden yazmak zorunda kalırsanız, tüm commit'lerin küresel olarak tutarlı biçimde tek bir yerde olması çok daha kolay olmaz mı?

    • Bunun sahte bir ikilem olduğunu düşünüyorum. Benim deneyimlediğim mikroservis organizasyonlarının çoğu, bu ve benzeri nedenlerle onaylı dil sayısını sadece 2-3 ile sınırlıyordu; ekip başka seçenekleri olmadığını gösterebilirse liderlik istisnaya izin verebiliyordu
      Mikroservisler, her ekibin organizasyonun tamamını umursamadan hareket edebileceği bir kanunsuz alan demek değildir. Ekipler arasında belli ölçüde tutarlılığı korumaya yönelik kurallar olabilir ve olmalıdır
    • Aslında bu mikroservislerde çok daha kolay. Çünkü desteklemeniz gereken açık bir arayüz vardır ve kod, monolitin geri kalanıyla Fransız örgüsü gibi birbirine dolanmış değildir
      En iyi kod, atıp yeniden yazması kolay olan koddur. Gerçekte eski kod daha fazla kişinin elinden geçer ve gittikçe kötüleşir; en önemlisi de kimse onu sürdürmek istemez hale gelir
    • O monolitte çalışan geliştirici sayısı önemlidir. Binary boyutu, ekiplerin genellikle monoliti parçalamaya başlamasının nedeni değildir
    • “Her şey tek bir yerde olduğu için her commit küresel olarak tutarlıysa çok daha kolay olmaz mı?” cümlesi bana hep biraz komik gelmiştir. İki taraf da bunu sık söyler ama karşı tarafın bakış açısından düşünmek nadirdir
      Mikroservisleri tercih eden taraf, bir servisin nasıl çalışması gerektiğine dair açık bir sözleşme olduğunu ve ilgili servisin kod tabanının çok daha küçük olduğu için değiştirmesinin ya da yeniden yazmasının daha kolay olduğunu söyler
      Monolit tarafı ise her şeyin büyük bir ip yumağı olduğunu, bu yüzden bir ipi değiştirmek için o ipin diğer iplerle nerelerde dolaştığını bilmenin yeterli olduğunu ve bu nedenle değiştirmenin ya da yeniden yazmanın daha kolay olduğunu söyler
      Kimin haklı olduğunu bilmiyorum. Yıllarca kod tabanını mikroskop altında incelemiş uzun süreli çalışanlar için monolit, diğer herkes içinse mikroservisler daha iyi olabilir
    • Tüm mikroservislerin aynı dili kullanmaması gerektiğini söyleyen kimse yok
  • Release management açısından bakınca, monolitten mikroservislere geçiş çoğu zaman yanlış nedenlerle yapılıyor
    Gerçek bir değişiklik için tek geçerli nedenin, performans darboğazlarının yol açtığı ölçeklenebilirlik sorunu olduğu görülüyor. Geri kalan her şey, yazılım geliştirme karmaşıklığını sistem bakımına taşımaktan ibaret
    Elbette geliştiriciler, başka ekiplerle hizalanma yükünün azalmasından memnun olacaktır. Ama bir özelliğin ne zaman ve nasıl uygulanacağını, mikroservislerin tamamında doğru şekilde test edileceğini, production'da etkinleştirileceğini ve merkezi olarak yönetileceğini netleştirmek; geliştirme ekipleri arasındaki iletişim yeterince olgun değilse çok daha zor hale gelir. Ve bu olgunlaşmamışlık çoğu zaman zaten baştan monoliti bölmenin asıl nedenidir

    • Geçerli nedenler de çok, yanlış nedenler de çok. Birden fazla paydaş varsa, iş gereksinimleri sürekli değişiyorsa ve geliştirici sayısı 10'dan fazlaysa, bağımsız biçimde deploy, test ve release edilebilen birimlere sahip olmak için yeterli neden olabilir
      Tersine, geliştirici sayısı azsa ve bağlam iyi tanımlanmışsa, birden çok mikroservisle uğraşmak işkence olur
      “Geri kalan her şey, yazılım geliştirme karmaşıklığını sistem bakımına taşımaktan ibaret” sözü, yazılım aktif olarak geliştiriliyorsa makul görünüyor. Geliştirme pahalıdır. Dağıtık sistemlerin bakım maliyeti büyük bir ekip için devasa bir monolit geliştirmenin maliyetinden daha düşük olabilir; sonuçta her şey duruma bağlıdır
    • Uygulamanın bu bölümünü ayrı bir bileşen olarak ayırmak istememizin tek nedeni de bu. O kadar büyüdü ki etkili biçimde bakımını yapmak zorlaştı; uygulamanın geri kalanı ise olduğu gibi kalacak
  • “Monolitin maliyeti” yazısı nerede? Burada o görünmüyor. Herkes mikroservisleri cahilce uyguladığı için sadece o sorun görünüyor
    Herkes monolitleri cahilce uyguluyor olsaydı “monolit kötü” yazılarını tonla görürdük
    İnsanlar iki sistemin de sonuçta aynı miktarda sorun ürettiğini anlamıyor. Bu, bir file iş yaptırmakla 1000 fareye iş yaptırmak arasındaki fark gibi. İkisi de sorun yaşar; sadece sorunları farklıdır
    Bunlardan birini seçince sorunlar ortadan kalkmaz. Hangi tarafı seçerseniz seçin sorun çıkar ve birini seçip çözüm üretmeniz gerekir. “Hangi mimari olduğu” en büyük engeli olan bir şirkette çalışmak isterim

    • Şu an mikroservislere aşırı gömülmemizin nedeni, geçmişte monolit kötüdür türü yazıların sayısız olması. Şimdi bu, maliyet/fayda oranının kendilerine uygun olmadığını fark etmenin ters tepkisi
  • Eğer monolit iyi bölünmüşse, aynı yerde dağıtılan mikroservisten farkı nedir? Muhtemelen sadece arayüzdür. Fonksiyon çağrısı RPC olur; bileşenleri ayrı ayrı ele almanın faydası için, örneğin yama geçmek adına biraz ek yük kabul edilir
    Dağıtık mikroservislerle aynı yerde duran mikroservisler arasındaki fark nedir? Dağıtım daha karmaşıktır ama süreçleri daha uygun donanıma akıllıca yerleştirebilirsiniz. Hata modları artar ama daha yüksek hata toleransı elde edebilirsiniz
    Bunun sihirli bir cevabı yok. Faydaya ihtiyacınız varsa bedelini ödersiniz. Bence bu mikroservisler ve monolitler tartışmalarının kaynağı, bir deseni yanlış uygulamak, hayatı kolaylaştıracak araçların eksikliği ya da çoğu zaman 10 yıllık yazılımı sürekli refactor edip yeniden tasarlamamak yüzünden, başlangıç mimarisinden bağımsız olarak üzerinde çalışması acı verici bir hale gelmesidir

    • Monolitten mikroservislere geçmek, başlangıçta ne kadar iyi bölünmüş olursa olsun, küçük bir değişiklik değildir. Elbette tasarım kötüyse geçiş daha da zorlaşır
      “Fonksiyon çağrısı RPC olur” sözü basit görünür ama o anda istemci uygulamanın DNS sunucusuna erişilememe, hostname çözümleme hatası, hosta erişilememe, bağlantı reddi, yetkilendirme reddi, güvenilmeyen TLS sertifikası, hız limiti aşımı, 301 kalıcı yönlendirme, sonucun hazır olmaması gecikmesi, timeout gibi tüm yürütme yollarını ele alması gerekir
      İyi bölünmüş bir uygulama bile bunu sağlam biçimde ele almak için asenkron kuyruklar, istek hız sınırlama, sonuç önbelleği, logaritmik backoff retry, yapılandırılabilir istemci kimlik bilgileri/güven depoları/kaynak URL'leri ve hata günlüğü eklenebilecek şekilde yeniden tasarlanmak zorunda kalabilir
      Yerel fonksiyon çağrılarında bağlamda bulunan veriyi sağlamak için ek RPC fonksiyonları ve parametreler de gerekir. Ayrıca monolit UI, daha önce mümkün olmayan ağ gecikmelerini ve hatalarını kullanıcıya yansıtmak zorunda kalabilir
      En iyi yapılmış monolit bile mikroservislere refactor edilmek istendiğinde ciddi emek ister
    • “Fonksiyon çağrısı RPC olur” ifadesinin arkasından yeni hata modları ve daha fazla plumbing işi gelir
      Bu RPC çağrısı güvenle yeniden denenebilir mi? Üstel backoff var mı? API load balancer düzgün çalışıyor mu; öyleyse artık izleme de gerekir. Mikroservisler arası tracing nasıl yapılacak; artık OpenTelemetry gibi bir şeye ihtiyaç doğar
      Mikroservis mimarisinde breakpoint ile debug etmek ne kadar daha zordur? İki mikroservis arasındaki veritabanı transaction'ı nasıl geri alınacaktır? Basit bir fonksiyon çağrısı bir anda çok daha karmaşık hale gelir
    • Mikroservisler tartışılırken lehte konuşan taraf, neredeyse her zaman bu kavramın özü olan mikro kısmını unutuyor. Servis kısmını herkes zaten biliyor; ihtiyaç varsa yapılır, ikna gerektiren fikir o değil
      Bu kavram savunulurken, servislerin çok küçük olması şartının yarattığı parçalanma hesaba katılmıyor. Daha açık söylersek, bir monolit ve bir mikroservisiniz varsa bu mikroservisler değildir. Mikroservis kelimesi, her şeyin küçük servislere bölündüğünü ve monolit kalmadığını ima eder
      Mikroservis lehine çoğu argüman, bunun mutlaka “mikro” olması gerektiğini fark ettiğiniz anda çöker. Ve o şarttan vazgeçince geriye yeni ya da derin bir öneri kalmaz
    • Geliştirici açısından fark arayüzdedir. Monoliti senkronize ve doğru tutmaya yarayan türlü araçlar vardır ama süreçler arası iletişime yardımcı olan araçlar statik değerlendirme yapamaz ve hiç etkileşimli de değildir
      Operasyon açısından bakınca “dağıtım daha karmaşık” demek muazzam bir küçümsemedir. Her paket, kendine özgü özellikleri ve sorunları olan, ayrı ayrı yönetilmesi gereken bir hedeftir
    • Atomik transaction kaybedilir. Bu yüzden tüm iş süreçleri birkaç basamak daha karmaşık hale gelir
  • Bu biraz, frontend geliştiricilerinin React/Vue/Svelte gibi frontend framework veya kütüphaneleri olmadan “modern web uygulaması” yapılamayacağını sanmasına benziyor; bugünlerde “monolit”in, tek bir instance olarak çalışan korkunç devasa bir katran yığını olduğu ve bu yüzden “ölçeklenmediği” yönünde bir fikir dolaşıyor gibi, ama bu saçma
    Bir de görünen şu ki toplam kod miktarı çok daha fazla oluyor ve servislerin çoğu %20 iş/domain kodu ile %80 ağ mesajı gönderip alma işleminden oluşuyor. Ne kadar gizleseniz de sonunda oradadır ve ağı bir şekilde ele almak zorundasınızdır
    Frontend çılgınlığında olduğu gibi, bu mikroservis kültü de ancak ekonomi çöktüğünde ve bu kıyametvari Babil kulelerini ayakta tutacak para kalmadığında sona erecek
    Eklemek gerekirse mikroservislerin de kullanılacağı yerler var. Maliyetten daha fazla değer elde eden bazı şirketlerde mantıklıdır

    • İnsanların mikroservisler konusunda kaçırdığı nokta, hedefin çoğu zaman teknik bir sorunu değil, organizasyon ve insan sorununu çözmek olmasıdır
      Servis bazında bağımsız ölçekleme gibi teknik faydalar da var ama en büyük fayda, net sahiplik sınırları oluşturmak ve gereksiz aşırı bağlılığı engellemektir
      Küçük bir ekip tek bir ürün geliştiriyorsa, mikroservislerin çözdüğü organizasyonel sorunlar henüz yok olabilir; dolayısıyla onlara ihtiyaç olmayabilir. Bu durumda mikroservisler erken optimizasyondur; henüz var olmayan bir sorunu çözmek için bedel ödemek anlamına gelir
    • React/Vue/Svelte framework değil, görünüm kütüphaneleridir; bu pozisyonu sonuna kadar savunacağım
      Dahası frontend karmaşıklığının tamamı zihindedir: https://bower.sh/front-end-complexity
    • Birçok web sitesinin JavaScript'i ve framework'leri fazla kullandığına katılıyorum. Ama masaüstü düzeyinde web uygulamaları yaparken, devasa bir kargaşaya dönüşmemek veya sonunda zaten bu framework'lerde bulunan kavramları yeniden icat etmemek için ne kullanılması gerektiğini merak ediyorum
  • Yazı, geliştirme organizasyonunun tamamen dağılmış ve kontrolden çıkmış olduğunu varsayıyor gibi. Sprint sırasında ne yapılacağına karar verememek, gizlice üçüncü taraf kütüphaneler ve kimsenin bilmediği diller getirmek, uyumsuz değişiklikleri sessizce production'a dağıtmak gibi bir durum söz konusu.
    Geliştiriciler aptal değilse mikroservisler de daha kolay olur gibi görünüyor

    • Ne yazık ki ekip içinde aptalların olması ya da aynı projede çalışan tüm ekibin aptal olması epey yaygın.
      Zeki ve yetkin geliştiricilerden oluşan bir ekipte çalışıyorsanız mikroservislerin daha kolay olacağına eminim. Tabii o durumda her şey daha kolay olurdu
    • Her geliştirici yeni işinde ilk birkaç ay boyunca kaçınılmaz olarak aptal gibi hisseder. Bunun nedeni, mevcut sistemin nasıl çalıştığını anlamak için gereken bilgileri özümsemenin zaman almasıdır.