Jenseits des Browsers: Erste Schritte mit serverlosem WebAssembly

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Sie haben wahrscheinlich schon von WebAssembly gehört und warum es ein leistungsstarkes Tool im Browser ist. In diesem Artikel untersuchen wir, warum serverloses WebAssembly außerhalb des Browsers genauso leistungsfähig sein könnte, und wie Sie damit beginnen können.

Jetzt, da WebAssembly von allen gängigen Browsern und mehr als 85 % der Benutzer weltweit unterstützt wird, ist JavaScript nicht mehr die einzige Browsersprache in der Stadt. Falls Sie es noch nicht gehört haben: WebAssembly ist eine neue Low-Level-Sprache, die im Browser ausgeführt wird. Es ist auch ein Kompilierungsziel, was bedeutet, dass Sie vorhandene Programme, die in Sprachen wie C, C++ und Rust geschrieben wurden, in WebAssembly kompilieren und diese Programme im Browser ausführen können. Bisher wurde WebAssembly verwendet, um alle Arten von Anwendungen ins Web zu portieren, einschließlich Desktop-Anwendungen, Befehlszeilentools, Spiele und Data-Science-Tools.

Hinweis: Eine ausführliche Fallstudie darüber, wie WebAssembly im Browser verwendet werden kann, um Webanwendungen zu beschleunigen, finden Sie in meinem vorherigen Artikel.

WebAssembly außerhalb des Webs?

Obwohl die meisten WebAssembly-Anwendungen heute browserzentriert sind, wurde WebAssembly selbst ursprünglich nicht nur für das Web entwickelt, sondern wirklich für jede Sandbox-Umgebung. Tatsächlich gab es in letzter Zeit großes Interesse daran, zu untersuchen, wie WebAssembly außerhalb des Browsers als allgemeiner Ansatz zum Ausführen von Binärdateien auf jedem Betriebssystem oder jeder Computerarchitektur nützlich sein könnte, solange es eine WebAssembly-Laufzeitumgebung gibt, die dieses System unterstützt. In diesem Artikel sehen wir uns an, wie WebAssembly außerhalb des Browsers serverlos/Function-as-a-Service (FaaS) ausgeführt werden kann.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

WebAssembly für serverlose Anwendungen

Kurz gesagt, serverlose Funktionen sind ein Computermodell, bei dem Sie Ihren Code an einen Cloud-Anbieter übergeben und ihn ausführen und die Skalierung dieses Codes für Sie verwalten lassen. Sie können beispielsweise verlangen, dass Ihre serverlose Funktion immer dann ausgeführt wird, wenn Sie einen API-Endpunkt aufrufen, oder dass sie von Ereignissen gesteuert wird, z. B. wenn eine Datei in Ihren Cloud-Bucket hochgeladen wird. Während der Begriff „serverlos“ wie eine Fehlbezeichnung erscheinen mag, da Server eindeutig irgendwo auf dem Weg beteiligt sind, ist es aus unserer Sicht serverlos, da wir uns keine Gedanken darüber machen müssen, wie diese Server verwaltet, bereitgestellt oder skaliert werden.

