Die Fastly Edge-Cloud-Plattform

Zurück zum Blog

Folgen und abonnieren

Optimierung der Rechenleistung für agentenbasierte Systeme mit neuer Funktion zur Weiterleitung von Anfragen

Ulyssa Mello

Staff Engineer

Ein Großteil der Entwicklungsarbeit, die wir in den letzten Jahren geleistet haben, konzentrierte sich darauf, Kunden dabei zu helfen, die CPU-Usage und die Wall-Clock-Zeit zu reduzieren. Vor einigen Monaten haben wir unser Preismodell aktualisiert, um dem Rechnung zu tragen. Dabei haben wir die Messung der Ausführungsdauer entfernt, um den Fokus rein auf Anfragen und den vCPU-Verbrauch zu legen. Dieses neue Modell gibt Kunden mehr Kontrolle, sodass sie durch das Schreiben von effizienterem Code direkt ihre Ausgaben reduzieren. 

Dieses Streben nach Effizienz spiegelt sich auch in einigen unserer jüngsten kundengetriebenen Entwicklungsarbeiten wider, bei denen wir vor der Notwendigkeit standen, länger laufende Backend-Anfragen zu unterstützen, insbesondere für rechenintensive agentische Workflows, die dazu führen, dass Services ihr Wall-Clock-Limit erreichen. 

Da das Weiterleiten von Anfragen an Large Language Models (LLMs) Zeit beansprucht, wollten wir Entwicklern eine Möglichkeit bieten, auf diese Antworten zu warten, ohne ihre verfügbaren Edge-Ressourcen zu binden. Die Erfüllung dieser Anforderung hat sich zu einer umfassenderen Plattformverbesserung entwickelt, die wir weiter ausbauen werden. Die Verbesserung ist eine neue Funktion zur Weiterleitung von Anfragen, die ab sofort in Version 0.13.0 des Fastly Rust SDK verfügbar ist.

Verwaltung von Wasm-Gastlimits und langlebigen Anfragen

Compute erzwingt für Wasm-Gäste in der Regel ein Wall-Clock-Timeout von 2 Minuten. Dieses Limit ist gewollt, um Ressourcen zu schützen und einen gesunden Umschlag von Anfragen sicherzustellen. Das Design funktioniert auch perfekt für die große Mehrheit von Microservices und Edge-Logik, bei denen wir eine 1:1-Zuordnung von laufenden Wasm-Gästen zu eingehenden Anfragen beibehalten.

Allerdings kann diese Architektur manchmal problematisch werden, wenn auf langsame oder nicht reagierende Backends gewartet wird. Dies kann an einer hohen Last auf dem Origin liegen, die alle laufenden Anfragen verlangsamt, oder daran, dass eine rechenintensive Berechnung abgeschlossen werden muss, um eine Antwort zu generieren. Manchmal liegt es nicht einmal unter der Kontrolle des Origins, wie etwa bei einer lang laufenden POST-Anfrage, bei der das Schreiben der Body-Bytes auf den Origin aufgrund eines großen Uploads oder einer langsamen Byte-Übertragung von einem mobilen Client eine Weile dauert.

(Hinweis: Wasm-Gäste sind kompilierte Wasm-Module, die innerhalb eines Wasm-Hosts ausgeführt werden. Wasm-Gäste werden in einer strikten Sandbox ausgeführt, sodass der Host nicht vertrauenswürdigen Code sicher ausführen kann, ohne das zugrunde liegende System zu kompromittieren.)

Die Lösung: PendingRequest::send_to_client

