Jetzt abonnieren, um Benachrichtigungen über neue Beiträge zu erhalten:

Cloudflare ist jetzt schneller und sicherer – dank Rust.

2025-09-26

Lesezeit: 12 Min.
Dieser Beitrag ist auch auf English und 简体中文 verfügbar.

Cloudflare arbeitet unermüdlich daran, das schnellste Netzwerk der Welt aufzubauen und zu betreiben. Wir verfolgen und berichten seit 2021 über die Performance unseres Netzwerks: Das neueste Update finden Sie hier.

Der Aufbau des schnellsten Netzwerks erfordert Arbeit in vielen Bereichen. Wir investieren viel Zeit in unsere Hardware, um effiziente und schnelle Maschinen zu betreiben. Wir investieren in Peering-Vereinbarungen, um sicherzustellen, dass wir mit jedem Teil des Internets mit minimaler Verzögerung kommunizieren können. Darüber hinaus müssen wir auch in die Software investieren, die unser Netzwerk betreibt, insbesondere da jedes neue Produkt sonst zusätzliche Verarbeitungsverzögerungen verursachen kann.

Unabhängig davon, wie schnell Nachrichten eingehen, entsteht ein Engpass, wenn die Software zu lange benötigt, um zu überlegen, wie Anfragen verarbeitet und beantwortet werden sollen. Wir freuen uns, Ihnen heute ein bedeutendes Upgrade unserer Software mitzuteilen, das die mittlere Reaktionszeit um 10 ms reduziert und eine 25%ige Performance-Steigerung erzielt, gemessen durch CDN-Performance-Tests von Drittanbietern.

Wir haben das letzte Jahr damit verbracht, wichtige Komponenten unseres Systems neu aufzubauen, und wir haben gerade die Latenzzeit des Datenverkehrs, der unser Netzwerk durchläuft, für Millionen unserer Kunden deutlich reduziert. Gleichzeitig haben wir unser System sicherer gemacht und die Zeit reduziert, die wir für die Entwicklung und Veröffentlichung neuer Produkte benötigen. 

Wo haben wir angefangen?

Jede Anfrage, die Cloudflare erreicht, beginnt eine Reise durch unser Netzwerk. Sie kann aus einem Browser stammen, der eine Webseite lädt, aus einer mobilen App, die eine API aufruft, oder aus automatisiertem Traffic eines anderen Dienstes. Diese Anfragen treffen zuerst auf unsere HTTP- und TLS-Schicht, wandern dann in ein System namens FL und gelangen schließlich zu Pingora, das Cache-Abfragen durchführt oder bei Bedarf Daten vom Ursprung holt.

FL ist das Herzstück von Cloudflare. Sobald eine Anfrage FL erreicht, führen wir anschließend die verschiedenen Sicherheits- und Performance-Features in unserem Netzwerk aus. Dabei werden die individuellen Konfigurationen und Einstellungen jedes Kunden berücksichtigt, von der Durchsetzung von WAF-Regeln und DDoS-Schutz bis hin zur Weiterleitung des Datenverkehrs an die Entwicklerplattform und R2

FL wurde vor über 15 Jahren entwickelt und ist ein Kernbestandteil des Cloudflare-Netzwerks. Dies ermöglicht uns, eine breite Palette von Funktionen bereitzustellen, aber im Laufe der Zeit wurde diese Flexibilität zu einer Herausforderung. Mit jedem neuen Produkt wurde FL schwerer zu warten, langsamer bei der Verarbeitung von Anfragen und komplizierter zu erweitern. Jede neue Funktion erforderte genaue Prüfungen der bestehenden Logik, und jede Ergänzung brachte ein wenig zusätzliche Latenz — was es zunehmend erschwerte, die gewünschte Performance zu halten.

