Mikroservis mimarisi bağımsız dağıtılabilirlik, teknoloji esnekliği ve ekip özerkliği vaat eder. Ancak pratikte, kötü uygulanmış mikroservisler iyi yapılandırılmış bir monolit'ten daha kötü olabilir. Innoware'de birden fazla mikroservis tabanlı platform geliştirdikten sonra, doğal karmaşıklığı yönetirken avantajları yakalayan pragmatik bir yaklaşım geliştirdik.
Her zaman sorduğumuz ilk soru şudur: "Bu projenin gerçekten mikroservislere ihtiyacı var mı?" Küçük ekiplere sahip erken aşama ürünler için modüler bir monolit genellikle daha iyi bir seçimdir. Mikroservisler, bağımsız ölçeklemeye ihtiyaç duyduğunuzda, birden fazla ekip paralel çalıştığında veya sistemin farklı bölümleri için farklı teknoloji yığınlarına ihtiyaç duyduğunuzda mantıklıdır.
Servis Sınırları
Mikroservislerde en kritik karar sınırları nereye çizeceğinizdir. Yanlış belirlerseniz, bir monolitte harcayacağınızdan daha fazla zamanı servisler arasında koordinasyona harcarsınız. Doğal olarak servis sınırlarına eşlenen sınırlı bağlamları belirlemek için domain-driven design kullanıyoruz.
Sınırlı bağlam, belirli bir modelin geçerli olduğu iş alanının bir parçasıdır. Örneğin bir sağlık platformunda, "Hasta" randevulama (uygunluk, tercihler, geçmiş) ile faturalandırmada (sigorta, ödeme yöntemleri, ödenmemiş bakiye) farklı şeyler ifade eder. Bunlar iki sınırlı bağlamdır ve iki servis olmalıdır.
Ayrıca "ekip sahipliği" sezgiselini uygulıyoruz: tek bir ekip bir servisin tüm yaşam döngüsüne (geliştirme, test, dağıtım, izleme) sahip olabiliyorsa, sınır muhtemelen doğrudur.
İletişim Kalıpları
Senkron ve asenkron iletişimin bir kombinasyonunu kullanıyoruz ve her etkileşim için doğru kalıbı seçmek kritiktir. Senkron iletişim (tip güvenliği ve performansı nedeniyle servisler arası çağrılar için REST yerine gRPC'yi tercih ediyoruz) çağıranın anında yanıta ihtiyaç duyduğu durumlar için uygundur. Örneğin, bir kullanıcının kimlik doğrulama token'ını doğrulamak.
Mesaj kuyrukları aracılığıyla asenkron iletişim (görev kuyrukları için RabbitMQ ve olay akışı için Kafka kullanıyoruz) diğer her şey için uygundur. Sipariş oluşturulduğunda, sipariş servisinin e-postanın gönderilmesini veya analitiğin kaydedilmesini beklemesine gerek yoktur.
Güvenilir olay yayınlama sağlamak için Outbox Pattern uyguluyoruz. Olayları doğrudan mesaj aracısına yayınlamak yerine (bu başarısız olabilir ve sistemi tutarsız durumda bırakabilir), olayları iş operasyonuyla aynı veritabanı işleminde bir outbox tablosuna yazıyoruz. Ayrı bir süreç outbox'ı okur ve olayları aracıya yayınlar.
Veri Yönetimi
Her servis kendi veri deposuna sahiptir. Bu tartışılmaz. Servisler arasında veritabanı paylaşmak, mikroservislerin tüm amacını baltalayan bağımlılık oluşturur. Esas olarak işlemsel veriler için PostgreSQL (JSONB desteği çoğu kullanım durumu için yeterince esnek kılar) ve önbellekleme, hız sınırlama ve oturum yönetimi için Redis kullanıyoruz.
Servisler arası sorgular için ayrılmış okuma modelleri ile CQRS kalıbını kullanıyoruz. Ürün kataloğu servisi "ÜrünGüncellendi" olayı yayınladığında, arama servisi Elasticsearch dizinini günceller ve öneri servisi grafik veritabanını günceller.
Gözlemlenebilirlik
Dağıtık bir sistemde gözlemlenebilirlik olması güzel olan bir şey değildir, hayatta kalma gereksinimidir. Bir istek başarısız olduğunda, kök nedeni bulmak için potansiyel olarak düzinelerce servis boyunca izlemeniz gerekir.
Serilog ile yapılandırılmış günlükleme, her günlük girişinin bir korelasyon ID'si, servis adı ve ilgili iş bağlamını içermesini sağlar. OpenTelemetry ile dağıtık izleme, istekleri servis sınırları boyunca takip eder. Prometheus ve Grafana panolarıyla metrikler, istek oranları, hata oranları, gecikme yüzdelikleri ve kaynak kullanımı dahil sistem sağlığına gerçek zamanlı görünürlük sağlar.
Dağıtım
Tüm servislerimiz Docker ile konteynerleştirilmiş ve Kubernetes ile orkestre edilmiştir. CI/CD pipeline'ımız (Jenkins) her servisin 10 dakikadan kısa sürede bağımsız olarak derlenebilmesini, test edilebilmesini ve dağıtılabilmesini sağlar. Sıfır kesinti süreli sürümler için sağlık kontrolleriyle birlikte kademeli dağıtımlar ve dağıtım sonrası sağlık kontrolleri başarısız olursa otomatik geri alma kullanıyoruz.
