Blog von Obi Madu
Zurück zu allen Artikeln
System DesignInfrastructureBackend

API-Schlüssel-Pooling mit Bifrost

Ein praktischer Leitfaden zur Konfiguration von API-Key-Pooling in Bifrost und zur sicheren Skalierung über mehrere Knoten durch Externalisierung der Rate Limits.

API-Schlüssel-Pooling mit Bifrost

Bifrost ist ein schneller, Go-basierter AI Gateway. Wenn man bei seinem LLM-Provider an Rate Limits stößt und mehrere API-Schlüssel bündeln muss, um den Durchsatz zu erhöhen, bietet Bifrost eine native, performante Routing-Engine, um das Load Balancing zu übernehmen.

Ein einzelner Bifrost-Knoten mit Key-Pooling zu konfigurieren ist jedoch einfach; dieses Setup in Produktion über mehrere Knoten hinweg zu skalieren, erfordert sorgfältige architektonische Planung, um die Provider-Quotas nicht zu sprengen.

Hier ist genau beschrieben, wie man API-Schlüssel in Bifrost bündelt und dieses Setup sicher skaliert.

1. Konfigurieren des Key-Pooling in Bifrost

Bifrost erlaubt es, mehrere API-Schlüssel für einen einzelnen Provider zu definieren und ihnen Gewichtungen zuzuweisen. Die Routing-Engine verteilt eingehende Anfragen automatisch über diese Schlüssel, basierend auf deren Gewichtungen und Gesundheitsstatus.

Für ein GitOps-freundliches, zustandsloses Deployment konfiguriert man das über eine config.json-Datei, die in den Bifrost-Container gemountet wird.

{
  "$schema": "https://www.getbifrost.ai/schema",
  "providers": {
    "openai": {
      "keys": [
        {
          "name": "openai-key-primary",
          "value": "env.OPENAI_API_KEY_1",
          "models": ["gpt-4o", "gpt-4o-mini"],
          "weight": 0.7
        },
        {
          "name": "openai-key-secondary",
          "value": "env.OPENAI_API_KEY_2",
          "models": ["gpt-4o", "gpt-4o-mini"],
          "weight": 0.3
        }
      ]
    }
  }
}

In dieser Konfiguration fungiert Bifrost als smarter Router. Es sendet grob 70 % des Traffics an den primären Schlüssel und 30 % an den sekundären. Wenn der primäre Schlüssel ein 429 Too Many Requests von OpenAI erhält, markiert Bifrots interne Logik ihn vorübergehend als degradiert und leitet Traffic an den sekundären Schlüssel weiter.

2. Ausführen der Anfrage

Aus dem Anwendungscode heraus behandelt man Bifrost genau wie die Standard-OpenAI-API. Man muss keine Routing-Logik in die App einbauen.

Man zeigt einfach mit der baseURL des SDKs auf die Bifrost-Instanz und gibt einen Platzhalter-API-Schlüssel an (oder einen Virtual Key, wenn man Governance aktiviert hat).

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: "vk-my-bifrost-key", // The gateway authenticates this
  baseURL: "http://localhost:8080/v1" // Pointing to Bifrost
});

const response = await client.chat.completions.create({
  model: "openai/gpt-4o",
  messages: [{ role: "user", content: "Analyze this dataset..." }]
});

Bifrost fängt diese Anfrage ab, wählt anhand der Gewichtungen in config.json den passenden physischen API-Schlüssel aus, hängt ihn an die Header an und proxyt die Anfrage an OpenAI.

3. Die Multi-Knoten-Skalierungsfalle

Dieses Setup funktioniert für einen einzelnen, massiven Bifrost-Knoten. Das Problem entsteht, wenn man Hochverfügbarkeit braucht und auf mehrere Instanzen hinter einem Load Balancer skaliert.

Im Open-Source- (OSS) Bifrost fungiert jeder Knoten als unabhängige Entscheidungs-Engine.

  • Knoten A lädt die config.json und verfolgt die TPM/RPM-Nutzung von openai-key-primary in seinem lokalen Speicher.
  • Knoten B lädt dieselbe config.json und verfolgt seine eigene lokale Nutzung.

Da OSS-Bifrost den Laufzeitzustand (wie Live-Rate-Limits oder Token-Buckets) nicht in Echtzeit über Knoten hinweg synchronisiert, weiß Knoten A nicht, wie viele Token Knoten B gerade an OpenAI gesendet hat. Bei starkem gleichzeitigem Traffic überschreiten die Knoten kolleiv die physischen Provider-Limits, was zu Upstream-429-Fehlern und verworfenen Anfragen führt.

(Hinweis: Bifrost bietet einen kostenpflichtigen Enterprise-Tier, der ein modifiziertes RAFT-Konsens-Protokoll nutzt, um diesen Zustand zu synchronisieren. Hier konzentrieren wir uns aber auf die OSS-Architektur.)

4. Wie man es wirklich skaliert: Die Kontrollebene externalisieren

Wenn man OSS-Bifrost über mehrere Knoten hinweg nutzen will, ohne Limits zu überschreiten, muss man die 3-Schichten-Architektur anwenden. Man muss die "smarte" Quota-Erzwingung aus Bifrost herauslösen und an eine global koordinierte Kontrollebene externalisieren.

In dieser Architektur ist Bifrost rein eine Routing- und Ausführungs-Engine. Es wählt den Schlüssel und tätigt den Netzwerkaufruf.

Um globale Rate Limits zu erzwingen, platziert man ein dediziertes Quotasystem (wie OpenMeter oder ein Kong API Gateway mit Redis-basiertem Rate Limiting) vor Bifrost.

Der Ablauf:

  1. Die App sendet eine Anfrage an das Kong/Redis-Layer.
  2. Die Kontrollebene prüft Redis: Hat dieser Nutzer/dieses Team genug globale TPM-Kapazität über unsere gesamte Infrastruktur?
  3. Wenn ja, dekrementiert sie den globalen Zähler und leitet die Anfrage an den Bifrost-Load-Balancer weiter.
  4. Bifrost empfängt die Anfrage, nutzt seine internen Gewichtungen, um einen physischen API-Schlüssel auszuwählen, und führt den Aufruf aus.

Indem man die globale Quota-Erzwingung in Redis und das physische Key-Routing in Bifrost aufteilt, erhält man die schnelle Go-Proxy-Performance von Bifrost und behält dennoch korrekte Rate Limits über beliebig viele Knoten bei.

Im nächsten Beitrag betrachten wir, wie LiteLLM dieses genaue Problem behandelt, da es einen anderen Ansatz wählt, indem es Redis direkt in seine Open-Source-Proxy-Schicht bündelt.