Sie sehen, wie wichtig FL für unser System ist – wir bezeichnen es oft als das „Gehirn“ von Cloudflare. Es ist auch einer der ältesten Teile unseres Systems: Der erste Commit zur Codebasis wurde von einem unserer Gründer, Lee Holloway, lange vor unserer ersten Produkteinführung durchgeführt. Wir feiern diese Woche unseren 15. Geburtstag – dieses System wurde 9 Monate zuvor gestartet!

commit 39c72e5edc1f05ae4c04929eda4e4d125f86c5ce
Author: Lee Holloway <q@t60.(none)>
Date:   Wed Jan 6 09:57:55 2010 -0800

    nginx-fl initial configuration

Wie der Commit impliziert, wurde die erste Version von FL auf Basis des NGINX-Webservers implementiert, wobei die Produktlogik in PHP umgesetzt wurde.  Nach drei Jahren wurde das System zu komplex für eine effektive Verwaltung und reagierte zu langsam. Daher wurde das laufende System fast vollständig neu geschrieben. Dies führte zu einem weiteren wichtigen Commit, der diesmal von Dane Knecht, unserem jetzigen CTO, erfolgte.

commit bedf6e7080391683e46ab698aacdfa9b3126a75f
Author: Dane Knecht
Date:   Thu Sep 19 19:31:15 2013 -0700

    remove PHP.

Ab diesem Zeitpunkt wurde FL mit NGINX, dem OpenResty-Framework und LuaJIT implementiert.  Das funktionierte lange Zeit sehr gut, doch in den letzten Jahren zeigten sich zunehmend Alterserscheinungen. Wir mussten immer mehr Zeit darauf verwenden, obskure Fehler in LuaJIT zu beheben oder zu umgehen. Die stark dynamische und unstrukturierte Natur unseres Lua-Codes, die anfangs ein Segen war, um schnell Logik zu implementieren, entwickelte sich zu einer Fehlerquelle und führte zu Verzögerungen bei der Integration komplexer Produktlogik. Mit jeder neuen Produkteinführung mussten wir prüfen, ob bestehende Produkte durch die neuen Logiken beeinträchtigt werden könnten.

Es war klar, dass wir ein Umdenken brauchten. Daher legten wir im Juli 2024 den ersten Commit für eine völlig neue und grundlegend andere Implementierung an. Um keine Zeit mit der Namensfindung zu verlieren, nannten wir sie einfach „FL2“ – und begannen selbstverständlich, das ursprüngliche System als „FL1“ zu bezeichnen.

commit a72698fc7404a353a09a3b20ab92797ab4744ea8
Author: Maciej Lechowski
Date:   Wed Jul 10 15:19:28 2024 +0100

    Create fl2 project

Rust und starre Modularisierung

Wir haben nicht bei null angefangen. Wir haben bereits in einem Blogbeitrag darüber berichtet, wie wir ein anderes unserer Altsysteme durch Pingora ersetzt haben. Pingora ist in der Programmiersprache Rust mit der Tokio-Laufzeitumgebung aufgebaut. Wir haben auch über Oxy gebloggt, unser internes Framework zum Aufbau von Proxys in Rust. Wir schreiben viel Rust-Code und sind darin ziemlich gut geworden.

Wir haben FL2 in Rust auf Oxy entwickelt und ein striktes Modul-Framework erstellt, um die gesamte Logik in FL2 zu strukturieren.

Warum Oxy?

Als wir mit der Entwicklung von FL2 begannen, war uns klar, dass es nicht nur um den Ersatz eines alten Systems ging – wir erneuerten die Grundfesten von Cloudflare. Das bedeutete, dass wir mehr als nur einen Proxy brauchten: ein Framework, das mit uns wachsen, die enorme Skalierung unseres Netzwerks bewältigen und es den Teams ermöglichen würde, sich schnell zu bewegen – ohne Kompromisse bei Sicherheit oder Performance.

