1 puan yazan GN⁺ 2024-09-26 | 1 yorum | WhatsApp'ta paylaş
  • Wafris, Rails middleware istemcisi v1’de kullanıcıya ait Redis deposunu v2’de SQLite tabanlı depolama ile değiştirerek hem dağıtım zorluğunu hem de istek değerlendirme gecikmesini azaltmayı hedefliyor
  • Başlangıçtaki Redis tercihi, Heroku ve Sidekiq gibi Rails ekosistemindeki alışkanlıklardan etkilenmişti; ancak gerçek operasyonlarda kullanıcıların Redis yöneticisi rolünü de üstlenmesi sorunu büyüdü
  • Tüm gelen HTTP isteklerini kurallarla karşılaştıran okuma yolu temel darboğaz; raporlama amaçlı yazmalar ise daha yavaş işlenebilir ya da toplu/asenkron biçimde ayrıştırılabilir
  • Yerel bir MacBook Air M2’de 1,2 milyon aralık içeren veri kümesiyle en kötü durum IP aralığı sorgusu test edildiğinde SQLite, yerel Redis’ten yaklaşık 3 kat daha hızlı performans gösterdi; ağ gecikmesi buna dahil değil
  • v2, belirli bir süreye veya istek sayısına göre yeni kuralları kontrol edip ardından yeni SQLite DB’nin tamamını indiren bir senkronizasyon yapısı kullanıyor; başarılı kurulumlar yaklaşık 3 kat arttı

Redis tabanlı v1’de ortaya çıkan dağıtım sürtünmesi

  • Wafris, açık kaynaklı bir web uygulaması güvenlik duvarı şirketi olarak Rails uygulamalarına bağlanan bir middleware istemcisi sunuyor
  • v1 istemcisi, uygulamayla birlikte dağıtılan kullanıcıya ait bir Redis deposu gerektiriyordu
  • İlk Redis seçiminde Heroku’da Redis’i kolayca ekleyebilme ortamı, uzaktan erişim kolaylığı ve Sidekiq gibi başarılı örnekler etkili oldu
  • Gerçek kullanıcı ortamları daha çeşitliydi ve birçok kullanıcı Redis dağıtımı ve yapılandırma sorunlarını ayıklamakta zorlandı
  • RailsWorld 2023 sırasında da Rails uygulamasının yanında bir Redis sunucusunun doğal olarak gerekli olduğu varsayımına karşı olumsuz bir hava vardı

Hız sorununun özü ağ gecikmesi

  • Redis, geleneksel RDBMS’lerle karşılaştırıldığında hızlıdır; ancak ayrı bir veritabanı olduğu için bağlantı, bellek ve süreç yönetimi gerektirir
  • Bulut ortamlarında ağ gecikmesi, istek işleme performansını doğrudan etkiler
    • Wafris, uygulamaya gelen her HTTP isteğini kayıtlı kurallarla karşılaştırmak zorundadır
    • v1 istemcisi ne kadar hızlı yapılırsa yapılsın, uygulamanın konuşlandığı ağ yavaşsa toplam yanıt süresi yavaşlayabiliyordu
  • Rails uygulamaları da her zaman tekil bir “majestic monolith” biçiminde dağıtılmıyordu
    • Birden fazla zona dağıtılan uygulamalar
    • Sorumlulukları çakışan birden fazla sunucuya bölünmüş uygulamalar
    • Yalnızca bir kısmı Rails olan, başka diller veya framework’lerle birlikte dağıtılan uygulamalar
  • Bu tür operasyonel ortamlarda Redis kullanımındaki sürtünme daha da arttı

Wafris istek işlemede okuma ve yazmayı ayırma

  • Wafris, Rails middleware olarak kurulur; “IP 1.2.3.4’ü engelle” gibi kurallar ayarlandıktan sonra gelen istekler bu kurallarla karşılaştırılır
  • Basitleştirilmiş işlem akışı iki adımdan oluşur
    1. HTTP isteğini kurallarla karşılaştır; eşleşirse 403, eşleşmezse 200 işle
    2. Engelleme, izin verme, geçirme gibi işlem sonuçlarını raporla
  • İlk adım olan kural okuma, raporlama yazmasından çok daha önemlidir
    • İstekler sıralı olarak işlenmelidir
    • Filtreleme çalışmazsa kötü istekler geçebilir
    • İstek değerlendirmesi, kullanıcının hissettiği site performansını etkiler
    • Raporlama yazması daha yavaş, toplu halde ve asenkron işlenebilir

