Çiçeksepeti’nde Yazılım Sistemleri

Turgay Özgür
ÇSTech
Published in
13 min readJan 25, 2022

--

Yazılım sistemleri, uyum içinde çalışan bir organizma olarak düşünülebilir. Bu organizma, yazılımın kendisi, ekip üyeleri, araçlar, ilkeler ve uygulanan iyi pratiklerin bir bütünüdür.

Bu yazıda, Çiçeksepeti’nde tasarlanan ve geliştirilmeye devam edilen yazılım sistemleriyle ilgili fikirler, öğrenilenler ve bazı diğer detaylarla ilgili konulara değineceğim.

Sisteme Hakim Olun

Yazılımda, bir araya gelerek tüm sistemin oluşmasını mümkün kılan en küçük parça tek satır koddur. Bu aslında bir yapı taşı olarak düşünülebilir ve değerlendirmeye de buradan başlamak gerekir.

Temiz Kod

Bir kodu temiz yapan nedir? İsimlendirmeler, dönüşümler, yaklaşımlar, prensipler ve kalıplar… Evet, sadece bir başlık altında ve hatta bir yazıda bile bahsedilebileceklerden çok daha fazlası var. Yine de, aşağıdaki başlıklar, temiz kod konusunun bizim için ne kadar önemli olduğu hakkında size fikir verecektir.

Kod ve Uygulama Seviyesindeki Standartlar

Yazılım geliştiricileri olarak tek bir şirket bünyesinde bile birçok proje ile çalışıyoruz. Geliştirdiğimiz bir servis ya da basitçe bir implemantasyon ve hatta tek satır kod bile, bir diğer geliştirici tarafından kolayca anlaşılabilir olmalı. Kodlama standartlarının endişelerinden biri de bunu sağlamaktır.

Diğer bir yandan, uygulama seviyesindeki standartlar da düşünülmelidir. Standartlardan tam anlamıyla faydalanmanın yolu, hem kod hem de uygulama seviyesinde bu standartların belirlenmesidir.

Bunları kolayca organize edebilmek ve sürdürülebilir kılmak için bir git repository oluşturduk. Statik bir site üzerinde host ederek de gerektiğinde hızlıca bakabilmeyi kolaylaştırdık.

Standartlara sahip olmanın avantajları:

  • Kodun kendisi ve uygulamanın tamamı, geliştiriciler tarafından kolayca anlaşılabilir.
  • Yeni takım üyeleri, takım içinde geliştirilmiş projelere kolayca adapte olabilir.
  • Analizden, testten veya deploymenttan sorumlu diğer takım üyeleri için de daha anlaşılabilir bir yapı elde edilir.
  • Bazı olası sorunlar, daha geliştirme aşamasında tespit edilip çözülebilir.
  • Geliştirme yaparken aynı konseptleri tekrar tekrar düşünmekten kurtarır.
  • Standartları tartışmayı mümkün kılar.

Dikkate alınması gereken bazı başlıklar:

  • Naming, formatting.
  • Configuration, error handling, caching, logging, monitoring.
  • Authentication/authorization.
  • Localization/globalization.
  • Communication. (REST, RPC, Messaging.)
  • Routing. (RESTful maturity level için bir karar vermek.)
  • Uygulamanın mimarisi. (N Layer, Clean Architecture gibi.)
  • Dosya/klasör yapısı. (Programlama diline bağlı olarak.)

Tanımlanan standartlara uymaya zorlayacak bir .editorconfig dosyası oluşturmayı düşünebilirsiniz.

Standartları teknolojinizin her sürecine yayın. Bu süreçler Development, Test Otomasyonu, DevOps, Infrastructure, Security, ve Data olarak düşünülebilir.

Dokümantasyon

https://keepcalms.com

Yukarıda bahsettiğim standartlar, dokümantasyonun da bir parçası olarak kabul edilebilir. Yine de dokümanlara yazılabilecek daha fazla konu vardır. Bunlardan bazıları:

  • Internal librarylerin kullanım klavuzları.
  • How todos.
  • Hatalar ve bulunan çözümler.
  • Ve tabiki, standartlar.

