AI Engineering Academy · Lektion

Load balancing og strategier med flere nøgler

Implementér round-robin- og vægtet load balancing på tværs af flere API-nøgler og konti for at udvide Deres kapacitet inden for hastighedsgrænserne og reducere p99-latenstidsspidser.

Lektion 2 af 413 trin

Load balancing og strategier med flere nøgler er en gratis AI Engineering Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i AI Engineering Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. AI Engineering Academy-kurset indeholder 4 lektioner i alt.

Hvorfor én API-nøgle ikke er nok

En enkelt OpenAI API-nøgle har en fast hastighedsgrænse målt i anmodninger pr. minut (RPM) og tokens pr. minut (TPM). På niveau 1 tillader GPT-4o 500 RPM og 30.000 TPM. For en produktionsapplikation med hundredvis af samtidige brugere vil en enkelt nøgle konstant ramme disse grænser. Flere API-nøgler øger din tilgængelige kapacitet proportionalt.

Oprettelse af flere API-nøgler

Du kan oprette flere API-nøgler i én OpenAI-organisation eller oprette flere OpenAI-konti (som faktureres separat). Gem hver nøgle i din miljøkonfiguration, og behandl dem som en pulje. Opbevar nøglerne i en hemmelighedshåndteringstjeneste som AWS Secrets Manager eller HashiCorp Vault i stedet for i kildekoden eller .env-filer, der er gemt i versionsstyringen.

import os

API_KEYS = [
    os.environ['OPENAI_KEY_1'],
    os.environ['OPENAI_KEY_2'],
    os.environ['OPENAI_KEY_3'],
    os.environ['OPENAI_KEY_4'],
]

# Total effective RPM = 500 * 4 = 2000 RPM
# Total effective TPM = 30000 * 4 = 120000 TPM

Belastningsfordeling med round-robin

Round-robin fordeler anmodninger jævnt på tværs af alle nøgler ved at gå gennem dem i rækkefølge igen og igen. Det er enkelt at implementere og sikrer, at hver nøgle håndterer omtrent samme belastning over tid. Brug en trådsikker tæller eller et atomisk heltal for at undgå, at to samtidige anmodninger vælger den samme nøgle på samme tid. Round-robin fungerer godt, når alle nøgler har identiske hastighedsgrænser.

import itertools
import threading
from openai import OpenAI

class RoundRobinPool:
    def __init__(self, keys: list):
        self._clients = [OpenAI(api_key=k) for k in keys]
        self._cycle = itertools.cycle(range(len(self._clients)))
        self._lock = threading.Lock()

    def get_client(self) -> OpenAI:
        with self._lock:
            idx = next(self._cycle)
        return self._clients[idx]

pool = RoundRobinPool(API_KEYS)
client = pool.get_client()

Vægtet belastningsfordeling

Vægtet belastningsfordeling tildeler nøgler på højere niveauer (med højere hastighedsgrænser) en større andel af trafikken i forhold til deres kapacitet. Hvis nøgle A er på niveau 3 (10.000 RPM), og nøgle B er på niveau 1 (500 RPM), bør nøgle A modtage ca. 95 % af anmodningerne. Vægtet fordeling forhindrer nøgler på lavere niveauer i at blive flaskehalse, når de bruges sammen med nøgler på højere niveauer.

import random

class WeightedPool:
    def __init__(self, key_configs: list):
        # key_configs = [{'key': '...', 'weight': 10}, ...]
        self._clients = [OpenAI(api_key=c['key']) for c in key_configs]
        self._weights = [c['weight'] for c in key_configs]

    def get_client(self) -> OpenAI:
        return random.choices(self._clients, weights=self._weights, k=1)[0]

pool = WeightedPool([
    {'key': os.environ['OPENAI_KEY_TIER3'], 'weight': 20},
    {'key': os.environ['OPENAI_KEY_TIER1'], 'weight': 1},
])

Sporing af hastighedsgrænsens status pr. nøgle

OpenAI API'en returnerer headere med oplysninger om hastighedsgrænsen sammen med hvert svar: x-ratelimit-remaining-requests og x-ratelimit-remaining-tokens. Spor disse headere pr. nøgle, så du ved, hvilke nøgler der nærmer sig udtømning. Når en nøgle angiver færre end 10 resterende anmodninger i det aktuelle minut, skal du midlertidigt lede trafikken væk fra den for at forhindre 429-fejl, før de opstår.

