
Der Invocation Flow – vom HTTP-Request bis zum Ergebnis.
Im vorherigen Artikel haben wir die Architektur hinter evrtng Functions vorgestellt. Jetzt schauen wir uns an, was tatsächlich passiert, wenn du eine Function aufrufst – Schritt für Schritt durch den gesamten Stack. Vom HTTP-Request über Authentifizierung und Message Queue bis hin zum Pod, der deinen Code ausführt und das Ergebnis zurückliefert.
Der Invocation Flow
- HTTP-Request trifft Traefik: Dein Request – egal ob über CLI, SDK oder direkt per HTTP – erreicht zuerst Traefik, unseren Edge Router. Dort wird TLS terminiert und Let’s-Encrypt-Zertifikate automatisch verwaltet.
- APISIX übernimmt das Gateway: Hinter Traefik sitzt APISIX, unser API-Gateway. Hier laufen Rate-Limiting, Billing-Logs und Missbrauchsschutz zusammen.
- Nginx verteilt an Controller: Erst hinter APISIX kommt Nginx als Reverse Proxy zum Einsatz. Er verteilt eingehende Anfragen gleichmässig auf die Controller-Replicas.
- Controller authentifiziert: Der Controller prüft deine Credentials gegen CouchDB. Namespace, API-Key und Berechtigungen werden validiert – erst wenn alles passt, geht es weiter.
- Action-Code wird geladen: Der Controller holt den Action-Code aus CouchDB. Das kann JavaScript, Python, Java oder jede andere unterstützte Sprache sein – die Plattform ist polyglott.
- Load Balancer wählt Invoker: Der integrierte Load Balancer prüft alle verfügbaren Invoker und wählt denjenigen mit der geringsten Auslastung aus. So wird die Last gleichmässig verteilt.
- Kafka-Nachricht: Der Controller publiziert eine Nachricht mit Action-Code, Parametern und Metadaten auf Kafka. Sobald Kafka die Nachricht bestätigt, bekommst du eine ActivationId zurück.
- Invoker übernimmt: Der Invoker pickt die Nachricht aus Kafka, spawnt einen Kubernetes-Pod mit der passenden Runtime, injiziert den Code und führt ihn aus.
- Ergebnis: Das Resultat wird in CouchDB gespeichert, der Pod zerstört. Du kannst das Ergebnis über die ActivationId abrufen – synchron (Blocking) oder asynchron (Non-Blocking).
Dieser gesamte Flow basiert auf der Apache OpenWhisk Architektur, die wir für evrtng angepasst und optimiert haben.
Eine typische evrtng Function
// evrtng Functions - Event-Driven Serverless
async function main(params) {
const start = Date.now();
const event = params.trigger || 'manual';
const timestamp = new Date().toISOString();
const result = await processEvent({
type: event,
data: params.payload,
timestamp
});
return {
statusCode: 200,
body: {
processed: true,
eventType: event,
result: result.summary,
executionTime: Date.now() - start
}
};
}
Eine async function main(params) – der Einstiegspunkt jeder evrtng Function. Die Plattform kümmert sich um Container, Skalierung, Logging und Monitoring. Du schreibst nur die Logik.
Wie wir eure Functions sicher ausführen

Jede Function-Ausführung in einem isolierten Kubernetes-Pod.
- Prozess-Isolation: Jede Function läuft in einem eigenen Prozess-Namespace. Kein Zugriff auf Speicher oder Dateien anderer Functions.
- Netzwerk-Isolation: Kein direkter Zugriff zwischen Containern möglich. Strikte Netzwerk-Policies verhindern laterale Bewegung.
- Kurzlebigkeit: Container werden nach jeder Ausführung zerstört. Kein persistenter Zustand, immer eine saubere Umgebung.
- Resource Limits: CPU, Memory und Ausführungszeit sind pro Container begrenzt. Eine Runaway Function kann den Host nicht beeinträchtigen.
Warm Containers
Wenn der Invoker eine Nachricht aus Kafka erhält, prüft er zunächst, ob ein warmer Container verfügbar ist. Warm bedeutet: bereits initialisiert mit der richtigen Runtime, bereit zur sofortigen Code-Ausführung. Das reduziert Cold Starts erheblich – oft von mehreren Sekunden auf zweistellige Millisekunden. Ist kein warmer Container vorhanden, wird ein neuer gespawnt und der Code über eine interne HTTP-Schnittstelle injiziert.
Der Warm-Container-Mechanismus macht OpenWhisk – und damit evrtng Functions – konkurrenzfähig bei der Latenz. Häufig aufgerufene Functions profitieren massiv, da ihre Container im Pool gehalten werden. Selten genutzte Functions werden on-demand erzeugt. Das ist ein guter Kompromiss zwischen Performance und Ressourceneffizienz – und einer der Gründe, warum wir uns für diese Architektur entschieden haben.