Biz dokümantasyon toolu olarak https://docusaurus.io/ kullanmayı tercih ediyoruz.

Proje Şablonları

Eğer kod daha önca tanımlanan standartlara uygun bir şekilde geliştirildiyse bu, standartların da bir göstergesi haline gelir.

Başka bir geliştiricinin kodları çoğu kez bize doğru, olması gereken kodun kaynağı gibi gelir ve onlardan ilham almak ve o kodları kopyalamak kolayımıza gelir. Standartlara gelince ise bunun önüne geçen şeylerden biri de projeler için şablonlarımızın olmasıdır.

Biz, .NET ve Golang gibi, kullandığımız programalama dilleri için proje şablonları oluşturduk. Bu şablonlar standartlarımza uygun şekilde yazılmış hazır örneklerle geliyorlar ve yeni bir projeye hızlıca başlamayı çok kolaylaştırıyorlar.

Gereğinden fazla düşünmeyin ve her şeyi bu şablonlara koymaya çalışmayın. Proje şablonlarını olabildiğince basit ve en önemlisi de güncel tutmaya çalışın.

Template engine olarak ise https://yeoman.io/ kullanmayı tercih ediyoruz.

Clean Architecture

Web API veya MVC kalıbında projeler geliştirmek için sıklıkla kullandığınız yazılım dillerinde, proje yapısı ve katmanları arası bağımlılıklar iyi tanımlanmış olmalıdır. Clean architecture yaklaşımının devreye girdiği yerlerden biri de burasıdır.

Clean architecture, günümüzde modern web uygulamalarının en yaygın kullanılan tekniklerinden biridir. Onion architecture olarak da adlandırılır.

Representation of the dependencies between layers of clean architecture by microsoft.

Kendi iç projelerimizi ve API’larımızı clean architecture’a göre dizayn etmek için referans aldığımız projelere ise jsontaylordev and ardalis linklerinden ulaşabilirsiniz.

DDD Bir Zorunluluk Değil

Anemic entity/domain objeleri iyi bir pratik olmayabilir. Fakat, DDD bundan çok daha fazlasıdır. DDD’nin ilgilendiği diğer konular bounded context, aggragate root, value object, specification, domain event ve daha fazlasıdır. C# ve Java gibi OO yazılım dilleri DDD prensiplerine kolayca ayak uydurabilirler. Fakat, diğer bazı programalama dilleri için bu o kadar kolay değildir. Yine de uygulamak için zorlamaya değer mi?

Çiçeksepeti’nde biz, mikroservisler veya sayıları çok az olsa da mikroservis olmaya hazır monolith uygulamalar geliştiriyoruz. Bu servislerden çoğu basit CRUD servisleri. Çünkü isterleri basit ve sadece clean architecture ve clean code prensiplerini takip ederek geliştirmek de oldukça efektif.

Bence her servisi ya da mikroservisi DDD’nin tüm prensiplerine bağlı kalmak zorunda bırakmamalıyız. Bunun yerine, fonksiyonal domain objeleriyle ve clean architecture prensipleri ile servisi geliştirmeyi tamamlayabiliriz. DDD kullanarak basitleştirmeye çalışmak günün sonunda daha da kompleks servisler ortaya çıkarabilir.

Perfosmansa ve Sürdürülebilirliğe Odaklanın

Performans

Yüksek trafik almaya hazır sistemler geliştirmek için en önemli şeylerden biri de performans odaklı olmaktır. Seçilen yazılım dilinin kendisi de daha fazla performans için yardımcı olabilir fakat yazılım dili seçimi hakkında düşünmeden önce düşünülmesi gereken konular var.

  • Performansı sağlamak için genel kabul görmüş iyi pratikler nelerdir?
  • Kullanılan programalama dili özelindeki iyi pratikler nelerdir?
  • Yapılan implemantasyon için hangi DB teknolojisi en uygunu?
  • Indexler ve DB sorguları.
  • CQRS’i servis seviyesinde uygulamak gerekir mi?
  • In-memory, distributed ya da response cache. Bunlardan hangileri mevcut duruma en uygun olanı? Birlikte kullanılmaları mümkün mü?
  • Servisin startup süresi. Saniyeler içinde scale olması gereken sistemler ya da serverless sistemler için önemlidir.

