- Wafris, Rails middleware istemcisi sunan açık kaynaklı bir web uygulaması güvenlik duvarı şirketidir
- v1 istemcisi yerel bir Redis veri deposu gerektiriyordu, ancak v2'de SQLite kullanılıyor
- Redis'ten SQLite'a geçiş kararı alınmasının arka planını, performans değerlendirmelerini ve mimari değişiklikleri açıklıyor
TL;DR
- SQLite'ın iyi yaptığı ve iyi yapmadığı şeyler vardır
- Redis'in iyi yaptığı ve iyi yapmadığı şeyler vardır
- Geleneksel RDBMS'lerin (Postgres/MySQL) iyi yaptığı ve iyi yapmadığı şeyler vardır
- Bu veri depoları bire bir değiştirilemez; bunu yapmaya çalışırsanız sorun yaşarsınız
- Bu yazı, Redis tabanlı v1 istemcisinden SQLite tabanlı v2 istemcisine yeniden mimarileştirme sırasında yapılan testleri ve alınan kararları anlatıyor
Değişimi zorlayan etkenler
- Wafris'in hedefi, geliştiricilerin sitelerini kolayca koruyabilmesini sağlamaktır
- Redis dağıtım sorunları nedeniyle v1 bu hedefe tam olarak ulaşamadı
- Heroku gibi Redis'in kolayca kullanılabildiği ortamlarda çalışıldığı için Redis seçildi, ancak birçok kullanıcı Redis dağıtım sorunları yaşadı
- Kullanıcıları Redis gibi ayrı bir veritabanı kullanmaya zorlamak kullanıcı yararına değildir
"Hız" nedir?
- Redis, geleneksel RDBMS'lerden "daha hızlı"dır, ancak yine de bağlantı, bellek, süreç gibi şeylerin yönetilmesi gerekir
- Bulut ortamlarında ağ gecikmesi büyük bir sorun olabilir
- Gelen her HTTP isteğinde Wafris kurallarının değerlendirilmesi gerektiğinden, ağ gecikmesi uygulamayı yavaşlatabilir
Monolitimsi varsayım
- Tamamen dağıtık uygulamalar vardır, ancak çoğu Rails uygulaması bir "Majestic Monolith"tir
- Birden çok bölgeye dağıtılan, işlevleri çakışan sunuculara bölünen ya da yalnızca kısmen Rails olan uygulamalarda Redis kullanımı daha fazla sorun çıkarır
Mimarinin yeniden düşünülmesi
- Wafris, Rails middleware olarak kurulan bir web uygulaması güvenlik duvarıdır
- Basitçe iki aşamaya ayrılır: 1) HTTP isteğini kurallarla karşılaştırmak, 2) işleme sonucunu raporlamak
- Kural "okuma"sı (1. aşama), "yazma"dan (2. aşama) çok daha önemlidir
- Okumalar sıralı işlenmelidir, başarısız olmamalıdır ve kullanıcının hissettiği performansı etkiler
- Yazmalar daha yavaş, toplu ya da asenkron yapılabilir
SQLite sahnede
- SQLite'ın hangi kullanım alanlarına uygun olduğu başkaları tarafından iyi şekilde anlatılmıştır
- SQLite, istemci/sunucu veritabanlarıyla değil,
fopen() ile rekabet eder
- Ağ gidiş-dönüşlerini ortadan kaldırmanın onu Redis'ten çok daha hızlı yapması bekleniyordu
- SQLite ve Redis için benchmark değerlendirmesi yapmaya karar verildi
SQLite ve Redis benchmark'ı
- Benchmark, insanın kendini hassas sayılarla kandırdığı karanlık bir sanattır
- Veri depolarında benchmark yapmak daha da zordur
- Amaç mutlak hızı bulmak değil, kendi veri yapımıza ve kullanım senaryomuza özel bir benchmark oluşturmaktı
- Optimizasyon ayarları göz ardı edildi. Amaç, Wafris'in uygulamaya eklenir eklenmez çalışmasıydı
- Teorik benchmark'lar yerine uygulamanın kritik yolu ve en kötü sorguları test edildi
- En kötü sorgu, IP aralıklarını (IPv4, IPv6) kategorilere eşleyen karmaşık bir "lexical decimal" veri yapısı isteğidir
- Aralık sorguları önceden hesaplanıp SQLite tablolarına ve Redis sıralı kümelerine yazıldı
- Her gelen HTTP isteğinde, istek IP'si izin/ver engel özel aralıklar, GeoIP aralıkları ve IP itibar aralıklarıyla karşılaştırılmalıdır
Test protokolü
- Testler, M2 MacBook Air üzerinde Homebrew ile kurulu Redis ve yerel SQLite veritabanıyla yapıldı
- Mevcut aralık veri kümesi (1,2 milyon öğe) üzerinde test edildi
- Birden fazla IP kümesi, SQLite ve Redis üzerinde aynı sırayla çalıştırıldı
- Her çarpan için test 5 kez çalıştırıldı ve ortalaması alındı
Test sonuçları
- SQLite, Redis'i açık ara geçti (bizim özel kullanım senaryomuzda)
- SQLite, yerel Redis örneğinden yaklaşık 3 kat daha hızlıydı
- Bu sonuç, ağ gecikmesi hesaba katılmadan elde edildi
- SQLite, Redis'le sadece başa baş bile olsa ağ süresini ortadan kaldırdığı için yine avantaj sağlayacaktı
Grafikte olmayanlar
- SQLite performansı benchmark'ta 2 kat daha kötü olsa bile, pratikte ağ gecikmesi yüzünden yine daha hızlı olabilir
- Redis sunucusunu ne kadar güçlendirirseniz güçlendirin, ağ bant genişliği, bağlantılar ve bölgeler arası gecikme gibi sınırlar vardır
- SQLite ile neredeyse sınırsız yatay ölçekleme "ücretsiz" olarak elde edilebilir
- SQLite ile onboarding çok daha iyi hale gelir. Kullanıcılar muhtemelen kullanıldığını bile fark etmez
- Redis'ten daha fazla performans çıkarılabilirdi, ancak kullanıcıları Redis ayarlarını değiştirmeye ikna etmek zordu
Sonuç sadece başlangıç
- SQLite'ın Redis'ten daha hızlı olduğu gösterildi, ancak gerçek ödünleşimler vardır
- Yukarıdaki testlerde yazma işlemleri hesaba katılmadı
- Okuma ve yazma rekabetini yönetmek için veritabanı bağlantıları, bağlantı havuzu, transaction'lar vb. gerekir
- Tıpkı elektrikli bir süper otomobilin beton blok taşımaya uygun olmaması gibi, SQLite da uygun olmadığı rollerde kullanılmamalıdır
Senkronizasyon mimarisinin kurulması
- v1'de (Redis), kullanıcı Wafris Hub üzerinden kuralları güncellediğinde, Redis veri deposundaki kurallar da güncelleniyordu
- SQLite'ta web sunucusuna "push" yapılamadığı için bu yaklaşım çalışmıyor
- v2'de (SQLite): 1) kullanıcı Wafris Hub'da kuralları günceller, 2) istemci belirli aralıklarla güncellenmiş kuralları kontrol eder, 3) kurallar güncellenmişse tamamen yeni bir SQLite veritabanı indirilir
- Bu, kullanıcının kurulum ve yapılandırma sorumluluğunu büyük ölçüde azaltır
- v2 istemcisinin kurulum başarı oranı 3 kat arttı
SQLite'ın dağıtık mimarisi
- Otomatik ölçeklemenin etkin olduğu bir bulut sağlayıcısına dağıtılmış bir Rails uygulamasını düşünün
- İstekler 100 req/s'den 10.000 req/s'ye çıktığında, işlem örnekleri ölçeklenir ama veritabanı ölçeklenmez
- Bu, pratikte Rails uygulamalarının aşırı yük nedeniyle çökmesinin başlıca nedenidir
- SQLite veritabanını her işlem örneğine senkronize etmek, tüm çağrıları yerelde tutarak bu sorunu çözer
Peki ya yazmalar?
- Uygulama okuma (kural değerlendirme) ve yazma (raporlama) yollarına ayrıldı, ardından yazma yolu göz ardı edildi
- Yazma yolu şu şekilde yeniden tasarlandı: 1) Wafris Hub'a asenkron bağlanıp raporlama, 2) raporları toplu gönderme, 3) istemcide veritabanına yazmayı tamamen kaldırma
- Bu yaklaşım herkes için işe yaramayabilir, ancak bizim önemsediğimiz kullanıcılar yalnızca dağıtımı kolay ve hızlı bir Wafris istemcisi istiyor
Sonuç
- SQLite kullanan v2 mimarisinden çok memnunlar
- Şimdiden birçok sitenin saldırılara dayanmasına ve çevrimiçi kalmasına yardımcı oluyor
- Başlamak çok daha kolay hale geldi; bu da hem destek yükünü hem de kullanıcı zahmetini azalttı
- Bunun daha güvenli ve emniyetli bir internet için bir kazanım olduğunu düşünüyorlar
7 yorum
SQLite yeterince iyi ama, bu durumda sanki sadece Redis’e uygun olmayan bir kullanım senaryosuymuş gibi... geliyor bana.
Benchmark’in M2’de yapılmış olması biraz şey..
O zaman her bir AWS instance'ı için ayrı ayrı ölçüm mü yapmak gerekiyor? Açık kaynaktan beklentiniz biraz fazla gibi görünüyor.
Aynı sunucu ortamında yapılmış ama bu sorun olur mu?
Benchmark için belirli bir CPU mu kullanmak gerekiyor...?
M2 üzerinde yapılan şeyin hangi yönleri sorun yaratabilir? (Gerçek hizmet ortamının M2 işlemcisi olmaması dışında)
Sorun da bu zaten. Laboratuvarda deney yapıp, bunun ticari kullanım için mükemmel olduğunu iddia etmek!