SQLite’ın seçilme nedeni

  • Wafris’in ana darboğazı ağ I/O’suydu ve SQLite dokümantasyonundaki “SQLite, istemci/sunucu veritabanlarıyla rekabet etmez. SQLite, fopen() ile rekabet eder” cümlesi bu tercihi etkiledi
  • Sadece ağ gidiş-dönüşlerini ortadan kaldırmanın bile Redis tabanlı yapıdan daha hızlı olabileceği varsayımıyla SQLite ve Redis benchmark’a tabi tutuldu
  • Başvurulan kaynaklar şunlardı

Benchmark kapsamı ve bilinçli sınırlamalar

  • Benchmark, genel bir veritabanı performans karşılaştırması değil; Wafris’in hot path’ini ve en kötü durum sorgusunu hedefleyen taraflı bir testti
  • En kötü durum sorgusu, IP aralıklarıyla kategorileri eşleyen “lexical decimal” veri yapısı üzerinde yapılan sorguydu
    • Basit bir örnek olarak, bir IP adresinin iki adres arasındaki aralıkta olup olmadığını kontrol edip ülkeyi döndüren IP → ülke eşlemesi verilebilir
    • Bu yapı milyonlarca satır ölçeğindedir ve IPv6’da her öğe büyüktür
  • Aralık sorguları önceden hesaplandıktan sonra iki depoya yazıldı
  • Patolojik durumda her gelen HTTP isteği, istek IP’sini şu aralıklarla karşılaştırmak zorundadır
    1. Kullanıcı tanımlı izin aralıkları
    2. Kullanıcı tanımlı engelleme aralıkları
    3. GeoIP aralıkları
    4. IP itibar aralıkları
  • Bu sorgu türü yeterince önemli olduğu için diğer sorgular veya özellikler taşınmadan yalnızca bu tek tür test edildi

Test yöntemi ve sonuçlar

  • Testler, Homebrew ile kurulmuş Redis ve yerel SQLite DB kullanılarak yerel bir MacBook Air M2 üzerinde yapıldı
  • Protokol şöyleydi
    1. Mevcut 1,2 milyon öğelik aralık veri kümesini kullan
    2. Birden fazla IP kümesini aynı sırayla SQLite ve Redis üzerinde çalıştır
    3. Her çarpan için testi 5 kez çalıştır ve ortalamayı kullan
  • Wafris’in belirli kullanım örneğinde SQLite, yerel Redis’ten yaklaşık 3 kat daha hızlı performans gösterdi
  • Bu sonuçlar ağ gecikmesi hesaba katılmadan önceki değerlerdir
  • Testler bilinçli olarak basit bir kurulumu ve gerçek kullanımın kusurlarını yansıtacak şekilde tasarlandı; genel bir veritabanı karşılaştırmasına genellemek zordur

Grafikte görünmeyen operasyonel farklar

  • SQLite performansı benchmark’ta Redis’ten belirgin biçimde kötü olsaydı bile, aynı veri merkezindeki veya bölgedeki Redis’e olan ağ gecikmesi nedeniyle gerçek ortamda daha hızlı olabileceği değerlendirildi
  • Redis sunucusu cluster veya sharding ile sağlam yapılandırılsa bile ağ bant genişliği, bağlantı sayısı ve bölgeler arası gecikme gibi sınırlamalar kalır
  • SQLite her compute instance’ında yerel olarak bulunduğu için Wafris’in bu kullanım örneğinde yatay ölçekleme maliyeti neredeyse ortadan kalkar
  • Onboarding de SQLite tarafında daha basittir
    • Kullanıcı, SQLite kullanıldığını bilmeden bile gem’i web uygulamasına ekleyip çalıştırabilir
  • Redis tarafında da ek optimizasyon için çok alan vardır; ancak Wafris, kullanıcılara cache eviction politikası gibi temel ayar değişikliklerini bile tutarlı biçimde kabul ettirmekte zorlanıyordu

