Mikroservisler ile ilgili 7 başlıktan oluşan bu yazı dizisinde bir spring cloud mikroservis uygulamasını gerçekleştireceğim. Bu konuda temel düzeyde bilgi ve sıfır tecrübe ile başlayarak yazdığım hayali bir biletleme sitesi üzerinden nasıl gerçekleştirdiğimi anlatacağım. Günümüzde birçok kişinin üzerine birşeyler söylediği ve bloglarında parça parça yazdığı bu konuyu öğrenirken edindiğim tecrübeyi yazacağım. "Bu kod ile bunu yapabilirsiniz" şeklinde değil, bu ihtiyacımızı bu kod ile çözdük, bu sorunlarla karşılaştık ve bunları elde ettik şeklinde anlatacağım. Bu kararları ise bir domain üzerinden ilişkilendirerek "neden" sorularının da cevaplarının da oturmasını amaçlıyorum. İnternette teoriyi yazıya geçirme yolculuğunu anlatan bir yazı dizisi örneğine rastlamadım :) Yapacağım örnek mümkün olduğu kadar güncel teknolojileri kullanacak. Fakat bu sırada konuyu alakasız araçlarla karıştırmak istemiyorum. Sonuçta "SAGA orkestrasyonu" ile bir projeyi ayağa kaldırmış olacağız.
Konu mikroservisler olunca öncelikle birkaç soru önce çıkıyor: Neden mikroservis mimarisi uyguluyorsunuz, hangi ihtiyaçlara binaen? Nasıl mikroservis mimarisi uygulayacaksınız, belli bir patterne karar verdiniz mi? Hangi teknolojileri kullanacaksınız ve neden? Kullanılan araçların ve yapılan geliştirmelerin alternatifleri neler olabilir? Mikroservisler soyut kavramlardır. Kodlaması sırasında domain - teknoloji - ihtiyaçlar / beklentiler şeklinde 3 ana unsura göre şekillenmektedir. Bu yüzden yazı dizisinin planı şu şekilde:
En önemli adımı attık ve mikroservis mimarisi ile çalışan bir proje oluşturmaya karar verdik. Bu projenin oluşturulması sırasında mikroservis mimarisi ile ilgili düşüncelerimi de yazacağım. Bu şekilde bu konuda bilginiz olmasa bile konuya yabancı kalmadan takip edebileceksiniz. Başta söylediğim gibi soyut kavramlar üzerinden konuşmak ve bunu yazarsam bu işe yarıyor şeklinde açıklamak mikroservisleri anlamak ve uygulayabilmek için yeterli değil. Bu yüzden bir uygulama yazmaya karar verdik ve aldimbilet.com şeklinde bir web sitesi hayal ettik.
Peki aklımıza gelen her proje bir mikroservis yapısına çevirilebilir mi? Teknik olarak cevap evet. Nedir mikroservis: Büyük işleyişlerin ve akışların küçük katılımcılar ile gerçekleştirilmesidir. Küçük katılımcılar ise restful web servisler olur ve dağıtık yapıda tasarlanıp bağımsız çalışarak bir sistemi hantallıktan kurtarabilir. Bir ülke yönetiminin yerel yönetimler tarafından desteklenmesi gibi düşünebilirsiniz. Yani teknik olarak her ülkeyi küçük şehirlere bölmeniz mümkün fakat bu her zaman mantıklı mı? Tabi ki hayır. Tek elden yönetilmesi ve hantallığı sorun olmaya başladığında bir proje mikroservis mimarisine dönüşmeye aday hale gelmektedir.
Normalde bir programlama dilinde esas işi yapan sınıflar veya kodlar yardımcı kodlarla veya kütüphanelerle desteklenmektedir. Bu mantığın aynısını web servisler aracılığı ile iletişim kurulan bir yapıya dönüştürerek mikroservis mimarimizi uygulamaya koyabiliriz. Elimizde hazır bir monolith uygulama olmadığı için domain 'i inceleyerek başlayalım. Örnek projemiz içinde kullanıcıları ve etkinlikleri olan bir bilet kesme uygulaması olacak. Bu projede kullanıcı girişi yapılması, etkinlik seçilmesi ve bilet alınması öngörülüyor. Yapacağımız uygulama tam teşekküllü bir bilet uygulaması olmayacak çünkü maksadımız mimari üzerinde kafa yormak ve teknik detayları öğrenmek. Bu yüzden demo ekranlarımız ve basit veritabanlarımız olacak. Merak etmeyin, yazı dizisinin sonunda projeyi bütün servisleri ile beraber siz de ayağa kaldırabileceksiniz. Sonrasında isterseniz kendi girişiminiz için kullanabilirsiniz tabi :)
Peki o zaman ne istediğimizi biliyoruz. Kullanıcılar, etkinlikler ve ödemeler gibi 3 adet ana işlevi yerine getirmek istiyoruz. Burada fark ettiyseniz işlev bazlı bir yaklaşım yapıyoruz. Yani sistemi işlevlere göre modelliyoruz. Mikroservis tasarımlarında oluşturacağınız mimariyi farklı hedefleri gözeterek oluşturabilirsiniz. Bizim sistemimiz bu 3 fonksiyonu subdomain olarak kabul edecek ve her birisi için bir servis ayağa kaldıracak. Bir bakıma kullanıcılardan veya etkinliklerden sorumlu devlet bakanı gibi. Tasarımı bu şekilde yapmamızın bir sebebi de bir e-ticaret uygulaması kadar yoğun giriş çıkış ve anlık işlem beklemememiz. Bir biletleme uygulamasında 1 saatlik bir gecikme bile yaşansa hayati bir önem taşımayabilir. Bu yüzden sistemimizin çok ağır yük altında çalışmak zorunda kalmayacağını varsayıyoruz bu noktada. Aksi türlü olsa idi ne olurdu veya farklı yaklaşımlarla domain 'i bölümlendirebilir miydik gibi sorular serinin 7. ve son yazısında olacak.
Çok yoğun çalışan bir sistem olmasa bile minik servislerimiz bizim sistemimizi ayakta tutacak ve sistemin güvenilir ve tutarlı çalışmasını sağlayacak. Nedir güvenilirlik ve tutarlılık: Örneğin bizim uygulamamız spamlara izin vermemek adına rezervasyon veya koltuk seçimi yapmaya izin vermesin. Sistem bilet için ödeme yapılması sırasında kalan koltuk yada kişi sayısını kontrol ederek satışı gerçekleştirsin. Buradaki hayali isteğimiz mikroserviste veri tutarlılığı adına bir gereksinim çıkarmak ve bunu karşılamak. Bu sürece Saga ismi veriliyor. Bunu bir olaylar zinciri gibi düşünebilirsiniz. Zincir koptuğunda sistemin kendini onarabilmesi de gerekecektir. Örneğin yer kalmadığı için ödeme yapılıp bilet kesilemezse para iadesi gibi. Bu da burada not olarak dursun.
Şu anda elimizde 2 karar var. 3 adet minik servisimiz olacak ve bunları merkezi bir koordinatör yada orkestratör ile yöneteceğiz. Bu kararları almak işin ilk kısmı idi. Domain 'i inceledik ve isteklerimizi, kısıtlarımızı ve hedeflerimizi belirledik. Normalde yazılım mühendisliğinde izlenmesi gereken süreci işletmiş olduk. Tabi bu noktada mikroservisler ile ilgili deneyiminiz yoksa herşey havada kalacaktır. Yani tamam kullanıcı girecek etkinlik seçecek ve bilet alacak diye mi mikroservis mimarisine geçiyoruz diye düşünebilirsiniz. Burada işin ödünleşim kısmı geliyor. Yukarıda dediğim gibi her uygulama için mikroservis yapmak mantıklı olmayacaktır. Bizim sebeplerimiz şunlar:
Bunlar gibi sorunlarınız varsa eğer, siz de yavaş yavaş mikroservis yazmalı mıyız diye düşünmeye başlayabilirsiniz. Biz şu anda isterlerimizi belirledik, potansiyel risklerimizi gördük ve bunlara mikroservis mimarisinin çözüm olabileceğine karar verdik. Bu noktada elinizdeki yazılım geliştiricileri bu işe yatkın değilse veya şirket kültürünüz hantal ise 2 kere düşünmenizde fayda olacaktır. Bizim bir proje yazmayı kafaya koymuş kişiler olarak böyle bir kaygımız yok :)
Bu noktada mikroservisler üzerinde kafa yormak adına şöyle bir soru sorabilirim. Şehirlerden oluşan bir ülkeyi tekrar düşünün. Merkezi bir yönetimle bu şehirler yönetiliyor ve şehirler de kendi içlerinde bir takım işleri yönetiyor. Elimizde merkezi bir yönetim olmasa olmaz mıydı? Yani mikroservis mimarisi merkezde bir network hub gibi işleticisi bulunan ve küçük servisleri konuşturan bir yapı mıdır sadece? Aslında hayır. Benim gördüğüm kadarıyla 2 ana yaklaşımımız bulunuyor. Birincisi koordinatör ile üst düzey bir aracının servisleri gereğine göre harekete geçirmesi. İkincisi ise servislerin işini bitirdikten sonra sıradaki diğer servise mesaj paslaması. Şehirler arası bağlantılarla bu şehirlerin yönetilmesi gibi biraz. Biz bu durumda ilk yaklaşımı seçtik. Çünkü sistemimizde hayata geçecek olan iş kuralları fazla karmaşık değil ve sistemimiz aşırı yük altında çalışmayacak gibi görünüyor. Tabi ki bu kararlarımızdan ileride pişman olabiliriz eğer hedeflerimiz net değilse. Bu yazı dizisinde hedefimiz değişmeyeceğine göre bu konuda da sorun yok :) Ama işe başlamadan önce baştaki soruları kendinize mutlaka sorun. Gerek var mı? Varsa ne kadar ve nasıl?
Tekrar bir özet. Evet bu yazı çok soyut ama merak etmeyin teknik kısımlar bir sonraki yazıdan başlayacak. Şu anda "neden mikroservis yapalım ki" sorusunu sorduk ve kendimizden cevap aldık. Kendi kendimize konuşma konusunda biz yazılımcıların üstüne yoktur zaten. "Nasıl yapalım" diye düşündük ve bir orkestrayı yöneten şef gibi küçük işlev parçacıklarını yönetmeye karar verdik. Ne elde etmeyi istediğimizi biliyoruz, belli bir scope içerisinde esnek ve güvenilir bir yapı oluşturmak istiyoruz. Sürecin en önemli aşamalarının bunlar olduğunun bir kere daha altını çizeyim. Şimdi sıra geldi teknolojilere. Bu isterleri, kısıtları ve hedefleri göz önünde bulundurarak belli teknolojiler kullanmamız ve kodlamaya başlamamız lazım.
İyi de ben yazılımcıyım. Yani bir yerlere db statement kodları yazacağım. Bir yerlerde if 'ler else 'ler yazacağım günün sonunda. Bu kodları şimdi gökten zembille gelmiş gibi nereye yazacağımı nereden bileceğim? Gidip bir proje oluşturup dümdüz yazmaya mı başlayacağım? Servis oluşturmak için ne yapmam lazım? Saga ne? (Doğudaki ağızlarda bu "sanane" diye anlaşılmasın :) Merkezi sistem minik servisleri nasıl bilecek. Network programlaması falan mı yapacağız? 3 küçük proje oluşturursam olacak mı bu iş? Şu anda bunun gibi sorular soruyor olmalısınız eğer mikroservisler konusunda tecrübeniz yoksa.
Bu kısım teoride anlaşılabilen kavramların pratiğe ve koda dönüşmesi kısmı. Beni en çok zorlayan da bu oldu. Çünkü teknik olarak mikroservisler ile ilgili araçlar veya teknolojilerle ilgili teorik bilgim vardı fakat uygulamaya geçirme konusunda bilgim yoktu. Kim neyi nasıl yapıyor bilemiyordum ve kimseden de öğrenemiyordum. Bu yüzden mimariye karar verirken bazı hatalar yaptım ve zamanla değiştirmek zorunda kaldım. Örneğin küçük servislerin bir mesaj altyapısı olmadan gateway üzerinden süreçleri ilerletmesinin doğru olacağını düşünmüştüm. Ayrıca message queue tabanlı bir yaklaşımla merkezi yaklaşım arasında çok büyük farklar olduğunu bilmiyordum. Siz şu anda hazır mimari üzerinden ilerleyeceksiniz fakat ben yaptığım hataları aralarda bu şekilde yazacağım. Benzer sıkıntıları sizler de yaşamış veya yaşayacak olabilirsiniz.
Aşağıdaki resimde kurguladğım mimariyi basit bir şekilde ifade ettim. Fakat bu resim sadece kafanızda büyük resimin oturması için. Bunu gibi internette onlarca farklı yapıda çizim bulabilirsiniz. Ben de buldum ama kod yazmaya yardımcı olmadı. Kodlar aradım buldum ama onlar da sistemin bütününe uymadı. Ben de oturup kendim yazdım diyebilirim. Buyurun mimarimiz:
Neyin ne ifade ettiğini anlamasanız da şimdilik sorun değil. Bir sonraki yazıda bu resmi inceleyerek bunu gerçekleştirebilmemizi sağlayan spring cloud teknolojilerinden bahsedeceğim zaten. Bundan sonraki her yazının başında da bu resmi bulacaksınız. Çünkü günün sonunda bu resimdeki yapıyı kodlara dönüştürebilirsek yukarıdaki isterler, kısıtlar ve amaçlar gerçekleşmiş olacak. Bir sonraki teknik yazıda görüşmek üzere :)
Bir yorum yazabilirsiniz