Sürdürülebilirlik

Her yeni proje başlangıcında kullanılması muhtemel yeni toollar ve teknolojiler bizi heyecanlandırır. Var olan projeyi sıfırdan yazmak düşünülüyorsa, bu hiç de kolay bir iş değildir. Olgun, hatalardan arınmış ve stabil bir uygulamayı çöpe atmak büyük bir maliyet getirir. Bunun yerine eldeki uygulamayı/mimariyi son teknolojiye adapte etme ve iyi pratikleri parça parça onun üzerinde uygulamaya odaklanın.

Yazılım mimarinizde her şeyi bir anda değiştirmekten kaçının!

Yeni bir başlangıç ya da değil, uygulamanın ve sistemin sürdürülebilir olduğundan emin olmak için birçok prensip ve teknik vardır.

Sürdürülebilir Kod

  • DRY, KISS, YAGNI, SOLID prensiplerinin rehberliğinde geliştirilmesi gerekir.
  • Şirket içinde oluşturulan kodlama standartlarını takip etmelidir.
  • Clean architecture gibi, iyi tanımlanmış, sürdürülebilir bir yaklaşım ile geliştirilmelidir.
  • Birim ve entegrasyon testleri ile desteklenmelidir.

Biz Çiçeksepeti’nde, bir yüzdeye erişmesi zorlanan birim testleri yerine mümkün olan en fazla durumu test etmeye odaklı entegrasyon testlerine daha çok önem veriyoruz. Yine de, birim testlerini de CI adımlarında çalıştırıyor ve başarılı olmasını bekliyoruz.

Sürdürülebilir Mimari

  • Teknoloji değişikliklerine kolayca uyum sağlayabilir.
  • Mikroservisler, bağımsız databaseler, izole edilmiş teknolojiler ve toollar gibi, birbirinden bağımsız parçalardan oluşur.
  • Güçlü bir loglama, monitor etme ve alarm verme yeteneği vardır.
  • Everything as Code prensibini takip eder.
  • Uygulama veya servisleri sık sık, sıfır kesinti ile deploy etmeye imkan verir.

Birbirinden bağımsız ve bir günde hatta bir saatte bile defalarca deploy olabilecek mikroservisler geliştiriyoruz. Deployment sayısı olarak ise herhangi bir üst limitimiz yok.

Polyglot Olun, Over Polyglot Değil

Kompleks sistemler inşa etmek, birçok farklı senaryo karşımıza çıkarır ve tek bir programlama dili kullanmak, sistemin yeteneklerini kısıtlayacaktır.

https://blog.lelonek.me

Bazı durumlarda, başka bir dil ile geliştirilmiş bir kütüphane, mevcutta kullandığımız dil ile geliştirilenden daha iyi olabilir. Dahası, bu kütüphane kullandığımız programlama dilinde hiç olmayabilir. Diğer yandan, servisler/uygulamalar için farklı bir programlama dili seçme sebepleri performans ve kaynak kullanımı da olabilir.

Mikroservisler, bağımsız olduklarından ve aralarındaki iletişim bir standart ile sağlandığından, herhangi birinin yeni bir programlama dili ile geliştirilmesine imkan verirler. Yine de, 3–4 programalama dilinden fazlası yarardan çok karmaşa getirecektir.

3–4 programlama dilinden fazlasını kullanmanın zorlukları:

  • Öğrenme süreci ve geliştirme hızı.
  • Her biri için kod seviyesindeki ve uygulama seviyesindeki standartları oturtmak.
  • Ortak kütüphaneleri hepsi için geliştirmek.
  • Her biri için build ve deployment adımlarını ayarlamak.
  • Her biri için deneyimli developer bulmak.

Programalama dili dikkatlice seçilmelidir. Denemek istemek yeterli değildir. Yapılmak isteneni, mevcutta kullandığınız programlama dilinden daha iyi yaptığına emin olun.