Oxy bietet uns eine leistungsstarke Kombination aus Performance, Sicherheit und Flexibilität. In Rust entwickelt, beseitigt es ganze Klassen von Fehlern, die FL1 auf Basis von NGINX/LuaJIT belasteten – etwa Speicherfehler und Datenrennen – und erreicht dabei Performance auf C-Niveau. Bei der Skalierung von Cloudflare sind solche Garantien kein Luxus, sondern essenziell. Jede eingesparte Mikrosekunde pro Anfrage verbessert die Nutzererfahrung spürbar, und jeder vermiedene Absturz oder Sonderfall trägt zur Stabilität des Internets bei. Die strikten Compile-Time-Garantien von Rust passen zudem perfekt zur modularen Architektur von FL2, in der wir klare Verträge zwischen Produktmodulen und deren Ein- und Ausgaben durchsetzen.

Aber bei der Wahl ging es nicht nur um die Sprache. Oxy ist das Ergebnis jahrelanger Erfahrung im Aufbau von Hochleistungs-Proxys. Es unterstützt bereits mehrere große Cloudflare-Services, von unserem Zero Trust-Gateway bis hin zu Apples iCloud Private Relay. Wir wussten also, dass es die verschiedenen Traffic-Muster und Protokollkombinationen bewältigen konnte, die FL2 ausgesetzt war. Dank des Erweiterbarkeitsmodells können wir Datenverkehr von Schicht 3 bis Anwendungsschicht abfangen, analysieren und manipulieren und sogar Traffic auf verschiedenen Schichten entkapseln und erneut verarbeiten. Diese Flexibilität ist entscheidend für das Design von FL2, da wir dadurch alles von HTTP bis zu rohem IP-Traffic einheitlich behandeln und die Plattform weiterentwickeln können, um neue Protokolle und Funktionen zu unterstützen, ohne grundlegende Teile neu schreiben zu müssen.

Oxy bringt zudem eine umfangreiche Palette integrierter Funktionen mit, die zuvor durch aufwendigen, maßgeschneiderten Code umgesetzt werden mussten. Funktionen wie Monitoring, Soft Reloads, dynamisches Laden und Austauschen von Konfigurationen sind bereits Teil des Frameworks. So können sich die Produktteams auf die geschäftsspezifische Logik ihrer Module konzentrieren, anstatt jedes Mal die Infrastruktur neu zu entwickeln. Dieses stabile Fundament ermöglicht es uns, Änderungen mit Vertrauen vorzunehmen, schnell auszuliefern und darauf zu vertrauen, dass sie im Betrieb wie erwartet funktionieren.

Reibungslose Neustarts – So bleibt das Internet im Fluss

Eine der wichtigsten Verbesserungen, die Oxy bietet, ist die Handhabung von Neustarts. Jede Software, die sich in ständiger Entwicklung und Verbesserung befindet, muss schließlich aktualisiert werden. Bei Desktopsoftware ist das einfach: Sie schließen das Programm, installieren das Update und öffnen es wieder. Im Web sind die Dinge viel schwieriger. Unsere Software ist ständig im Einsatz und kann nicht einfach gestoppt werden. Eine abgebrochene HTTP-Anfrage kann dazu führen, dass eine Seite nicht geladen werden kann, und eine unterbrochene Verbindung kann Sie aus einem Videoanruf werfen. Zuverlässigkeit ist ein Muss.

In FL1 bedeuteten Upgrades Neustarts des Proxy-Prozesses. Ein Neustart eines Proxys bedeutete, den Prozess vollständig zu beenden, was sofort alle aktiven Verbindungen unterbrach. Das war besonders problematisch für langlebige Verbindungen wie WebSockets, Streaming-Sitzungen und Echtzeit-APIs. Sogar geplante Upgrades können zu für den Benutzer sichtbaren Unterbrechungen führen, und ungeplante Neustarts während Vorfällen können noch schlimmer sein.

