.png)
Bir ürünü sıfırdan geliştirmenin en büyük zorluklarından biri geliştirme ve barındırma (hosting) maliyetleridir. Yeni bir ürün, ilk etapta gelir üretmez. Buna rağmen, yüksek trafikle karşılaşıldığında dahi sistemin yanıt verebilir kalmasını sağlayacak güvenilir ve dayanıklı bir mimari tasarlamamız gerekir. Bu da bizi bir paradoksla karşı karşıya bırakır:
Bu nedenle pek çok startup, yatırım ve fon bulma konusunda yoğun bir arayışa girer. Ancak bu durum başka bir problemi de beraberinde getirir. Büyük bir trafiği karşılayabilmek için güçlü bir sunucu kiralamış veya satın almış olsak bile, bir ya da iki yıl içinde trafik bu sunucunun kapasitesini aşabilir. Bu noktada ya sunucuyu değiştirmemiz ya da yeni bir sunucu ekleyip kodumuzu çoklu sunucu yapısına uygun hâle getirmemiz gerekir.
Bu problemi çözmek için farklı yaklaşımlar mevcuttur. En yaygın çözümlerden biri, kiralanan sunucular (AWS tarafında EC2) için Auto Scaling Group’lar kurmaktır. AWS CloudWatch gibi izleme servisleri, CPU veya ağ yüküne bağlı olarak sunucu sayısını artırıp azaltır.
Auto Scaling Group’lar iyi bir çözüm olabilir; ancak sonuçta hâlâ yönetilmesi gereken sunucu kümeleridir (işletim sistemi bakımı vb.). Ayrıca canlı ortamda güncelleme yapmak da karmaşıktır. Örneğin, sunucuların neredeyse tamamı güncellenmişken son sunucuda güncelleme başarısız olursa ne yaparsınız? Tüm güncellemeleri geri mi alırsınız? Tüm sunucuları kapatıp güncelleme yapamazsınız; çünkü bu durumda uygulamanız tamamen offline olur.
Elbette Blue-Green deployment gibi yöntemlerle bu sorunlar aşılabilir; ancak bu yöntemler hem karmaşık hem de nispeten yavaştır. Auto Scaling Group’lar güçlü ve faydalı yapılardır; fakat genellikle gerçekten sunucuya ihtiyaç duyulan durumlarda tercih edilmelidir: geliştirme ortamları, bazı Big Data uygulamaları veya legacy sistemleri ölçeklenebilir hâle getirmek gibi.
Bu noktada serverless servislerin parladığını düşünüyoruz.
AWS Lambda, e-posta gönderme, küçük SQL sorguları çalıştırma gibi hafif iş yükleri için tasarlanmış bir container servisidir. Temel olarak kodunuzu yazarsınız ve AWS bu kodu sizin yerinize bir yerde çalıştırır. Bir web uygulamasının backend omurgasını oluşturmak için oldukça uygundur. Web sunucusu AWS Amplify üzerinde barındırılabilir ve backend ile yapılan tüm etkileşimler AWS Lambda üzerinden gerçekleşebilir.
Ancak AWS Lambda’nın da bazı dezavantajları vardır. Bunlardan en önemlileri:
Bir Lambda fonksiyonu çağrıldığında AWS, fonksiyonun çalışacağı bir container ayağa kaldırır. Bu işlem bir saniyeye kadar sürebilir. Fonksiyon “warm” hâle geldiğinde sonraki çağrılar çok daha hızlıdır. Ancak bir süre çağrılmayan fonksiyon “cold” olur ve yeniden çağrıldığında daha uzun sürede başlar. Bu etkiyi azaltmak için yüksek trafik beklenen zamanlarda fonksiyonları önceden tetiklemek gibi yöntemler kullanılabilir.
Ayrıca Lambda, hafif işler için tasarlanmıştır; bu nedenle kullanılabilecek kütüphane boyutu, kod boyutu ve RAM gibi sınırlamalar vardır.
Bu nedenle genellikle hafif arka plan işleri için Lambda, daha ağır hesaplamalar için ise Docker tabanlı container servisleri (ör. AWS ECS) kullanmak iyi bir yaklaşımdır.
Mixit, çok amaçlı bir optimizasyon aracıdır. Farklı ürünlere ait kimyasal özellikleri (kaynak ürünler) ve hedef ürün listesini girdi olarak alır. Kullanıcıya, kaynak ürünlerin hangi oranlarda karıştırılması gerektiğini gösteren bir karışım matrisi hesaplar. Böylece hedef ürünlere mümkün olduğunca yakın sonuçlar elde edilir. Aynı zamanda ürün fiyatları ve hacimleri de hesaba katılabilir.
Yukarıda da belirttiğimiz gibi serverless teknolojilerin güçlü bir savunucusuyuz ve bu nedenle uygulama backend’inde Lambda kullanmayı tercih ettik. Geliştirme sürecinde aldığımız bazı mimari kararları aşağıda özetliyoruz:
Operasyonel verilerin yapısı sabit değildir (bir projede 10 ürün varken başka bir projede 7 olabilir; kimyasal özellikler de benzer şekilde değişkendir). Bu nedenle NoSQL bir veritabanı tercih ettik. AWS DynamoDB, JSON formatında veri saklaması, neredeyse sınırsız ölçeklenebilmesi ve yönetilen bir servis olması sayesinde bu ihtiyaç için idealdi.
Müşteri verileri ise oldukça yapısal olduğundan, bu veriler için AWS RDS PostgreSQL kullandık.
Frontend ile backend arasındaki iletişim için bir REST API oluşturduk. API’deki her bir metod, bir Lambda fonksiyonuna bağlıdır. Bu fonksiyonlar temel veritabanı sorgularını gerçekleştirir, AWS Cognito ile yetkilendirme entegrasyonunu sağlar ve sistemin büyük bölümünü yönetir.
Optimizasyon süreci ise Lambda için fazla ağırdır. Bu nedenle optimizasyon motorunu bir Docker image hâline getirdik. Bir optimizasyon isteği geldiğinde, ilgili Lambda fonksiyonu bu image’ı AWS ECR Fargate (AWS’in serverless container servisi) üzerinde çalıştırır.