Biz, production ortamında backend servislerimiz için .NET, Golang, Node.js ve python kullanmayı tercih ettik.

Framework Geliştirmeyin, Küçük İşlevsel Kütüphaneler Geliştirin

Yeni bir projeye başlarken her zaman “Hadi yeni bir framework yazalım ve geliştiriciler tek satır bile kod yazmadan her şeyi implemente etmiş olsunlar!” diyen birileri vardır. Lütfen, bunu yapmayın.

Yeni bir framework(gibi) yazmaya çalışmaktan uzak durmak için bazı sebepler:

  • Herhangi bir kod değişimi tüm servislerde/uygulamalarda güncelleme ve deployment gerektirebilir.
  • Çok dilli ortamlarda aynı framework yapısını kullandığınız tüm yazılım dilleri için yapmak zorunda kalırsınız.
  • Bu yapıyı güncel tutmaya çalışmak da içinden çıkılamaz bir hale gelebilir.
  • İster istemez bazı şeylerin soyutlamasının soyutlamasını yapıyor olacaksınız ki bu da bir antipatterndir.
  • Diğer geliştiricilerin motivasyonu kötüleşecek.

Framework benzeri çözümler yerine, caching, monitoring, exception handling gibi cross-cutting concernler için dikkatlice dizayn edilmiş küçük işlevsel kütüphaneler ve bazı implemantasyonlar yapmayı düşünün.

Mikroservisler

Mikroservis tabanlı mimariler, mimari tasarımın yaygın bir uygulaması haline geldiler. En önemli getirisinden biri de yatay olarak ölçeklenebilmekteki yeteneğidir. Getirdiği ekstra kompleksitenin yanında, bağımsız konfigurasyonlar ve deployment yapabilme imkanı sunar. Caching, consistency ve networking gibi konularında da ekstra zorluklar getirir.

Tecrübelerimize göre, efektif bir mikroservis tabanlı mimari oluşturmak için bazı önemli noktalar:

  • Mikroservisleri olabildiğince saf tutun. Basit şeyler için kompleks çözümler geliştirmeye çalışmayın.
  • Kod tekrarı her zaman kötü değildir. Bazen, ekstra bağımlıklıklardan ve komplex yapılardan kurtarır.
  • Bir veya iki programlama dilini ana diller olarak seçin ve en fazla iki ya da üç programlama dilini çok özel isterler için kullanın.
  • Kod ve uygulama seviyesi standartlar belirleyin.
  • Her committe, birim ve entegrasyon testlerini koşturun. Bunları CDC ve performans testlerini de içerecek şekilde genişletin.
  • Databaseleri de böldüğünüzden ve bir domainden başka bir domainin databaseine erişmediğinizden emin olun.
  • Eventual consistencyden mümkün olduğunca uzak durun.
  • CI/CD adımlarında gerekli scriptler için ortak bir git reposu oluşturmayı düşünün.
  • Uygulamalarınızı/servislerinizi dockerize edin ve bir orchestration toolu ile birlikte host edin.
  • Push-based yerine, pull-based logging ve monitoring yaklaşımları geliştirin.
  • Takip edilebilirliği artırmak için APM ve service mesh çözümleri kullanmayı düşünün.

Geniş ölçekli veya çoklu geliştirme ekipleri için mikroservisler en iyi seçenek olabilir. Startuplar ve küçük takımlar için ise mikroservis olmaya hazır, modüler monolith yapılar inşa etmeyi düşünün.

BFFs

BFF servis yaklaşımını kullanıyoruz ve diğer servisleri private olarak bunların arkasında veya bazı proxy yapılarının arkasında tutuyoruz.

BFF servisler, single point of failure haline gelebilirler. Mobil ve web gibi her ön yüz için ayrı BFF servisleri yapıp farklı instancelarda host etmeyi düşünün. Daha da iyisi, bazı yoğun yük altındaki ve frontende göre değişimeyen durumlara özel, arka plandaki servislere proxyler veya service mesh yapıları ile path-based direkt erişim imkanı tanıyın.

BFFs & Path-based routing.

Database Tasarımı & CQRS