Oxy ändert das. Es beinhaltet einen integrierten Mechanismus für sanfte Neustarts, der es uns ermöglicht, neue Versionen auszurollen, ohne Verbindungen zu verlieren, wann immer dies möglich ist. Wenn eine neue Instanz eines Oxy-basierten Dienstes startet, akzeptiert die alte Instanz keine neuen Verbindungen mehr, bedient aber weiterhin die bestehenden, wodurch diese Sitzungen ununterbrochen fortgesetzt werden können, bis sie auf natürliche Weise enden.

Das bedeutet, dass eine bestehende WebSocket-Sitzung beim Deployment einer neuen Version ununterbrochen fortgesetzt werden kann, bis sie auf natürliche Weise endet, anstatt durch den Neustart beendet zu werden. Im gesamten Cloudflare-Netzwerk werden Bereitstellungen über mehrere Stunden orchestriert, sodass die aggregierte Einführung reibungslos und für Endnutzer nahezu unbemerkt abläuft.

Wir gehen noch einen Schritt weiter, indem wir die systemd-Socket-Aktivierung verwenden. Anstatt jeden Proxy seine eigenen Sockets verwalten zu lassen, lassen wir diese von systemd erstellen und verwalten. Dadurch wird die Lebensdauer von Sockets von der Lebensdauer der Oxy-Anwendung selbst entkoppelt. Wenn ein Oxy-Prozess neu startet oder abstürzt, bleiben die Sockets geöffnet und bereit, neue Verbindungen anzunehmen. Diese werden bedient, sobald der neue Prozess ausgeführt wird. Das beseitigt die „Connection Refused“-Fehler, die während Neustarts in FL1 auftreten konnten, und verbessert die Gesamtverfügbarkeit bei Upgrades.

Wir haben auch unsere eigenen Koordinationsmechanismen in Rust entwickelt, um Go-Bibliotheken wie tableflip durch shellflip zu ersetzen. Dabei wird ein Neustart-Koordinationssocket verwendet, der die Konfiguration validiert, neue Instanzen erzeugt und sicherstellt, dass die neue Version fehlerfrei ist, bevor die alte heruntergefahren wird. Dies verbessert die Feedbackschleifen und ermöglicht unseren Automatisierungstools, Fehler sofort zu erkennen und darauf zu reagieren, anstatt sich auf blinde, signalbasierte Neustarts zu verlassen.

Zusammensetzen von FL2 aus Modulen

Um die Probleme zu vermeiden, die wir in FL1 hatten, wollten wir ein Design, bei dem alle Interaktionen zwischen der Produktlogik explizit und leicht verständlich sind. 

Aufbauend auf den Grundlagen von Oxy haben wir eine Plattform entwickelt, die die gesamte für unsere Produkte entwickelte Logik in klar definierte Module unterteilt. Nach einigen Experimenten und Recherchen haben wir ein Modulsystem entworfen, das strikte Regeln durchsetzt:

  • Das Modul kann keine E/A (Eingabe oder Ausgabe) durchführen.

  • Das Modul bietet eine Liste von Phasen.

  • Die Phasen werden in einer strikt definierten Reihenfolge evaluiert, die für jede Anfrage gleich ist.

  • Jede Phase definiert eine Reihe von Eingaben, die die Plattform bereitstellt, und eine Reihe von Ausgaben, die sie erzeugen kann.

Hier ist ein Beispiel dafür, wie eine Modulphasendefinition aussieht:

Phase {
    name: phases::SERVE_ERROR_PAGE,
    request_types_enabled: PHASE_ENABLED_FOR_REQUEST_TYPE,
    inputs: vec![
        InputKind::IPInfo,
        InputKind::ModuleValue(
            MODULE_VALUE_CUSTOM_ERRORS_FETCH_WORKER_RESPONSE.as_str(),
        ),
        InputKind::ModuleValue(MODULE_VALUE_ORIGINAL_SERVE_RESPONSE.as_str()),
        InputKind::ModuleValue(MODULE_VALUE_RULESETS_CUSTOM_ERRORS_OUTPUT.as_str()),
        InputKind::ModuleValue(MODULE_VALUE_RULESETS_UPSTREAM_ERROR_DETAILS.as_str()),
        InputKind::RayId,
        InputKind::StatusCode,
        InputKind::Visitor,
    ],
    outputs: vec![OutputValue::ServeResponse],
    filters: vec![],
    func: phase_serve_error_page::callback,
}