class SmartPool:
    def __init__(self, keys: list):
        self._clients = [OpenAI(api_key=k) for k in keys]
        self._remaining = {i: 500 for i in range(len(keys))}  # initial RPM

    def get_best_client(self):
        # Pick key with most remaining capacity
        best_idx = max(self._remaining, key=lambda i: self._remaining[i])
        return self._clients[best_idx], best_idx

    def update_remaining(self, idx: int, response_headers: dict):
        remaining = int(response_headers.get('x-ratelimit-remaining-requests', 0))
        self._remaining[idx] = remaining

Håndtering af 429-fejl for hastighedsgrænsen

Når en nøgle returnerer en 429-fejl, skal du straks fjerne nøglen fra puljen i det tidsrum, der angives i Retry-After-headeren (typisk 60 sekunder). Markér den som under afkøling, og led al trafik til de resterende nøgler. Når afkølingsperioden udløber, skal du føje nøglen til puljen igen. Det forhindrer kaskadefejl, hvor gentagne forsøg på den samme nøgle forværrer situationen.

import time
from openai import RateLimitError

class CooldownPool:
    def __init__(self, keys: list):
        self._clients = [(OpenAI(api_key=k), None) for k in keys]  # (client, cooldown_until)

    def get_available_clients(self):
        now = time.time()
        return [
            (i, c) for i, (c, until) in enumerate(self._clients)
            if until is None or until <= now
        ]

    def mark_cooling(self, idx: int, retry_after: int = 60):
        client, _ = self._clients[idx]
        self._clients[idx] = (client, time.time() + retry_after)
        print(f'Key {idx} cooling down for {retry_after}s')

Brug af OpenRouter som multiplekser

OpenRouter er en proxytjeneste, der stiller hundredvis af modeller til rådighed gennem ét OpenAI-kompatibelt API-endepunkt. Ved at sende trafikken gennem OpenRouter får du automatisk belastningsfordeling på tværs af flere underliggende udbyderkonti, skift til alternative udbydere og adgang til open source-modeller som sikkerhedskopier. Prisforhøjelsen er lille i forhold til den driftsmæssige enkelhed, tjenesten giver.

from openai import OpenAI

# OpenRouter uses the same OpenAI SDK interface
client = OpenAI(
    api_key=os.environ['OPENROUTER_API_KEY'],
    base_url='https://openrouter.ai/api/v1'
)

response = client.chat.completions.create(
    model='openai/gpt-4o',  # OpenRouter model name format
    messages=[{'role': 'user', 'content': prompt}]
)
# Automatic failover if OpenAI is down

Overvågning af nøglesundhed med målinger

Spor målinger pr. nøgle, herunder sendte anmodninger, modtagne 429-fejl og afkølingstid i den seneste time. En nøgle med en høj 429-rate har brug for enten reduceret trafik eller en opgradering af niveauet. Eksponér disse målinger på et /metrics-endepunkt i Prometheus-format, så dit overvågningssystem kan sende en alarm, når en nøgle konsekvent rammer grænserne.

from dataclasses import dataclass, field
from collections import defaultdict

@dataclass
class KeyMetrics:
    requests_sent: int = 0
    rate_limit_errors: int = 0
    total_tokens_used: int = 0
    cooldown_count: int = 0

class MetricPool:
    def __init__(self, keys: list):
        self._clients = [OpenAI(api_key=k) for k in keys]
        self._metrics = [KeyMetrics() for _ in keys]

    def report(self):
        for i, m in enumerate(self._metrics):
            error_rate = m.rate_limit_errors / max(m.requests_sent, 1)
            print(f'Key {i}: {m.requests_sent} req, {error_rate:.1%} 429 rate')

Geografisk fordeling af nøgler

Hvis dine brugere er spredt globalt, bør du overveje at vedligeholde separate API-nøgler pr. geografisk region og sende anmodninger til den nøgle, der er tættest på brugeren. En kortere netværksrundtur forbedrer TTFT. Implementér en let belastningsfordeler i hver region (AWS Lambda@Edge eller Cloudflare Worker), som vælger den relevante nøgle og videresender anmodningen, så dine nøgler ikke eksponeres for klienterne.