Doğru bir database tasarımı her zaman zor olmuştur. İlişkisel bir database seçmek genelde hızlı ve yeterli bir seçenek olabilir. Ancak, NoSQL, document-based, key-value store, ve event store gibi bu alanda diğer seçenekler de mevcut.

Commandlar ve queryler için databaseleri bölmek, bunlar için farklı trafik davranışları olan serivslerde uygun bir seçenek olarak düşünülebilir.

Biz Çiçeksepeti’nde ilişkisel database olarak MySQL kullanmayı tercih ettik. Her servis/uygulama kendi izole edilmiş database(ler)ine sahip ve sadece ait olduğu domain içerisinden erişilebilir. Bu yaklaşım, database tarafında daha kolay scale olabilen ve hataları tolere edebilen sistemler elde etmek için oldukça önemlidir.

Hem kod hem de database tarafında CQRS dizayn prensiplerini takip ediyoruz. MySQL, MSSQL, Elasticsearch, Redis, MongoDB ve S3 teknolojilerini sıklıkla kullanıyoruz.

Applying CQRS on the code level.

CQRS yaklaşımını sadece code seviyesinde uygulamak, hem command hem de query olarak bağımsız şekilde scale olma yeteneği getirmez ancak gerektiğinde kolayca query ve command olarak iki farklı servis konumlandırmanın yolunu açar.

Applying CQRS on the service and the database level.

Eventual Consistency & Outbox Pattern

Bir transactionı commit etmek monolith uygulamalar için basit bir görevdir. Fakat bir transaction, aynı anda birden fazla consumer servisi ilgilendirebilir. Mesela başarılı bir operasyon sonrasında kullanıcıya onay emaili atmak gibi. İşte bu gibi noktalar, eventual consistency sağlayacak şablonların implemente edilmesinin zorunlu olduğu yerlerdir.

Biz eventual consistency için, outbox pattern kullanan bir sistem dizayn ettik.

Outbox pattern implemantasyonu ile ilgili bazı ana noktalar:

  • Event gönderimlerinin transaction blokları içerisinde garanti edilebilmesi için outbox tablosu.
  • Bu tabloyu düzenli olarak kontrol edecek ve henüz gönderilmemiş eventleri gönderecek bir servis/job.
  • Transaction biter bitmez event gönderiminin de hiç beklenmeden denenmesi. Bu deneme hata alırsa zaten outbox tablosuna da yazıldığı için tekrar gönderimi denenecektir.
  • Hataları işlemek. Herhangi bir consumer içinde hata alınırsa, bu hataya dair eventlerin de yine geriye dönük olarak işleniyor olması.
Representation of outbox pattern with failure scenario.

Biz buna ek olarak, eventleri basit bit HTTP isteği ile gönderme ve alma için message brokerı soyutlayan bir servis geliştirdik. Bu yaklaşım event gönderme ve alma ile ilgili tüm kontrolü ele almamıza ve her serviste programlama diline özel SDK kullanmaktan ya da event gönderme/alma sürecini hepsinde implemente etmek gibi şeylerden kurtulamamızı sağladı.

Hataya Toleranslı Dağıtık Cache Mekanizması

Caching, uygulamanın ve tabii sistemin cross-cutting concernlerinden biridir. In-memory caching basit, güvenli(?), ve implemente etmesi nispeten kolaydır. Ancak dağıtık(distributed) caching ise network ile ilişkisinden ötürü in-memory cacheden çok daha karmaşıktır.

Distributed caching, stateless, scalable ve memory dostudur. Mikroservis tabanlı sistemler inşa ederken bu yeteneklere sahip olmak daha da değer kazanır.