Um diese langlaufenden Backend-Anfragen besser zu unterstützen und den RPS-Durchsatz zu steigern, haben wir eine neue PendingRequest::send_to_client -Funktion eingeführt. Mit dieser neuen Funktion können wir eine asynchrone Anfrage an einen Origin senden, und wenn es sich um eine Direct-Pass- oder hit-for-pass-Anfrage handelt, können wir sie vom Gast an den Host übergeben, während sie noch verarbeitet wird – noch bevor wir die endgültige Antwort kennen. Anschließend weisen wir die Plattform an, die Antwort an den Downstream-Client zurückzugeben, sobald sie schlussendlich vorliegt. Da die Anfrage im Hintergrund weiterläuft, kann der Wasm-Gast frühzeitig beendet werden und seine Ressourcen für zukünftige Anfragen freigeben. Dieser Ansatz erhöht den RPS-Durchsatz drastisch und schützt Compute-Services davor, ihre verfügbaren Compute-Instanzen durch das Warten auf den Abschluss langlaufender Anfragen zu erschöpfen.

Hello-World-Beispiel:

use fastly::{Error, Request};

fn main() -> Result<(), Error> {
    // 1. Receive the incoming downstream request from the client:
    let req = Request::from_client();

    // 2. Dispatch the direct pass request asynchronously to your slow backend:
    let pending_req = req.with_pass(true).send_async("my_slow_origin_backend")?;

    // 3. Hand off the unresolved, in-flight request directly to the host daemon:
    pending_req.send_to_client()?;

    // 4. Terminate the guest cleanly. 
    // The host daemon takes over, monitoring the request and piping the eventual
    // response back downstream completely independently.
    Ok(())
}

Wichtige Anwendungsfälle

  • Schwere KI-Gateways und langlaufende LLM-Schleifen: Anfang dieses Jahres haben wir untersucht, wie Entwickler sichere, KI-Agent-Schleifen mit niedriger Latenz direkt auf Fastly Compute aufbauen. In einem agentischen Workflow koordiniert ein Edge-Service häufig mehrere Iterationen von Überlegungen, Tool-Aufrufen und externen Modell-Prompts. Während unsere Laufzeit eine außergewöhnlich sichere Umgebung zur Ausführung dieser autonomen Agenten bietet, können schwere Textgenerierungsaufgaben oder komplexe Verarbeitungen von Upstream-LLM-Anbietern die Verarbeitungszeiten drastisch skalieren, bevor Header generiert werden. Indem Sie diese Verbindungsmuster mit der neuen API im Rust SDK umfunktionieren, können Sie Fastly Compute als intelligentes KI-Gateway mit hohem Durchsatz nutzen. Ihre Edge-Anwendung kann die Anfrage über dynamische Backends autorisieren, Client-Berechtigungen auswerten oder semantische Caching-Layer einfügen und dann den schweren LLM-Aufruf asynchron ausführen. 

  • Origin Shield-Optimierung: Die meisten Architekturen leiten initiale Anfragen an ein Edge-POP weiter, das diese dann per Proxy an ein Origin Shield-POP weiterleitet, wo eine starke Bearbeitung stattfindet. Das Edge-POP modifiziert die finale Antwort häufig nicht, sondern leitet die Antwort des Origin Shield-POP stattdessen einfach direkt durch. Mit Pending Request Handoff kann das Edge-POP die Shield-Anfrage asynchron auslösen, übergeben und seinen lokalen Gast-Footprint sofort beenden – wodurch die gesamte Wall-Clock-Zeit an Ihren nächstgelegenen Edge-POP drastisch minimiert wird.

Abbildung 1: Die Grafik zeigt einen Compute Service, der nach NYC abschirmt und gleichmäßigen Traffic in Brisbane (BNE) verzeichnet, bei der Übergabe seiner Shield-Anfragen. Die Wall-Clock-Zeit in BNE verschwindet nahezu, nachdem die Funktion zur Weiterleitung von Anfragen genutzt wird.

  • Langlaufende Uploads: Wenn Ihr Service eingehende Inhalte auf der Edge von Clients mit geringer Bandbreite empfängt, verhindert die Nutzung dieser Funktion, dass Ihr Service Gast-Wall-Clock-Timeouts erreicht, indem die Plattform den Upload unabhängig von der Ausführung des Wasm-Gasts fortsetzen kann.

Header-Modifikation und Fehlerbehebung