REGIONAL_KEYS = {
    'us-east': os.environ['OPENAI_KEY_US_EAST'],
    'eu-west': os.environ['OPENAI_KEY_EU_WEST'],
    'ap-southeast': os.environ['OPENAI_KEY_AP'],
}

def get_key_for_region(user_region: str) -> str:
    # Default to us-east if region unknown
    return REGIONAL_KEYS.get(user_region, REGIONAL_KEYS['us-east'])

Test af din belastningsfordeler

Skriv en belastningstest, der sender 100 samtidige anmodninger gennem din fordelingspulje og måler fordeling, fejlrater og latenstidspercentiler. Kontrollér, at ingen enkelt nøgle håndterer mere end sin proportionelle andel, og at 429-fejlene er under 0,1 %. Brug asyncio.gather eller et værktøj som Locust til at simulere den samtidige belastning, som dit produktionssystem faktisk vil opleve.

import asyncio
import time

async def load_test(pool, concurrency=100, total=1000):
    sem = asyncio.Semaphore(concurrency)
    results = []

    async def one_request():
        async with sem:
            client = pool.get_client()
            start = time.perf_counter()
            try:
                await client.chat.completions.create(
                    model='gpt-4o-mini',
                    messages=[{'role': 'user', 'content': 'Ping'}],
                    max_tokens=5
                )
                results.append(('ok', time.perf_counter() - start))
            except Exception as e:
                results.append(('error', str(e)))

    await asyncio.gather(*[one_request() for _ in range(total)])
    ok = [r for r in results if r[0] == 'ok']
    print(f'Success rate: {len(ok)/total:.1%}')
    return results

Valg af den rette fordelingsstrategi

Tilpas din fordelingsstrategi til strukturen for dine hastighedsgrænser. Brug round-robin, når alle nøgler har identiske niveaubegrænsninger, og trafikken er jævnt fordelt. Brug vægtet fordeling, når nøglerne har forskellige niveaubegrænsninger. Brug sundhedsbevidst routing (hvor nøgler tæt på udtømning springes over), når du vil minimere 429-fejl under trafikspidser. For de fleste produktionssystemer giver sundhedsbevidst routing med eksponentiel backoff den bedste balance mellem enkelhed og robusthed.

# Strategy selection guide:
# Scenario A: 4 keys all Tier 2 (same limits)
#   -> Round-robin: simple, even distribution
#
# Scenario B: 1 Tier 3 key + 3 Tier 1 keys
#   -> Weighted: Tier 3 gets 10x weight
#
# Scenario C: Variable traffic with burst periods
#   -> Health-aware: track remaining headers, skip near-limit keys
#
# Scenario D: Multi-region, latency-sensitive
#   -> Geographic: regional keys, route by user location

Hurtigt tjek

Test din forståelse af strategier til belastningsfordeling for LLM-API'er.

Opsummering af lektionen

I denne lektion lærte du, at round-robin og vægtet fordeling fordeler trafik på tværs af flere API-nøgler og dermed øger den tilgængelige kapacitet under hastighedsgrænserne, at sporing af afkøling forhindrer kaskadefejl med 429-fejl ved midlertidigt at fjerne begrænsede nøgler, og at OpenRouter tilbyder en administreret multipleksløsning med automatisk skift til en reserve. I næste afsnit implementerer vi reserveudbydere og kredsløbsafbrydere.

Gratis at komme i gang

Lær Python med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
30
Lektioner
120

Ofte stillede spørgsmål

Er lektionen “Load balancing og strategier med flere nøgler” gratis?

Ja — hele teksten til “Load balancing og strategier med flere nøgler” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af AI Engineering Academy-kurset, skal du opgradere til CoddyKit PRO. AI Engineering Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Load balancing og strategier med flere nøgler”?

Implementér round-robin- og vægtet load balancing på tværs af flere API-nøgler og konti for at udvide Deres kapacitet inden for hastighedsgrænserne og reducere p99-latenstidsspidser. Du øver dig i AI Engineering Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på AI Engineering Academy?

Der kræves ingen tidligere erfaring. AI Engineering Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Load balancing og strategier med flere nøgler”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne AI Engineering Academy-lektion?

Ja. Alle AI Engineering Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Måling af LLM-latenstid: TTFT og TPOT
  2. Load balancing og strategier med flere nøgler
  3. Fallback-udbydere og circuit breakers
  4. Timeoutbudgetter og kontrolleret forringelse
← Tilbage til AI Engineering Academy