Cache datası için network üzerinde daha az işlem yapmak ve cache sunucusunda bir problem olsa dahi sistemin ayakta kalmaya devam etmesini sağlamak için bazı önemli noktalar:

  • Cache server ile iletişime geçen kodu hatalara karşı toleranslı olacak şekilde geliştirmek.
  • Caching mekanizması çok hızlı çalışmalıdır. Networkdeki bir timeout kabus gibidir. Bir sorun halinde her seferinde timeout süresi sonuna kadar beklemediğinize emin olun.
  • Bir failover senaryosu kodlandığına emin olun. Distributed cache hata alırsa, direkt olarak data kaynağından datayı çekmeyi düşünün.
  • Network yükünü azaltmak için, kısıtlı sayıdaki bilgiyi, çok kısıtlı bir süre için in-memory olarak da tutmayı düşünün. Bu, çoğunlukla aynı data ile çalışan servisler için network yükünü önemli ölçüde azaltır.

Biz yukarıda bahsettiğim yaklaşımları backend servislerimizde distributed caching yaptığımız yerlerde kullanıyoruz.

Representation of the failure tolerant distributed caching.

Infrastructure

Hem AWS, hem GCP üzerinde aktif bir sistemimiz var ve şu an için AWS ana servis sağlayıcımız. Deployment yapabilme adına bir gün ya da bir saat özelinde dahi herhangi bir üst limitimiz yok. Oluşturduğumuz CI/CD yapısı, bir servisi yaklaşık 7 dakika içinde aşağıda bahsettiğim 4 farklı test aşamasından geçirerek deploy edebiliyor.

DevOps ve Cloud alanında da en iyi pratikleri takip etmeye çalışıyoruz. Bahsetmek istediğim bazı başlıkları aşağıda detaylandırdım.

Twelve-Factor App

Twelve-Factor App’in odaklandığı nokta, cloud ortamında servislerin konfigurasyonları, deploy edilmesi ve yönetilmesi konusunda temiz metodolojiler tanımlamaktır. 2012 yılında ortaya atılmış ve halen geçerliliğini korumaktadır.

Sırt çantamızda her zaman Twelve-Factor App bulunuyor ve sistemlerimizi buradaki prensiplere paralel şekilde geliştirmeye çalışıyoruz. Yine de bazı noktalarda ufak farklılıklar yapabiliyoruz.

CI/CD Scriptlerini Konumlandırmak

DevOps adımları her zaman bir şeyleri otomatikleştirecek ayarlara ve script dosyalarına ihtiyaç duyarlar. Tüm bu ayar ve dosyaları servisin kendi içerisinde tutmayı öneren bir pratik zaten var. Fakat bu ayar ve dosyalardan herhangi birini güncellemek gerektiğinde tüm servislerde bunu yapma gerekliliği doğabilecektir.

Biz bunları başka bir git reposu üzerinde konumlandırmayı tercih ediyoruz. Her build öncesinde ilgili repoyu da build ortamına çekip, build olacak servise göre ayarlayıp süreci devam ettiriyoruz.

Representation of dealing with scripts in CI environments.

CI Üzerinde Test Adımları

Otomasyon testleri, build sonunda elde edilen çıktının beklendiği gibi çalıştığına emin olmak için en önemli adımlardan biridir.

Bizim build sırasında ve sonrasında koşturduğumuz, tamemen izole 4 farklı test adımımız var.

  • Birim testleri. Önceden tanımlı bir coverage değerimiz yok. Yani, geliştirici hangi noktalarda birim testleri gerekli ise bunları yazmaktaki sorumluluğu alır, belirli bir yüzdeyi cover etmeye zorlamaz.
  • Entegrasyon testleri. Tüm gerçekleşebilecek senaryolara en yakınını test etmeye çalıştığımız, en değerli test adımı. Geliştirici ve test mühendisi bu adım için birlikte çalışırlar.
  • Servisler arası iletişimin halen sağlıklı olduğuna emin olmak için, CDC testleri.
  • Performans testleri. Sistem geneline yaptığımız yük testlerine göre daha basit olan bir test olarak düşünülebilir. Yine de, yapılan ilgili commitin herhangi bir noktada 5ms’den fazla bir yavaşlamaya neden olmadığını görmeye değer.

Tüm bu testlerin gerçek anlamda izole olarak koşturulduğunu söylemeliyim. DB veya başka bir servis çağrısı gibi tüm dış ihtiyaçlar test anında sıfırdan oluşturulur ve dış dünya ile herhangi bir bağlantısı olmaz.

