Zum Inhalt springen

Ratenbegrenzung

Queuety unterstützt Ratenbegrenzungen pro Handler, um eine Überlastung externer APIs oder anderer begrenzter Ressourcen zu vermeiden. Hat ein Handler sein Limit erreicht, lassen Worker seine Jobs warten und übernehmen sie erneut, sobald im Zeitfenster wieder Kapazität verfügbar ist.

Ratenlimit festlegen

Wende beim Dispatchen eines Jobs ein Ratenlimit an:

PHP
use Queuety\Queuety;

Queuety::dispatch( 'call_openai', $payload )
    ->rate_limit( 10, 60 ); // max 10 executions per 60 seconds

Die beiden Argumente sind:

  1. $max – Maximale Anzahl von Ausführungen im Zeitfenster
  2. $window – Dauer des Zeitfensters in Sekunden

Ein beim Dispatch festgelegtes Limit wird nur im Prozess PHP registriert, der den Job dispatcht. Ein Worker in einem separaten Prozess, etwa wp queuety work, sieht es nicht. Limits, die prozessübergreifend gelten müssen, solltest du deshalb wie unten gezeigt in der Methode config() des Handlers festlegen (#3).

Ratenlimits auf Handler-Ebene

Lege Ratenlimits in der Methode config() des Handlers fest, damit sie für jeden Dispatch gelten:

PHP
use Queuety\Handler;

class CallOpenAIHandler implements Handler {
    public function handle( array $payload ): void {
        // Call the API...
    }

    public function config(): array {
        return [
            'rate_limit' => [ 60, 60 ], // 60 requests per minute
        ];
    }
}

So funktioniert es

Ratenlimits werden pro Handler-Namen erfasst. Nachdem ein Job übernommen wurde, registriert der Worker das Limit des Handlers (aus config()) und prüft den Ratenbegrenzer. Hat der Handler sein Limit erreicht, stellt der Worker den Job ohne Verzögerung wieder in pending ein, verbraucht keinen Versuch und wartet dann QUEUETY_WORKER_SLEEP Sekunden, bevor er erneut abfragt. Ein Worker, der mit --once gestartet wurde, wird stattdessen beendet.

Jeder Worker führt einen Zähler im Speicher und aktualisiert ihn alle 5 Sekunden anhand der Tabelle queuety_logs. Dabei zählt er die completed-Protokolleinträge des Handlers aus den letzten $window Sekunden. Da die Zählung aus der gemeinsam genutzten Protokolltabelle stammt (und gegebenenfalls aus dem gemeinsamen Cache), gelten Limits auf Handler-Ebene für alle Worker-Prozesse, nicht nur für einen einzelnen Worker. Fehlgeschlagene Ausführungen zählen nicht zum Limit.

Programmatischer Zugriff

Greife direkt auf den Ratenbegrenzer zu:

PHP
$limiter = Queuety::rate_limiter();

// Register a rate limit
$limiter->register( 'call_openai', 60, 60 );

// Check whether a handler has reached its limit
$limited = $limiter->is_limited( 'call_openai' ); // true while the limit is reached

// Seconds until the current window resets
$wait = $limiter->time_until_available( 'call_openai' );

register() und is_limited() wirken auf den Begrenzer im aktuellen Prozess PHP. Ein hier registriertes Limit ändert nicht, was ein separat laufender Worker durchsetzt.

Anwendungsfälle

  • Externe API-Limits. Stimme dein Ratenlimit auf das Kontingent von API ab (e.g., 60 RPM bei OpenAI).
  • E-Mail-Drosselung. Verhindere, dass innerhalb kurzer Zeit zu viele E-Mails versendet werden.
  • Ressourcenschutz. Begrenze CPU-intensive Handler, damit sie andere Jobs nicht verdrängen.