Umut ABALI
← Projelere dön

Inference Worker Lab

Kuyrukla ayrılmış çıkarım: FastAPI gateway, Redis Streams worker'ları (mock veya vLLM), idle-claim kurtarma, sınırlı retry ve lag/pending autoscaler.

Problem

Worker çökse de çıkarım isteklerinin nasıl yaşadığını gösteren bir lab istedim: idle pending kayıtlarını geri almak, sonuç zaten succeeded ise modeli iki kez çağırmamak, retry'ları DLQ ile sınırlamak ve claimed işi düşürmeden lag'e göre ölçeklemek.

Mimari

Inference Worker Lab mimari diyagramıXADDlag / pendingClientAPI :8080FastAPI · /v1/jobsRedis Streaminference:jobs · group workersworker-1MOCK | VLLMworker-2worker-Nscalerlag + PEL · hysteresis
inference-worker-lab README'den: istemci → FastAPI → Redis Stream → worker'lar; scaler lag ve PEL'i izler.
  • POST /v1/jobs, inference:jobs akışına XADD eder (consumer group: workers). GET /v1/jobs/{id} sonuç anahtarlarını okur; GET /v1/scale scaler görünümünü verir.
  • Worker'lar IWL_CLAIM_IDLE_MS (varsayılan 30 sn) idle kalan mesajları XAUTOCLAIM eder. XREADGROUP sonrası XACK öncesi çöküşü başka worker alır. Sonuç anahtarı zaten succeeded ise reclaim ack eder ve modeli yeniden çağırmaz.
  • Başarısız deneme attempt+1 ile yeniden XADD edilir, eski id ack edilir. IWL_MAX_ATTEMPTS'te iş failed işaretlenir ve inference:dlq'ya eklenir. Bu XADD ile XACK arasında çöküş iki kopya bırakabilir; ikisi de çalışabilir (at-least-once, exactly-once değil).
  • POST /v1/jobs idempotency_key kabul eder: aynı anahtar aynı job_id'yi döner, ikinci stream kaydı eklemez (anahtar yazıldıktan sonra XADD öncesi bir çöküş penceresi vardır). Bitmemiş iş (lag) IWL_MAX_QUEUE_DEPTH'e (varsayılan 10000; 0 kapatır) ulaşınca enqueue 429 döner.
  • Scaler, never-delivered lag ve PEL pending kullanır; hysteresis uygular. Container başlatmaz/durdurmaz; desired sayıyı yazar. worker-N kimlikli worker, N-1 >= desired iken idle kalır.
  • MOCK (varsayılan) sabit gecikme + token echo kullanır. VLLM modu OpenAI uyumlu chat completions çağırır.

Tasarım kararları

Çöküş kurtarma için XAUTOCLAIM

Idle pending kayıtlar CLAIM_IDLE_MS sonra claim edilir. Succeeded sonuçlar reclaim'i kısayollar; model iki kez çağrılmaz.

Ödünleşim: At-least-once: retry XADD ile XACK arasında çöküş, ikisi de çalışabilen kopyalar bırakabilir.

Ölçeklemede lag ve pending

Scale-up never-delivered lag veya claim edilip ack edilmemiş in-flight ile olabilir. Scale-down yalnızca lag SCALE_DOWN_LAG veya altında ve pending 0 iken.

Ödünleşim: Claim'li iş varken küçülmeyi engeller; scaler container orkestre etmez.

Maksimum kuyruk derinliğinde 429

Bitmemiş iş IWL_MAX_QUEUE_DEPTH'e gelince enqueue HTTP 429 ile reddeder.

Ödünleşim: İstemciye açık backpressure; derinlik 0 limiti kapatır.

Teknolojiler

PythonFastAPIRedis StreamsPrometheusDocker ComposevLLM (optional)

Sırada ne var

  • Retry XADD/XACK penceresinde exactly-once veya daha güçlü dedupe.
  • Gerçek vLLM backend ile GPU / compose profil ölçümleri (pytest GPU'yu atlar).

Sonuçlar

pytest (MemoryRedis + dinliyorsa gerçek Redis 7.0.15'te 2 test)
26
mock queue_to_done p95 (80 iş, concurrency 4, 5 ms backend; GPU/üretim değil)
~214 ms
vLLM uçtan uca gecikmeBenchmark yakında