12 Punkte von xguru 2024-09-26 | 7 Kommentare | Auf WhatsApp teilen
  • Wafris ist ein Open-Source-Unternehmen für Web Application Firewalls, das einen Rails-Middleware-Client anbietet
  • Der v1-Client benötigte einen lokalen Redis-Datenspeicher, in v2 wird jedoch SQLite verwendet
  • Erklärt den Hintergrund der Entscheidung zur Migration von Redis zu SQLite, Performance-Überlegungen und Änderungen an der Architektur

TL;DR

  • SQLite hat Dinge, die es gut kann, und Dinge, die es nicht gut kann
  • Redis hat Dinge, die es gut kann, und Dinge, die es nicht gut kann
  • Traditionelle RDBMS (Postgres/MySQL) haben Dinge, die sie gut können, und Dinge, die sie nicht gut können
  • Diese Datenspeicher sind nicht direkt austauschbar, und wenn man es versucht, bekommt man Probleme
  • Dieser Artikel beschreibt den Test- und Entscheidungsprozess beim Re-Architecting des Redis-basierten v1-Clients zum SQLite-basierten v2-Client

Faktoren, die die Änderung erzwangen

  • Das Ziel von Wafris ist es, es Entwicklern leicht zu machen, ihre Websites zu schützen
  • Wegen Problemen bei der Redis-Bereitstellung erreichte v1 dieses Ziel nicht vollständig
  • Redis wurde gewählt, weil in Umgebungen wie Heroku damit leicht gearbeitet werden konnte, doch viele Nutzer hatten Probleme bei der Bereitstellung von Redis
  • Nutzer zur Verwendung einer separaten Datenbank wie Redis zu zwingen, ist nicht nutzerfreundlich

Was ist „Geschwindigkeit“?

  • Redis ist „schneller“ als traditionelle RDBMS, aber Verbindungen, Speicher, Prozesse usw. müssen dennoch verwaltet werden
  • In Cloud-Umgebungen kann Netzwerklatenz ein großes Problem sein
  • Da Wafris-Regeln bei jeder eingehenden HTTP-Anfrage ausgewertet werden müssen, kann Netzwerklatenz die Anwendung verlangsamen

Die Annahme eines Monolithen (Monolith-ish)

  • Es gibt vollständig verteilte Anwendungen, aber die meisten Rails-Apps sind „Majestic Monoliths“
  • Apps, die über mehrere Regionen bereitgestellt werden, in Server mit überlappenden Funktionen aufgeteilt sind oder nur teilweise Rails verwenden, verursachen bei Redis-Nutzung noch mehr Probleme

Architektur neu denken

  • Wafris ist eine Web Application Firewall, die als Rails-Middleware installiert wird
  • Vereinfacht in zwei Schritte aufgeteilt: 1) HTTP-Anfragen mit Regeln vergleichen und 2) das Verarbeitungsergebnis melden
  • Das „Lesen“ der Regeln (Schritt 1) ist deutlich wichtiger als das „Schreiben“ (Schritt 2)
  • Lesezugriffe müssen sequenziell verarbeitet werden, dürfen nicht fehlschlagen und beeinflussen die wahrgenommene Performance der Nutzer
  • Schreibzugriffe können langsamer, gebündelt oder asynchron erfolgen

Enter SQLite

  • Andere haben bereits gut erklärt, wofür SQLite geeignet ist
  • SQLite konkurriert nicht mit Client/Server-Datenbanken, sondern mit fopen()
  • Es wurde erwartet, dass es durch den Wegfall der Netzwerk-Roundtrips deutlich schneller als Redis sein würde
  • Es wurde entschieden, SQLite und Redis per Benchmark zu vergleichen

Benchmarking von SQLite und Redis

  • Benchmarking ist eine dunkle Kunst, mit präzisen Zahlen sich selbst zu täuschen
  • Benchmarking von Datenspeichern ist noch schwieriger
  • Ziel war nicht, eine absolute Geschwindigkeit zu finden, sondern einen Benchmark zu erstellen, der auf unsere Daten und unseren Use Case zugeschnitten ist
  • Optimierungs-Tweaks wurden ignoriert. Wafris soll einfach in eine App eingebaut werden und sofort funktionieren
  • Es wurden nicht theoretische Benchmarks, sondern die Hot Paths der App und die schlimmste Query getestet
  • Die schlimmste Query ist eine komplexe Anfrage an eine „lexical decimal“-Datenstruktur, die IP-Bereiche (IPv4, IPv6) auf Kategorien abbildet
  • Bereichsabfragen wurden vorab berechnet und in SQLite-Tabellen sowie Redis Sorted Sets geschrieben
  • Bei jeder eingehenden HTTP-Anfrage muss die Anfragen-IP mit benutzerdefinierten Allow-/Block-Bereichen, GeoIP-Bereichen und IP-Reputationsbereichen verglichen werden

Testprotokoll

  • Getestet wurde auf einem M2 MacBook Air mit per Homebrew installiertem Redis und einer lokalen SQLite-Datenbank
  • Es wurde mit dem bestehenden Bereichs-Datensatz (1,2 Millionen Einträge) getestet
  • Mehrere IP-Sets wurden in derselben Reihenfolge gegen SQLite und Redis ausgeführt
  • Für jedes Vielfache wurde der Test fünfmal ausgeführt und der Durchschnitt gebildet

