AI Engineering Academy · Lekcja

Równoważenie obciążenia i strategie wielu kluczy

Zaimplementuj równoważenie obciążenia round-robin i ważone między wieloma kluczami oraz kontami API, aby zwiększyć dostępny limit zapytań i ograniczyć skoki opóźnienia p99.

Lekcja 2 z 413 kroki

Równoważenie obciążenia i strategie wielu kluczy to bezpłatna lekcja AI Engineering Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Engineering Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.

Dlaczego jeden klucz API nie wystarcza

Pojedynczy klucz OpenAI API ma stały limit szybkości mierzony w żądaniach na minutę (RPM) i tokenach na minutę (TPM). W Tier 1 GPT-4o obsługuje 500 RPM i 30 000 TPM. W aplikacji produkcyjnej obsługującej setki równoczesnych użytkowników pojedynczy klucz będzie stale osiągać te limity. Wiele kluczy API proporcjonalnie zwiększa dostępny zapas przepustowości.

Tworzenie wielu kluczy API

Możesz utworzyć wiele kluczy API w ramach jednej organizacji OpenAI albo utworzyć wiele kont OpenAI (każde rozliczane osobno). Przechowuj każdy klucz w konfiguracji środowiska i traktuj je jako pulę. Klucze przechowuj w menedżerze sekretów, takim jak AWS Secrets Manager lub HashiCorp Vault, zamiast w kodzie źródłowym lub plikach .env zapisanych w systemie kontroli wersji.

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

Równoważenie obciążenia round-robin

Round-robin równomiernie rozdziela żądania między wszystkie klucze, wybierając je cyklicznie w ustalonej kolejności. Jest proste w implementacji i zapewnia, że każdy klucz obsługuje z czasem mniej więcej takie samo obciążenie. Użyj licznika bezpiecznego wątkowo lub liczby atomowej, aby uniknąć sytuacji, w której dwa równoczesne żądania wybiorą jednocześnie ten sam klucz. Round-robin sprawdza się dobrze, gdy wszystkie klucze mają identyczne limity szybkości.

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()

Ważone równoważenie obciążenia

Ważone równoważenie obciążenia przydziela kluczom wyższego poziomu (z wyższymi limitami szybkości) większą część ruchu, proporcjonalnie do ich przepustowości. Jeśli klucz A ma Tier 3 (10 000 RPM), a klucz B Tier 1 (500 RPM), klucz A powinien otrzymywać około 95% żądań. Ważone równoważenie zapobiega powstawaniu wąskich gardeł przez klucze niższego poziomu, gdy są używane razem z kluczami wyższego poziomu.

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},
])

Śledzenie stanu limitów szybkości dla poszczególnych kluczy

OpenAI API zwraca przy każdej odpowiedzi nagłówki limitów szybkości: x-ratelimit-remaining-requests i x-ratelimit-remaining-tokens. Śledź te nagłówki dla każdego klucza, aby wiedzieć, które klucze są bliskie wyczerpania. Gdy klucz zgłasza mniej niż 10 pozostałych żądań w bieżącej minucie, tymczasowo kieruj ruch z dala od niego, aby zapobiec błędom 429, zanim wystąpią.

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

Obsługa błędów limitu szybkości 429

Gdy klucz zwróci błąd 429, natychmiast wycofaj go z puli na czas określony w nagłówku Retry-After (zwykle 60 sekund). Oznacz go jako znajdujący się w stanie schładzania i kieruj cały ruch do pozostałych kluczy. Po upływie okresu schładzania przywróć klucz do puli. Zapobiega to awariom kaskadowym, w których ponawianie prób z użyciem tego samego klucza pogarsza sytuację.

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')

Używanie OpenRouter jako multipleksera

OpenRouter to usługa proxy udostępniająca setki modeli za pośrednictwem pojedynczego endpointu API zgodnego z OpenAI. Kierowanie ruchu przez OpenRouter zapewnia automatyczne równoważenie obciążenia między wieloma kontami dostawców, przełączanie awaryjne na alternatywnych dostawców oraz dostęp do modeli open source jako kopii zapasowych. Niewielka marża jest ceną za oferowaną prostotę operacyjną.

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