Diese Phase ist für unser Produkt für benutzerdefinierte Fehlerseiten.  Es sind einige Eingaben erforderlich – Informationen über die IP-Adresse des Besuchers, einige Header- und andere HTTP-Informationen sowie einige „Modulwerte“. Modulwerte ermöglichen es einem Modul, Informationen an ein anderes zu übermitteln, und sie sind entscheidend dafür, dass die strikten Eigenschaften des Modulsystems funktionieren. Dieses Modul benötigt beispielsweise einige Informationen, die von der Ausgabe unseres regelsatzbasierten Produkts für benutzerdefinierte Fehler (der Eingabe „MODULE_VALUE_RULESETS_CUSTOM_ERRORS_OUTPUT“) erzeugt werden. Diese Eingabe- und Ausgabedefinitionen werden zur Kompilierzeit durchgesetzt.

Obwohl diese Regeln streng sind, haben wir festgestellt, dass wir unsere gesamte Produktlogik innerhalb dieses Frameworks implementieren können. Der Vorteil dabei ist, dass wir sofort erkennen können, welche anderen Produkte sich gegenseitig beeinflussen könnten.

So ersetzen Sie ein laufendes System

Ein Framework zu entwickeln ist das eine. Die gesamte Produktlogik korrekt umzusetzen, sodass Kundinnen und Kunden lediglich eine Leistungsverbesserung bemerken, ist etwas ganz anderes.

Die FL-Codebasis unterstützt Cloudflare-Produkte seit 15 Jahren und wird fortlaufend geändert. Wir konnten die Entwicklung nicht stoppen. Eine unserer ersten Aufgaben war es daher, Wege zu finden, die Migration einfacher und sicherer zu machen.

Schritt 1 – Rust-Module in OpenResty

Allein die Produktlogik in Rust neu zu implementieren ist bereits eine erhebliche Ablenkung vom eigentlichen Ziel, Produkte an Kundinnen und Kunden auszuliefern. Von allen Teams zusätzlich zu verlangen, zwei Versionen ihrer Produktlogik parallel zu pflegen und jede Änderung doppelt umzusetzen, bis die Migration abgeschlossen ist, wäre zu viel gewesen.

Wir haben also eine Ebene in unserer alten NGINX- und OpenResty-basierten FL implementiert, die es ermöglicht, die neuen Module auszuführen. Anstatt eine parallele Implementierung zu pflegen, konnten Teams ihre Logik in Rust implementieren und ihre alte Lua-Logik damit ersetzen, ohne auf die vollständige Ablösung des alten Systems zu warten.

Hier ist beispielsweise ein Teil der Implementierung für die zuvor definierte Phase des benutzerdefinierten Fehlerseitenmoduls (wir haben einige der weniger wichtigen Details weggelassen, sodass dies nicht ganz wie geschrieben kompiliert werden kann):