SQLite’a geçişten sonra gereken mimari değişiklikler

  • Redis tabanlı v1’in güncelleme akışı basitti
    1. Kullanıcı Wafris Hub’da kuralları günceller
    2. Wafris Hub, kullanıcının Redis deposundaki kuralları günceller
  • SQLite’ta Wafris Hub, SQLite veritabanını web sunucusuna doğrudan “push” edemiyordu
  • Bazı SQLite as a service sağlayıcıları benzer bir yöntemi mümkün kılsa da maliyet, performans ve güvenlik nedenleriyle Wafris’e uygun değildi
    • Bunu her kullanıcının ayrı ayrı dağıtması gerekir
    • Port açılması gerekir
    • Gelen bağlantılara izin verilmesi gerekir
  • SQLite tabanlı v2’nin güncelleme akışı şöyledir
    1. Kullanıcı Wafris Hub’da kuralları günceller
    2. İstemci, zamana veya istek sayısına dayalı belirli aralıklarla güncellenmiş kuralları kontrol eder
    3. Kurallar değiştiyse istemci tamamen yeni bir SQLite veritabanı indirir
  • Bu yapı, kullanıcı tarafındaki kurulum ve yapılandırma sorumluluğunu büyük ölçüde azalttı; v2 istemcisinin başarılı kurulumları yaklaşık 3 kat arttı

Dağıtık dağıtımlarda SQLite yapısı

  • AWS, Heroku, Fly gibi bulut ortamlarında Rails uygulaması autoscaling yaptığında compute instance’ları artar; ancak çoğu zaman veritabanı birlikte artmaz
  • İstekler 100 req/s’den 10.000 req/s’ye çıktığında dyno, machine, EC2 instance’ları ayağa kalkar; fakat veritabanı darboğazı aynı kalabilir
  • Wafris’in gözlemlediği Rails uygulama arızalarının başlıca nedeni, gerçek DDoS’tan çok credential stuffing veya kötü bot trafiğiydi
    • Bu tür trafik autoscaling’i tetikler
    • Ardından veritabanı bağlantıları tükenir ve uygulama çökebilir
  • SQLite DB her compute instance’ına senkronize edildiğinde, yeni instance’taki tüm çağrılar yerel tutulabilir

Yazma yolu istemciden kaldırıldı

  • Önceki testler yazma işlemlerini dikkate almadı ve SQLite’ın her role uygun olduğunu da varsaymıyor
  • Wafris, SQLite’ı okuma ağırlıklı role uygun şekilde kullanıp yazma yolunu ayrıca yeniden tasarladı
  • v2’nin raporlama yolu şöyle değişti
    • Wafris Hub’a asenkron bağlanıp raporla
    • Raporlama verilerini toplu gönder
    • İstemcide veritabanı yazmalarını tamamen kaldır
  • Bu yapı diğer hizmetlerin çoğu için uygun olmayabilir; ancak Wafris kullanıcılarının istediği kolay dağıtım ve hızlı istemci hedefleriyle uyumludur
  • SQLite tabanlı v2 mimarisi şimdiden birçok sitenin saldırılara dayanıp çevrim içi kalmasına yardımcı oldu; ayrıca Wafris’in destek işlerini ve kullanıcıların yaşadığı sürtünmeyi azalttı