Monitorowanie kondycji kluczy za pomocą metryk

Śledź metryki dla poszczególnych kluczy, w tym liczbę wysłanych żądań, otrzymanych błędów 429 oraz czas schładzania w ciągu ostatniej godziny. Klucz z wysokim odsetkiem błędów 429 wymaga ograniczenia ruchu albo podwyższenia poziomu. Udostępnij te metryki w endpointcie /metrics w formacie Prometheus, aby system monitorowania mógł generować alerty, gdy którykolwiek klucz stale osiąga limity.

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')

Geograficzna dystrybucja kluczy

Jeśli użytkownicy są rozproszeni globalnie, rozważ utrzymywanie osobnych kluczy API dla poszczególnych regionów geograficznych i kierowanie żądań do klucza znajdującego się najbliżej użytkownika. Skrócenie czasu podróży w obie strony przez sieć poprawia TTFT. Wdróż w każdym regionie lekki load balancer (AWS Lambda@Edge lub Cloudflare Worker), który wybiera odpowiedni klucz i przekazuje żądanie, chroniąc klucze przed ujawnieniem klientom.

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'])

Testowanie load balancera

Napisz test obciążeniowy, który wysyła 100 równoczesnych żądań przez pulę równoważącą i mierzy rozkład, wskaźniki błędów oraz percentyle opóźnienia. Sprawdź, czy żaden pojedynczy klucz nie obsługuje więcej niż przypadająca na niego proporcjonalna część ruchu oraz czy liczba błędów 429 jest niższa niż 0,1%. Użyj asyncio.gather lub narzędzia takiego jak Locust, aby zasymulować równoczesne obciążenie, którego rzeczywiście będzie doświadczać system produkcyjny.

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

Wybór właściwej strategii równoważenia

Dopasuj strategię równoważenia do struktury limitów szybkości. Użyj round-robin, gdy wszystkie klucze mają identyczne limity poziomów, a ruch jest równomiernie rozłożony. Użyj ważonego równoważenia, gdy klucze mają różne limity poziomów. Użyj routingu uwzględniającego kondycję (pomijania kluczy bliskich wyczerpania), gdy chcesz ograniczyć liczbę błędów 429 przy skokowym ruchu. W większości systemów produkcyjnych routing uwzględniający kondycję wraz z wykładniczym narastaniem opóźnienia zapewnia najlepszy kompromis między prostotą a odpornością.

# 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

Szybki sprawdzian

Sprawdź swoją wiedzę na temat strategii równoważenia obciążenia dla API LLM.

Podsumowanie lekcji

W tej lekcji poznano: round-robin i ważone równoważenie rozdzielają ruch między wiele kluczy API, zwiększając zapas dostępnego limitu szybkości, śledzenie schładzania zapobiega kaskadowym błędom 429, tymczasowo usuwając ograniczone klucze, a OpenRouter zapewnia zarządzaną opcję multipleksowania z automatycznym przełączaniem awaryjnym. W następnej części zaimplementujemy dostawców zapasowych i bezpieczniki obwodu.

Bezpłatny start

Ucz się Python dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
30
Lekcje
120

Często zadawane pytania

Czy lekcja „Równoważenie obciążenia i strategie wielu kluczy” jest bezpłatna?

Tak — pełny tekst „Równoważenie obciążenia i strategie wielu kluczy” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Engineering Academy, przejdź na CoddyKit PRO. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Równoważenie obciążenia i strategie wielu kluczy”?

Zaimplementuj równoważenie obciążenia round-robin i ważone między wieloma kluczami oraz kontami API, aby zwiększyć dostępny limit zapytań i ograniczyć skoki opóźnienia p99. Ćwiczysz AI Engineering Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć AI Engineering Academy?

Nie wymagamy żadnego doświadczenia. AI Engineering Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Równoważenie obciążenia i strategie wielu kluczy”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji AI Engineering Academy?

Tak. Każda lekcja AI Engineering Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Pomiar opóźnienia LLM: TTFT i TPOT
  2. Równoważenie obciążenia i strategie wielu kluczy
  3. Dostawcy zapasowi i circuit breakers
  4. Budżety czasu oczekiwania i kontrolowana degradacja
← Powrót do AI Engineering Academy