pub(crate) fn callback(_services: &mut Services, input: &Input<'_>) -> Output {
    // Rulesets produced a response to serve - this can either come from a special
    // Cloudflare worker for serving custom errors, or be directly embedded in the rule.
    if let Some(rulesets_params) = input
        .get_module_value(MODULE_VALUE_RULESETS_CUSTOM_ERRORS_OUTPUT)
        .cloned()
    {
        // Select either the result from the special worker, or the parameters embedded
        // in the rule.
        let body = input
            .get_module_value(MODULE_VALUE_CUSTOM_ERRORS_FETCH_WORKER_RESPONSE)
            .and_then(|response| {
                handle_custom_errors_fetch_response("rulesets", response.to_owned())
            })
            .or(rulesets_params.body);

        // If we were able to load a body, serve it, otherwise let the next bit of logic
        // handle the response
        if let Some(body) = body {
            let final_body = replace_custom_error_tokens(input, &body);

            // Increment a metric recording number of custom error pages served
            custom_pages::pages_served("rulesets").inc();

            // Return a phase output with one final action, causing an HTTP response to be served.
            return Output::from(TerminalAction::ServeResponse(ResponseAction::OriginError {
                rulesets_params.status,
                source: "rulesets http_custom_errors",
                headers: rulesets_params.headers,
                body: Some(Bytes::from(final_body)),
            }));
        }
    }
}

Die interne Logik in jedem Modul ist recht sauber von der Datenverarbeitung getrennt, wobei das Design der Programmiersprache Rust eine sehr klare und explizite Fehlerbehandlung fördert.

Viele unserer aktivsten Entwicklungsmodule wurden auf diese Weise gehandhabt, wodurch die Teams ihre Änderungsgeschwindigkeit während unserer Migration beibehalten konnten.

Schritt 2: Tests und automatisierte Rollouts

Für eine Migration dieser Art ist ein äußerst leistungsfähiges Testframework unerlässlich.  Wir haben ein System, intern „Flamingo“ genannt, entwickelt, das es uns ermöglicht, Tausende von vollständigen End-to-End-Testanfragen gleichzeitig auf unseren Produktions- und Vorproduktionssystemen auszuführen. Die gleichen Tests werden für FL1 und FL2 ausgeführt, was uns die Gewissheit gibt, dass wir keine Verhaltensweisen ändern.

Sobald wir eine Änderung bereitstellen, wird diese Änderung schrittweise in mehreren Phasen mit zunehmendem Traffic eingeführt. Jede Phase wird automatisch bewertet und besteht nur dann, wenn alle Tests erfolgreich ausgeführt wurden und sowohl die Gesamt-Performance als auch die Ressourcenauslastung innerhalb akzeptabler Grenzen liegen. Dieses System ist vollständig automatisiert und setzt Änderungen aus oder macht sie rückgängig, wenn die Tests fehlschlagen.

Der Vorteil ist, dass wir neue Produktfunktionen in FL2 innerhalb von 48 Stunden entwickeln und veröffentlichen können – wo es in FL1 Wochen gedauert hätte. Tatsächlich beinhaltete mindestens eine der Ankündigungen diese Woche eine solche Änderung!

Schritt 3 – Fallbacks

Über 100 Ingenieure haben an FL2 gearbeitet, und wir haben über 130 Module. Und wir sind noch nicht ganz fertig. Wir arbeiten noch am Feinschliff des Systems, um sicherzustellen, dass es alle Verhaltensweisen von FL1 repliziert.

Wie können wir also Traffic zu FL2 leiten, wenn es nicht alles verarbeiten kann? Wenn FL2 eine Anfrage oder eine Konfiguration für eine Anfrage erhält, die es nicht verarbeiten kann, gibt es auf und führt einen sogenannten Fallback aus – es übergibt die gesamte Anfrage an FL1. Es tut dies auf der Netzwerkebene – es leitet einfach die Bytes an FL1 weiter.

Neben der Möglichkeit, Traffic zu FL2 zu leiten, bevor dieser vollständig abgeschlossen ist, bietet dies einen weiteren großen Vorteil. Wenn wir eine neue Funktionalität in FL2 implementiert haben, aber noch einmal überprüfen möchten, ob sie genauso wie in FL1 funktioniert, können wir die Funktionalität in FL2 evaluieren und dann einen Fallback auslösen. Wir können das Verhalten der beiden Systeme vergleichen, wodurch wir ein hohes Maß an Sicherheit gewinnen, dass unsere Implementierung korrekt war.