Representation of testing steps on CI.

Sıfırdan izole bir ortam oluşturmak, build adımı dışına hatta test ortamına bile istek atmamak demektir. Database sıfırdan oluşturulur ve data migration o anda yapılır, dış API’ler tamamen mocklanır. Bu yaklaşım, testlerin her seferinde tutarlı bir sonuç vermesini sağlar.

Bunlarla birlikte kod kalitesini ölçmek ve güvenlik analizi yapmak için Sonarcube kullanıyoruz. Tüm testler ve Sonarcube analizi başarılı olarak geçmeli. Herhangi bir hata durumunda pipeline kırılır.

Servisleri Host Etmek

Servisleri host etmek için Kubernetes kullanmayı daha ilk sürümlerinden beri tercih ediyoruz. İlk zamanlar Mesos kullanmayı deneyip hızlıca vazgeçmiştik:). Servisleri highly available ve production ready olarak konumlandırma konusunda, Kubernetes cluster yönetimi ve konfigurasyonları açısından çokça deneyim kazanma şansımız oldu.

Deneyimlerimize göre, bazı püf noktaları şöyle sıralayabilirim:

  • Cluster genelinde bir hata durumunda kullanılmak üzere her zaman bir disaster recovery sernaryonuz olsun. Aynı clusterdan bir tane daha oluşturup, bunlardan birini 0 pod ile bekleyen ama gerektiğinde saniyeler içinde scale olacak şekilde konumlandırmayı düşünebilirsiniz.
  • Farklı davranışları ve kritiklik durumları farklı olan servisler için, farklı node poolları tanımlamayı düşünün.
  • Cluster auto-scaler ve pod auto-scaler ayarlayın. Bu noktada, pod kaynaklarını doğru ayarlamak daha da önem kazanıyor.
  • Özellikle büyük sistemlerde, Kubernetes tek başına yeterli olmuyor. Visibility, security ve çok daha fazlası için, bir service mesh ve/veya API gateway yapısı entegre etmek gerekiyor.
  • Kubernetes, service mesh ve benzeri yapılarla çözülebilecek problemleri kod tarafında çözmeyi bırakın. Circuit breaking, retry logic, service discovery, tracing, logging gibi örnekler verilebilir. Bunları kod tarafında halletmeye çalışmak, özellikle de dağıtık sistemlerde size daha fazla baş ağrısı olarak dönecektir. Servisleri olabildiğince saf tutun. Business odaklı olsunlar.

Biz Kubernetes üzerinde, en popüler service mesh çözümlerinden biri olan istio’yu kullanıyoruz. Bunun yanında, aşağıda da bahsettiğim logging, monitor toollarını ve pratiklerini de kullanıyoruz.

Logging ve Monitoring

Dağıtık sistemlerde visibility konusu diğer bir önemli konu. Logging ve monitoring yapılarını servislerden ve hatta programlama dillerinden tamamen izole bir şekilde konumlandırdık.

Logları servislerden log toplayıcılarına pushlamak yerine pull-based bir mekanizma tercih ettik.

Stdouta gönderilen tek satır JSON logları, log toplayıcılarına logları sunmak için standart haline geldi.

Kullandığımız teknoloji ve toollar ise loglama için Filebeat, Logstash, Loggly, ve monitoring tarafı için ise Prometheus, Grafana ve Instana APM olarak sıralanabilir.

Loglama yaklaşımı ile ilgili yazım için: https://medium.com/cstech/better-logging-approach-for-microservices-3cc2c45e7aaa

Kapanış

Tutarlı, günenilir, sürdürülebilir ve dayanıklı sistemler elde etmek için en iyi pratikleri ve en yeni teknolojileri kullanma konusunda her zaman heyecanlı ve istekli olduk.

Frontend, big data ve security konularında da bahsedilebilecek tonlarca şey var. Daha fazlasını cstech medium sayfamızda bulabilirsiniz.

Github sayfamızı ziyaret etmeyi unutmayın. Açık kaynak projelerimize yakında yenileri de eklenecek!

Okuduğunuz için teşekkürler.

Kaynaklar:

--

--