1 yorum

 
GN⁺ 2024-09-26
Hacker News yorumları
  • Her uygulama sunucusunun SQLite veritabanı dosyasının bir kopyasına sahip olduğu ve bunu belirli aralıklarla bütünüyle değiştirdiği model gerçekten ilginç.
    Burada web uygulaması güvenlik duvarı kuralları için kullanılıyor, ama feature flag ayarları için de çok uygun olur gibi. Feature flag'ler istek başına onlarca kez kontrol edilebilir ve çoğu zaman “kullanıcı A grubunda ve IP'si B ülkesinde” gibi sorgular gerekir; yerel SQLite bunu iyi karşılayabilir. Feature flag güncellemelerinin birkaç saniye, hatta daha uzun süre gecikmeyle yayılması genelde kabul edilebilir.

    • Bu yöntem CDN'lerde de kullanılan bir model. Tüm müşterilerin sertifikalarını, HTTP yönlendirme kurallarını vb. içeren küresel yapılandırma dosyası tek dosyalık bir B-tree yapısı olarak güncellenir, sonra bu “bundle” sık sık tüm edge konumlarına dağıtılır.
      Ancak bu amaçla SQLite kullanılan bir örnek henüz görmedim; genelde LMDB veya Kyoto Cabinet gibi DBM tarzı veritabanları kullanılıyor.
    • Airbnb de bu modeli çeviri, feature flag, yapılandırma, arama indeksi gibi şeyleri dağıtmak için kullandı. SQLite yerine Spotify'ın yaptığı anahtar-değer dosya biçimi Sparkey kullanıldı.
      Başlarda her sunucudaki Cron işi ilgili servisin verilerini çekiyordu; Kubernetes'e geçildikten sonra ise DaemonSet ve host etiketleme/taints benzeri bir yaklaşımla çeşitli veriler her host'a indirildi, ardından bu verileri kullanan servisin yalnızca ilgili host'ta çalışması garanti edildi. Ruby tarafında buna “hammerspace” deniyordu: https://github.com/airbnb/hammerspace
    • Feature flag değerlerini istek başına birkaç kez sorgulama sorunu, flag değerini yalnızca bir kez alıp istek nesnesine kaydetme yöntemiyle çözülür.
      Böylece tek bir istekte pahalı sorgulama maliyetini birden fazla kez ödemezsiniz ve istek işlenirken flag güncellenip değerin tutarsız hale gelmesi riski de olmaz.
    • Uzun bir migration sürecinde feature flag'lerle uzun süre uğraştıktan sonra, gerçekten kullanışlı temel yapı taşının “SQLite, ama her değişiklikte küresel sürüm sayacı artıyor ve yalnızca sürüm numaraları arasındaki değişiklikler alınabiliyor veya uygulanabiliyor” şeklinde olduğuna ikna oldum.
      Bunun üzerine gossip ağı ya da açıkça tanımlanmış ağaç biçimli cache/dağıtım ağı gibi çeşitli dağıtım mekanizmaları koyabilirsiniz. Daha yeni sürüme sahip olan herhangi biri güncellemeyi verebilir.
      Mevcut DB sürümünü uygulama çıktısına dahil edip, uygulama çalıştıktan sonra verimli şekilde güncelleyebilirsiniz. Feature flag veya canlı yapılandırmada, kod seviyesindeki varsayılanlar yerine yakın tarihli duruma fallback yapılabilir.
      Herhangi bir istemci küresel sayacı ETAG gibi gönderip yalnızca değişiklikleri alabilir; kısa süreli ağ kesintisinden sonra yeniden bağlanmak da basit ve ucuz hale gelir.
      Birkaç dakikalık geçmiş tutulabiliyorsa, W3C Baggage header'ı gibi bir yöntemle mikroservis çağrılarına sayaç eklenebilir ve birden fazla serviste flag/yapılandırma/veriler aynı sürüm numarası temelinde değerlendirilebilir. Zamana göre değerlendirme özelliği olmasa bile üretim numarasını log'lara yazmak, sonradan debug için çok yardımcı olur.
    • Dağıtım için SQLite harika. Bu fikir bir ölçüde Datasette projesinden esinlenmiş gibi görünüyor ve ileride raporlama ile veri keşfi tarafında hâlâ yapılabilecek bir şeyler olabilir.
  • Ağ gecikmesinin dışında, Redis'te okuma/yazma gecikmesinin sorgulanan anahtar sayısıyla neredeyse doğrusal orantılı olma eğiliminde olduğunu gördüm; yazıdaki grafik de buna benzer görünüyor.
    Monolitik bir uygulamada Postgres ve Redis'i kullanım amaçlarına göre birlikte kullandığımızda oldukça iyi çalışıyordu, ama yeni özellikleri paylaşılan Redis cluster'ına itmek fazla kolaydı. Redis tek thread'li olduğu için, 100 bin+ anahtarı topluca sorgulayan düşüncesiz tek bir özellik diğer özellikleri de yavaşlatabilir.
    Bu yüzden Redis'in bir seferde tek bir anahtar ya da küçük ve sabit sayıda anahtar okunup yazıldığında, örneğin popüler endpoint'lerde lock veya rate limiting gibi birçok rastgele özelliğin Redis kullandığı durumlarda özellikle iyi olduğu yönünde bir kılavuz önermiştim.
    Bu durumda Redis basit tek anahtarlı (IP adresi) sorgularda parlayacaktır, ancak aralık sorgusu ifadeleri gibi daha karmaşık okumalara pek uygun görünmüyor. Yerel Redis'e kıyasla SQLite'ın neden bu kadar iyi çalıştığını derinlemesine bilmiyorum; bu yüzden beklenmedik ve ilginç geldi.

    • Redis, insanların artılarını ve eksilerini kolayca yanlış anlayabildiği için çoğu zaman bir tuzak haline geliyordu.
      Redis'i, daha zengin temel operasyonlara sahip bir cache olarak görmek en iyisi. Doğru kullanıldığında hızlı ve güvenilirdir.
      Ama temel RDBMS'e pek uymayan şeyleri Redis'e koymaya başladığınızda kısa sürede iş kuyrukları, çeşitli lock türleri vb. ortaya çıkar; eninde sonunda performansın uçurumdan düşmesi ya da başka bir nedenle sistemin çökmesi an meselesi olur. Kurtarma süreci genellikle dağınık hale gelir ve çoğu zaman bir miktar veri kaybını kabullenmekle sonuçlanır.
      Bu akış küçük adımlarla kolayca gerçekleştiğinden, kaçınmak için disiplin gerekir. SQLite performansı yalnızca ağ overhead'inden kaçınmaktan ibaret değil; birçok kişinin serileştirme/deserileştirme maliyetini hafife alması da büyük etken. Redis protokolü oldukça minimal olsa bile maliyetler birikir; SQLite'ta ise pek çok işlem süreç içi bellek kopyalamaya indirgenir.
  • Birkaç hafta önce Neon içindeki hackathon'da Redis'in wire protocol'ü olan RESP'yi Postgres sorgularına çeviren küçük bir Node.js sunucusu yaptım.
    Çok eğlenceli bir hack projesiydi: https://github.com/btholt/redis-to-postgres

  • Veritabanının salt okunur olması nedeniyle replikasyon gerektirmeyen sunucu tarafı SQLite için oldukça uygun, özel bir kullanım durumu gibi geliyor.
    Başka bir alternatif statik dosyaları belleğe almak olabilir, ama bu durumda veriler bellekte sürekli tutulamayacak kadar fazla olduğundan SQLite iyi bir alternatif gibi görünüyor.

    • Yazıda aktarılmış olmasını umarım, ama bu belirli bir kullanım durumuna çok iyi uyan harika bir çözüm; Redis veya Postgres'in 1:1 ikamesi değil.
    • Statik dosyaları belleğe alma yaklaşımından başlayıp, genel kullanım durumlarında çalışması için gereken özellikleri yeterince eklediğinizde sonunda SQLite gibi bir ilişkisel veritabanına ulaşırsınız.
      Fark şu ki SQLite çok sağlam, performanslı ve olağanüstü iyi test edilmiş durumda.
  • RailsWorld 2023’te Redis için “kan kokusunu aldıkları” yönünde bir hava olduğuna dair kısım merak uyandırıcı
    Kariyerimde prodüksiyonda yalnızca bir Rails uygulamasıyla çalıştım ve o uygulama Redis kullanıyordu; bu yüzden güncel eğilimleri pek bilmiyorum. Ekosistemin iş perspektifinden Redis’e sırtını mı döndüğünü, bunun lisans değişikliği yüzünden mi olduğunu, yoksa YAGNI’ye daha yakın bir durum mu olduğunu merak ediyorum
    O dönemde Rescue ile birlikte indeks oluşturma, transcoding gibi asenkron işleri zamanlamak için kullanıyorduk; o zamanlar gayet iyi bir araç gibi görünüyordu

    • Biraz YAGNI’ye yakın. Rails topluluğunda Redis’in çok kullanılmasının en büyük nedeni asenkron işlerdi ve çoğu kişinin seçtiği araç Sidekiq oldu
      2024 Rails topluluğu anketinde de Redis hâlâ uygulamalarda en çok kullanılan veri deposu olarak görünüyor
      Ancak birçok uygulama Redis kullansa da pratikte bunu yalnızca Sidekiq benzeri amaçlarla kullanıyor; gerçek zamanlı liderlik tabloları ya da vektör DB özellikleri gibi alanlarda kullanmıyor. Bu yüzden gerçek kullanım deseni biraz bulanık
    • Bence tamamen basitlik meselesi
      Bugün belirli bir trafiği olan bir Rails kurulumunda genellikle frontend sunucusu, SQL DB, anahtar-değer deposu (Redis veya Memcached) ve bu anahtar-değer deposunu işaret eden bir cache deposu bulunuyor. Ama API kotası ya da hız sınırı tutmak gibi genel anahtar-değer kullanımları ile cache kullanım desenleri oldukça farklı olduğundan bu zahmetli hale geliyor
      Disk performansı yeterince hızlandı, SQL performansı da iyileşti; bu yüzden anahtar-değer deposunu kaldırıp geleneksel anahtar-değer amaçlarını SQL DB’ye, cache backend’ini ise diske ayırma yönünde bir hareket var. Yeni NVMe diskler RAM’e neredeyse yaklaşacak kadar hızlı, üstelik çok daha ucuz; bu yüzden daha fazla cache tutmak mümkün
    • Redis geçmişte, süre bitimi gibi özellikleri yerleşik olan çok akıllı bir paylaşımlı bellek gibi faydalıydı. Clustering ile birden çok makine arasında paylaşım da mümkündü
      Ama Kubernetes ve Redis-as-a-service çağında bu “paylaşımlı bellek” başka bir rack’teki başka bir VM’de duruyor. O noktaya gelindiğinde zaten kaynak verimliliğinden vazgeçilmiş oluyor; bence dosyayı S3’ten okuyup yazmak daha iyi
    • Günümüz SSD’leri hızlı olduğu için daha fazla insan RocksDB kullanmalı. SSD üzerinde çok daha büyük anahtar-değer depoları çalıştırılabilir
  • “Redis geleneksel RDBMS’lere göre hızlıdır, ancak yine de bağlantı, bellek, process vb. yönetilmesi gereken bir veritabanı olduğu için stack’i daha kırılgan hale getirir” kısmına gelince; oyuncak seviyesini aşan transaction’larla uğraşmaya başladığınızda, ilişkisel olsun ya da olmasın tüm veritabanlarının aşağı yukarı benzer düzeyde yönetim ve bakım gerektirdiğini düşünüyorum
    “Hızlıdır” kısmı da biraz ilginç. Join’leri dert etmiyorsanız satır ekleme ve sorgulama da oldukça hızlıdır

    • SQLite’ın sunucu ortamında istisnai derecede hızlı olmasının nedeni, sorgu yapmak veya veri almak için ağ çağrısı gerektirmemesidir
      Yerel diskten doğrudan okuduğunu anladığınızda, join ya da transaction tartışmaları çok anlamlı olmaktan çıkıyor. Zaten başlı başına birkaç büyüklük mertebesi daha hızlı bir yol
    • SQLite’ta bir tür garbage collection gibi görünen VACUUM işlemi var
      VACUUM’un ne zaman çalıştırılması gerektiğine dair dokümanları her okuduğumda kafam karışıyor. Son SQLite tabanlı uygulama dağıtımımda basitçe bir sayaç tutmuş, çok sayıda yazma işleminden sonra VACUUM çalıştıracak şekilde çözmüştüm
    • “Tüm veritabanları aşağı yukarı aynı düzeyde yönetim ve bakım gerektirir” ifadesine katılmıyorum
      Bağımsız bir sunucu process’i çalıştırılması gereken veritabanlarında yönetim ve bakım eforu kaçınılmaz olarak farklılaşır. Uç bir örnek olarak, SQLite ile Oracle kullanmanın gerçekten hiçbir farkı olmadığına inanmak zor
  • Redis’i SQLite ile Go’da yeniden uygulayan Redka ilginizi çekebilir: https://github.com/nalgeon/redka

    • Geçişi düşünecek kadar ilginçti, ancak “benchmark’lara göre Redka, Redis’ten birkaç kat daha yavaş” kısmını görünce tereddüt ettim
      Harika bir proje olduğu doğru, ama bu düzeyde geçiş için neredeyse hiç teşvik yok
  • Redis kullanım şeklinin doğru olup olmadığını teyit etmek istiyorum
    v1’de WAF ile Redis aynı sunucuda mıydı; istemci yönetim panelinde yeni bir kural ayarladığında bu kural yönetim paneliyle aynı sunucudaki Redis’e giriyor, Redis’in dahili senkronizasyon mekanizması sayesinde dünyanın dört bir yanındaki WAF’ların yanındaki yerel Redis’lere kural güncelleniyor muydu? Ardından yeni bir istek herhangi bir WAF’a geldiğinde WAF’ın, güncellenmiş Redis kurallarıyla isteği/IP’yi doğruladığı akış bu muydu, teyit etmek istiyorum
    v2’de ise Redis cluster’ı kaldırılıp, tüm WAF sunucularında SQLite DB bulunduğu, yönetim panelinden her WAF+SQLite sunucusuna yeni kuralları dağıtan ayrı bir senkronizasyon mekanizması oluşturulduğu ve yeni istek geldiğinde WAF’ın güncellenmiş SQLite kurallarıyla hızlıca doğrulama yaptığı yapı mı var, merak ediyorum

  • En iyi cümle şu: “SQLite, istemci/sunucu veritabanlarıyla rekabet etmez. SQLite, fopen() ile rekabet eder