Schritt 4 – Einführung

Wir haben Anfang 2025 begonnen, Kundentraffic über FL2 zu leiten und den Umfang des bereitgestellten Traffics im Laufe des Jahres schrittweise erhöht. Im Wesentlichen haben wir zwei Diagramme beobachtet: Eines zeigt den Anstieg des an FL2 weitergeleiteten Datenverkehrs, und das andere zeigt den Rückgang des Anteils des Datenverkehrs, der nicht von FL2 bedient wird und auf FL1 zurückfällt.

Wir haben diesen Prozess begonnen, indem wir den Datenverkehr für unsere kostenlosen Kunden durch das System leiteten. Wir konnten nachweisen, dass das System korrekt funktionierte und die Fallback-Raten für unsere Hauptmodule senken. Unsere Cloudflare Community-MVPs fungierten als Frühwarnsystem, führten erste Tests durch und wiesen auf mögliche Zusammenhänge mit der neuen Plattform hin, sobald Probleme gemeldet wurden. Ihre Unterstützung ermöglichte es unserem Team, schnell zu reagieren, gezielte Korrekturen vorzunehmen oder auszuschließen, dass der Umstieg auf FL2 die Ursache war.

Danach gingen wir zu unseren zahlenden Kunden über und erhöhten schrittweise die Anzahl der Kunden, die das System nutzten. Wir haben auch eng mit einigen unserer größten Kunden zusammengearbeitet, die von den Performance-Vorteilen von FL2 profitieren wollten, und sie frühzeitig eingebunden, um im Gegenzug viel Feedback zum System zu erhalten.

Aktuell verwenden die meisten unserer Kunden FL2. Wir müssen noch einige Funktionen fertigstellen und sind noch nicht bereit, alle zu integrieren. Unser Ziel ist es jedoch, FL1 in den nächsten Monaten zu deaktivieren.

Auswirkungen von FL2

Wie wir zu Beginn dieses Beitrags beschrieben haben, ist FL2 deutlich schneller als FL1. Der Hauptgrund dafür ist schlicht, dass FL2 weniger Aufwand erfordert. Vielleicht ist Ihnen in dem Beispiel zur Moduldefinition eine Zeile aufgefallen

    filters: vec![],

Jedes Modul kann eine Reihe von Filtern bereitstellen, die steuern, ob es ausgeführt wird oder nicht. Das bedeutet, dass wir nicht für jede Anfrage eine Logik für jedes Produkt ausführen – wir können sehr einfach genau die erforderlichen Module auswählen. Die inkrementellen Kosten für jedes neue Produkt, das wir entwickeln, sind entfallen.

Ein weiterer wichtiger Grund für eine bessere Performance ist, dass FL2 eine einzige Codebasis ist, die in einer performanceorientierten Sprache implementiert ist. Im Vergleich dazu basierte FL1 auf NGINX (welches in C geschrieben ist), kombiniert mit LuaJIT (Lua- und C-Schnittstellenschichten) und enthielt außerdem zahlreiche Rust-Module.  In FL1 investierten wir viel Zeit und Speicherressourcen in die Umwandlung von Daten zwischen den unterschiedlichen Darstellungsformaten einzelner Programmiersprachen.

Interne Messungen zeigen, dass FL2 weniger als die Hälfte der CPU-Leistung und deutlich weniger als die Hälfte des Speichers von FL1 benötigt. Das ist ein enormer Vorteil – diese Ressourcen können wir nun für die Entwicklung neuer Funktionen für unsere Kunden nutzen.

Wie messen wir, ob wir besser werden?

Mit unseren eigenen Tools und unabhängigen Benchmarks wie CDNPerf haben wir die Auswirkungen von FL2 gemessen, als wir es im gesamten Netzwerk einführten. Die Ergebnisse sind eindeutig: Websites reagieren im Median 10 ms schneller, was einer 25%igen Performance-Steigerung entspricht.