Testergebnisse

  • SQLite schlug Redis deutlich (in unserem speziellen Use Case)
  • SQLite war etwa 3× schneller als eine lokale Redis-Instanz
  • Das ist das Ergebnis noch vor Berücksichtigung der Netzwerklatenz
  • Selbst wenn SQLite nur gleich schnell wie Redis wäre, wäre der Wegfall der Netzwerkzeit bereits ein Vorteil

Was im Diagramm fehlt

  • Selbst wenn die SQLite-Performance im Benchmark doppelt so schlecht wäre, könnte sie in der Praxis wegen der Netzwerklatenz immer noch schneller sein
  • Egal wie leistungsfähig der Redis-Server ist, es gibt Grenzen bei Netzwerkbandbreite, Verbindungen usw. sowie Latenz zwischen Regionen
  • Mit SQLite ist nahezu unbegrenztes horizontales Scaling „kostenlos“ möglich
  • Das Onboarding wird mit SQLite deutlich besser. Nutzer merken womöglich gar nicht, dass es verwendet wird
  • Aus Redis ließe sich mehr Performance herausholen, aber es war schwer, Nutzer von Änderungen an ihrer Redis-Konfiguration zu überzeugen

Das Ergebnis ist erst der Anfang

  • Es wurde zwar bewiesen, dass SQLite schneller ist als Redis, aber es gibt reale Trade-offs
  • Die obigen Tests berücksichtigen keine Schreibvorgänge
  • Um Konkurrenz zwischen Lesen und Schreiben zu verwalten, braucht es Datenbankverbindungen, Connection Pooling, Transaktionen usw.
  • So wie ein elektrischer Supersportwagen schlecht dazu geeignet ist, Betonblöcke zu transportieren, sollte SQLite nicht für ungeeignete Aufgaben eingesetzt werden

Aufbau einer Synchronisierungsarchitektur

  • In v1 (Redis) wurden beim Aktualisieren von Regeln im Wafris Hub auch die Regeln im Redis-Datenspeicher aktualisiert
  • Mit SQLite funktioniert das nicht, weil nicht auf den Webserver „gepusht“ werden kann
  • In v2 (SQLite): 1) Der Nutzer aktualisiert Regeln im Wafris Hub 2) der Client prüft in festen Intervallen auf aktualisierte Regeln 3) wenn Regeln aktualisiert wurden, wird eine vollständig neue SQLite-Datenbank heruntergeladen
  • Dadurch sinkt die Verantwortung der Nutzer für Installation und Konfiguration erheblich
  • Die Erfolgsquote bei der Installation des v2-Clients stieg um das Dreifache

Verteilte Architektur mit SQLite

  • Betrachten wir eine Rails-App, die bei einem Cloud-Anbieter mit aktiviertem Auto-Scaling bereitgestellt wird
  • Steigen die Anfragen von 100 req/s auf 10.000 req/s, werden die Compute-Instanzen skaliert, die Datenbank jedoch nicht
  • Das ist in der Praxis ein Hauptgrund dafür, dass Rails-Apps wegen Überlastung ausfallen
  • Durch die Synchronisierung der SQLite-Datenbank auf jede Compute-Instanz lässt sich dieses Problem lösen, weil alle Aufrufe lokal bleiben

Was ist mit Schreibvorgängen?

  • Die App wurde in Lese- (Regelauswertung) und Schreibpfade (Reporting) aufgeteilt, danach wurde der Schreibpfad ignoriert
  • Der Schreibpfad wurde neu entworfen als 1) asynchrone Verbindung zum Wafris Hub zum Melden 2) gebündelte Übertragung von Reports 3) vollständige Entfernung von Datenbank-Schreibvorgängen aus dem Client
  • Das funktioniert vielleicht nicht für andere, aber uns interessieren nur Nutzer, die einen leicht bereitzustellenden und schnellen Wafris-Client wollen

Fazit

  • Mit der v2-Architektur auf Basis von SQLite ist man sehr zufrieden
  • Sie hilft bereits vielen Websites, Angriffe zu überstehen und online zu bleiben
  • Der Einstieg ist deutlich einfacher geworden, wodurch sowohl der Support-Aufwand als auch der Aufwand für die Nutzer sinken
  • Das ist ein Gewinn für ein sichereres und besser geschütztes Internet

7 Kommentare

 
aer0700 2024-09-26

SQLite ist zwar gut genug, aber in diesem Fall wirkte es irgendwie eher so, als wäre es einfach kein für Redis geeigneter Use Case gewesen …

 
kandk 2024-09-26

Dass die Benchmarks auf einem M2 durchgeführt wurden, ist schon etwas ...

 
colossus 2024-09-29

Muss man das dann für jede AWS-Instanz einzeln messen? Sie erwarten wirklich sehr viel von Open Source.

 
toru123 2024-09-27

Wurde das in derselben Serverumgebung durchgeführt – ist das problematisch?
Muss man für Benchmarks eine bestimmte CPU verwenden...?

 
superwoou 2024-09-26

Welche Probleme könnten bei dem auf dem M2 durchgeführten Test auftreten? (Abgesehen davon, dass die reale Service-Umgebung keinen M2-Prozessor verwendet)

 
kandk 2024-09-26

Genau das ist das Problem: im Labor experimentieren und dann behaupten, das sei perfekt für den kommerziellen Einsatz!

 
[Dieser Kommentar wurde ausgeblendet.]