Obwohl diese Funktionen normalerweise in Sprachen wie Python und JavaScript (Node.js) geschrieben sind, gibt es eine Reihe von Gründen, warum Sie sich stattdessen für die Verwendung von WebAssembly entscheiden könnten:

  1. Schnellere Initialisierungszeiten
    Serverlose Anbieter, die WebAssembly unterstützen (einschließlich Cloudflare und Fastly, berichten, dass sie Funktionen mindestens eine Größenordnung schneller starten können als die meisten Cloud-Anbieter mit anderen Sprachen. Sie erreichen dies, indem sie Zehntausende von WebAssembly-Modulen im selben Prozess ausführen, das heißt möglich, da die Sandbox-Natur von WebAssembly eine effizientere Möglichkeit bietet, die Isolierung zu erreichen, für die Container traditionell verwendet werden.
  2. Keine Umschreibungen erforderlich
    Einer der Hauptvorteile von WebAssembly im Browser ist die Möglichkeit, bestehenden Code ins Web zu portieren, ohne alles in JavaScript umschreiben zu müssen. Dieser Vorteil gilt auch im serverlosen Anwendungsfall, da Cloud-Anbieter einschränken, in welchen Sprachen Sie Ihre serverlosen Funktionen schreiben können. Normalerweise unterstützen sie Python, Node.js und vielleicht einige andere, aber sicherlich nicht C, C++ oder Rust . Durch die Unterstützung von WebAssembly können serverlose Anbieter indirekt viel mehr Sprachen unterstützen.
  3. Leichter
    Wenn wir WebAssembly im Browser ausführen, verlassen wir uns auf den Computer des Endbenutzers, um unsere Berechnungen durchzuführen. Wenn diese Berechnungen zu intensiv sind, werden unsere Benutzer nicht glücklich sein, wenn ihr Computerlüfter zu surren beginnt. Das Ausführen von WebAssembly außerhalb des Browsers bietet uns die Geschwindigkeits- und Portabilitätsvorteile von WebAssembly, während unsere Anwendung gleichzeitig leichtgewichtig bleibt. Da wir unseren WebAssembly-Code in einer besser vorhersagbaren Umgebung ausführen, können wir darüber hinaus potenziell intensivere Berechnungen durchführen.

Ein konkretes Beispiel

In meinem vorherigen Artikel hier im Smashing Magazine haben wir besprochen, wie wir eine Webanwendung beschleunigt haben, indem wir langsame JavaScript-Berechnungen durch C-Code ersetzt haben, der in WebAssembly kompiliert wurde. Die fragliche Web-App war fastq.bio, ein Tool zur Vorschau der Qualität von DNA-Sequenzierungsdaten.

Lassen Sie uns als konkretes Beispiel fastq.bio in eine Anwendung umschreiben, die serverloses WebAssembly verwendet, anstatt WebAssembly im Browser auszuführen. Für diesen Artikel verwenden wir Cloudflare Workers, einen serverlosen Anbieter, der WebAssembly unterstützt und auf der V8-Browser-Engine aufbaut. Ein anderer Cloud-Anbieter, Fastly, arbeitet an einem ähnlichen Angebot, jedoch basierend auf seiner Lucet-Laufzeit.

Lassen Sie uns zunächst etwas Rust-Code schreiben, um die Datenqualität von DNA-Sequenzierungsdaten zu analysieren. Der Einfachheit halber können wir die Rust-Bio-Bioinformatikbibliothek nutzen, um das Parsen der Eingabedaten zu handhaben, und die wasm-bindgen-Bibliothek, die uns hilft, unseren Rust-Code für WebAssembly zu kompilieren.

Hier ist ein Ausschnitt des Codes, der DNA-Sequenzierungsdaten einliest und einen JSON mit einer Zusammenfassung der Qualitätsmetriken ausgibt:

 // Import packages extern crate wasm_bindgen; use bio::seq_analysis::gc; use bio::io::fastq; ... // This "wasm_bindgen" tag lets us denote the functions // we want to expose in our WebAssembly module #[wasm_bindgen] pub fn fastq_metrics(seq: String) -> String { ... // Loop through lines in the file let reader = fastq::Reader::new(seq.as_bytes()); for result in reader.records() { let record = result.unwrap(); let sequence = record.seq(); // Calculate simple statistics on each record n_reads += 1.0; let read_length = sequence.len(); let read_gc = gc::gc_content(sequence); // We want to draw histograms of these values // so we store their values for later plotting hist_gc.push(read_gc * 100.0); hist_len.push(read_length); ... } // Return statistics as a JSON blob json!({ "n": n_reads, "hist": { "gc": hist_gc, "len": hist_len }, ... }).to_string() }

Wir haben dann das Wrangler-Befehlszeilentool von Cloudflare verwendet, um die schwere Arbeit der Kompilierung in WebAssembly und der Bereitstellung in der Cloud zu erledigen. Sobald dies erledigt ist, erhalten wir einen API-Endpunkt, der Sequenzierungsdaten als Eingabe verwendet und ein JSON mit Datenqualitätsmetriken zurückgibt. Wir können diese API jetzt in unsere Anwendung integrieren.

Hier ist ein GIF der Anwendung in Aktion:

GIF unserer Anwendung, die parallele Aufrufe an eine serverlose WebAssembly-Funktion durchführt und Diagramme mit den zurückgegebenen Daten aktualisiert.
Anstatt die Analyse direkt im Browser auszuführen, stellt die serverlose Version unserer Anwendung mehrere POST-Anforderungen parallel zu unserer serverlosen Funktion (siehe rechte Seitenleiste) und aktualisiert die Diagramme jedes Mal, wenn sie mehr Daten zurückgibt. (Große Vorschau)

Der vollständige Code ist auf GitHub (Open Source) verfügbar.

Alles in Kontext setzen

Um den serverlosen WebAssembly-Ansatz in einen Kontext zu stellen, betrachten wir vier Hauptwege, auf denen wir Datenverarbeitungs-Webanwendungen erstellen können (d. h. Web-Apps, bei denen wir Analysen der vom Benutzer bereitgestellten Daten durchführen):

Diese Abbildung zeigt vier Möglichkeiten, wie wir die Datenverarbeitung in einer Web-App strukturieren können: auf dem Server (ohne WebAssembly), im Browser mit JavaScript, im Browser mit WebAssembly und serverloses WebAssembly.
Vier verschiedene architektonische Entscheidungen, die wir für Apps treffen können, die Daten verarbeiten. (Große Vorschau)

Wie oben dargestellt, kann die Datenverarbeitung an mehreren Stellen erfolgen:

  1. Serverseitig
    Dies ist der Ansatz, der von den meisten Webanwendungen gewählt wird, bei denen API-Aufrufe im Front-End die Datenverarbeitung im Back-End starten.
  2. Clientseitiges JavaScript
    Bei diesem Ansatz ist der Datenverarbeitungscode in JavaScript geschrieben und wird im Browser ausgeführt. Der Nachteil ist, dass Ihre Leistung beeinträchtigt wird, und wenn Ihr ursprünglicher Code nicht in JavaScript war, müssen Sie ihn von Grund auf neu schreiben!
  3. Clientseitige WebAssembly
    Dazu muss Datenanalysecode für WebAssembly kompiliert und im Browser ausgeführt werden. Wenn der Analysecode in Sprachen wie C, C++ oder Rust geschrieben wurde (wie es in meinem Bereich der Genomik häufig der Fall ist), erübrigt sich das Umschreiben komplexer Algorithmen in JavaScript. Es bietet auch das Potenzial zur Beschleunigung unserer Anwendung (z. B. wie in einem früheren Artikel besprochen).
  4. Serverloses WebAssembly
    Dazu gehört das Ausführen des kompilierten WebAssembly in der Cloud unter Verwendung eines FaaS-ähnlichen Modells (z. B. dieser Artikel).

Warum also den serverlosen Ansatz den anderen vorziehen? Zum einen hat es im Vergleich zum ersten Ansatz die Vorteile, die mit der Verwendung von WebAssembly einhergehen, insbesondere die Möglichkeit, vorhandenen Code zu portieren, ohne ihn in JavaScript umschreiben zu müssen. Im Vergleich zum dritten Ansatz bedeutet serverloses WebAssembly auch, dass unsere App leichter ist, da wir die Ressourcen des Benutzers nicht für die Zahlenverarbeitung verwenden. Insbesondere wenn die Berechnungen ziemlich aufwendig sind oder die Daten bereits in der Cloud liegen, ist dieser Ansatz sinnvoller.

Auf der anderen Seite muss die App jetzt jedoch Netzwerkverbindungen herstellen, sodass die Anwendung wahrscheinlich langsamer sein wird. Darüber hinaus ist dieser Ansatz abhängig vom Umfang der Berechnung und davon, ob er in kleinere Analyseteile zerlegt werden kann, möglicherweise nicht geeignet, da die Anbieter von serverlosen Clouds die Laufzeit-, CPU- und RAM-Auslastung einschränken.

Fazit

Wie wir gesehen haben, ist es jetzt möglich, WebAssembly-Code serverlos auszuführen und die Vorteile sowohl von WebAssembly (Portabilität und Geschwindigkeit) als auch von Function-as-a-Service-Architekturen (Auto-Skalierung und nutzungsabhängige Preise) zu nutzen ). Bestimmte Arten von Anwendungen – wie Datenanalyse und Bildverarbeitung, um nur einige zu nennen – können von einem solchen Ansatz stark profitieren. Obwohl die Laufzeit aufgrund der zusätzlichen Roundtrips zum Netzwerk leidet, ermöglicht uns dieser Ansatz, mehr Daten gleichzeitig zu verarbeiten, ohne die Ressourcen der Benutzer zu belasten.