Sicherheit

FL2 ist von Grund auf sicherer als FL1. Kein Softwaresystem ist perfekt, aber die Programmiersprache Rust bietet uns enorme Vorteile gegenüber LuaJIT. Rust verfügt über starke Speicherprüfungen zur Kompilierzeit und ein Typsystem, das viele Fehlerarten vermeidet. In Kombination damit und mit unserem starren Modulsystem können wir die meisten Änderungen mit hoher Zuversicht vornehmen.

Natürlich ist kein System sicher, wenn es falsch verwendet wird. Auch in Rust lässt sich leicht Code schreiben, der zu Speicherbeschädigungen führt. Um Risiken zu minimieren, setzen wir auf strenge Prüfmechanismen zur Compile-Zeit, ergänzt durch klare Programmierstandards, umfassende Tests und sorgfältige Review-Prozesse.

Wir verfolgen seit Langem die Richtlinie, dass jeder unerklärliche Systemabsturz mit höchster Priorität untersucht werden muss. An dieser Regelung werden wir nicht rütteln, auch wenn die Hauptursache für neue Abstürze in FL2 bisher meist auf Hardwarefehler zurückzuführen ist. Die deutlich gesunkene Häufigkeit solcher Vorfälle verschafft uns die nötige Zeit, um diese Untersuchungen gründlich durchzuführen.

Was ist als Nächstes geplant?

Wir verbringen den Rest des Jahres 2025 mit der vollständigen Migration von FL1 zu FL2 und werden FL1 Anfang 2026 abschalten. Bereits jetzt sehen wir deutliche Vorteile in Bezug auf Kundenperformance und Entwicklungsgeschwindigkeit – und freuen uns darauf, diese allen unseren Kunden bereitzustellen.

Wir müssen noch einen letzten Dienst vollständig migrieren. Das Feld „HTTP- und TLS-Terminierung“ im Diagramm oben ist ebenfalls ein NGINX-Dienst, und wir befinden uns mitten in einer Neufassung in Rust. Wir machen mit dieser Migration gute Fortschritte und gehen davon aus, sie Anfang nächsten Jahres abzuschließen.

Danach, wenn alles modular, in Rust und getestet und skaliert ist, können wir wirklich mit der Optimierung beginnen! Wir werden die Verbindung der Module untereinander neu organisieren und vereinfachen, die Unterstützung für Nicht-HTTP-Datenverkehr wie RPC und Streams erweitern und vieles mehr. 

Möchten Sie Teil dieser Entwicklung werden? Dann besuchen Sie unsere Karriereseite – wir sind immer auf der Suche nach neuen Talenten, die uns helfen, ein besseres Internet zu schaffen.

Wir schützen komplette Firmennetzwerke, helfen Kunden dabei, Internetanwendungen effizient zu erstellen, jede Website oder Internetanwendung zu beschleunigen, DDoS-Angriffe abzuwehren, Hacker in Schach zu halten, und unterstützen Sie bei Ihrer Umstellung auf Zero Trust.

Greifen Sie von einem beliebigen Gerät auf 1.1.1.1 zu und nutzen Sie unsere kostenlose App, die Ihr Internet schneller und sicherer macht.

Wenn Sie mehr über unsere Mission, das Internet besser zu machen, erfahren möchten, beginnen Sie hier. Sie möchten sich beruflich neu orientieren? Dann werfen Sie doch einen Blick auf unsere offenen Stellen.
Birthday WeekRustNGINXUmfassende AnalyseTechnik

Folgen auf X

Cloudflare|@cloudflare

Verwandte Beiträge

28. Oktober 2025 um 13:00

Keeping the Internet fast and secure: introducing Merkle Tree Certificates

Cloudflare is launching an experiment with Chrome to evaluate fast, scalable, and quantum-ready Merkle Tree Certificates, all without degrading performance or changing WebPKI trust relationships....