Diese neue Funktion umfasst auch die Möglichkeit, Header in der schließlichen Antwort zu ändern. Sie können Änderungen einreihen, um bestimmte Header vor der eigentlichen Übergabe zu entfernen oder einzufügen. Dies ermöglicht Ihnen die Angabe von Änderungen wie „diesen Header-Namen entfernen“ oder „diesen Header mit dem Wert X einfügen“, was durchgeführt wird, sobald die Antwort eintrifft:

use fastly::{Error, Request};
use fastly::http::request::PendingResponseKind;

fn main() -> Result<(), Error> {
    // 1. Receive the incoming downstream request from the client:
    let req = Request::from_client();

    // 2. Dispatch the direct pass request asynchronously to your slow backend:
    let mut pending = req.with_pass(true).send_async("my_slow_origin_backend")?;

    // 3.1 Remove the `Server` header added by the origin's application server:
    pending.remove_response_header("Server", PendingResponseKind::Response);

    // 3.2 Insert the current service version for debugging:
    pending.set_response_header(
        "X-Service-Version",
        fastly::compute_runtime::service_version().to_string(),
        PendingResponseKind::Any
    );

    // 4. Hand off the unresolved, in-flight request directly to the host daemon:
    pending.send_to_client()?;

    // 5. Terminate the guest cleanly. 
    // The host daemon takes over, monitoring the request and piping the eventual
    // response back downstream completely independently.
    Ok(())
}

Beachten Sie die Verwendung des Typs PendingResponseKind im obigen Beispiel. Dies ermöglicht dem Service die Kontrolle darüber, ob die Header-Änderungen auf Origin-Antworten PendingResponseKind::Response, synthetische Fehlerantworten, die generiert werden, wenn die laufende Anfrage fehlschlägt PendingResponseKind::Error, oder beides PendingResponseKind::Any angewendet werden. In den Fällen, in denen die laufende Anfrage fehlgeschlagen ist, wird eine entsprechende 5XX-Antwort generiert und an den Client zurückgesendet. Typischerweise ist dies eines der folgenden:

  • 504 Gateway Timeout: Wird automatisch zurückgegeben, wenn die Verbindung zu Ihrem Origin das Zeitlimit überschreitet oder das First Byte Timeout für das Backend erreicht ist.

  • 502 Bad Gateway: Wird zurückgegeben, wenn der Origin-Server einen unvollständigen oder fehlerhaften Antwort-Body zurückgibt, das Backend ein ungültiges TLS-Zertifikat hat oder anderweitig nicht ordnungsgemäß funktioniert und antwortet.

Im Observability-Dashboard des Fastly Control Panels können Sie mithilfe des Diagramms „Backend-Anfragen & Fehler“ sehen, welche Arten von Backend-Fehlern für 502- und 504-Antworten verantwortlich sind. Weitere Informationen finden Sie unter Backend-Anfragefehlern.

Legen Sie noch heute los

Sie müssen nicht warten, bis Sie Ihren Service in der Produktivumgebung bereitsgestellt haben, um zu sehen, welche Vorteile Ihnen diese neue Funktion bieten kann! Sie wird in aktuellen Releases von Viceroy, unserer lokalen Testumgebung, vollständig unterstützt. Sie können zeitintensive Backend-Timeouts emulieren, Ihren Code für die Verwendung von Request::send_async/PendingRequest::send_to_client umstrukturieren und Ihre in der Warteschlange befindlichen Header-Operationen direkt über Ihr lokales Entwicklungsterminal debuggen. Während die Funktion zur Weiterleitung von Anfragen derzeit exklusiv in unserem Rust SDK (v0.13.0) verfügbar ist, werden wir sie auf die restlichen unserer offiziellen SDKs ausweiten. Werfen Sie auch einen Blick in unsere Dokumentation für weitere Informationen und teilen Sie uns in unserem Forum mit, was Sie entwickeln. 

Sind Sie bereit, loszulegen?

Treten Sie noch heute mit uns in Kontakt