コンテンツへスキップ

レート制限

Queuetyは、外部APIやその他の制約があるリソースへの過負荷を防ぐため、ハンドラーごとのレート制限に対応しています。ハンドラーが上限に達すると、ワーカーはそのジョブを保留し、ウィンドウに空きができたら再び取得します。

レート制限の設定

ジョブのディスパッチ時にレート制限を適用します。

PHP
use Queuety\Queuety;

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

引数は次の2つです。

  1. $max - ウィンドウ内で許可される実行の最大数
  2. $window - ウィンドウの時間(秒)

ディスパッチ時の上限は、ジョブをディスパッチするPHPプロセスにのみ登録されます。wp queuety workのように別プロセスで動作するワーカーからは見えないため、プロセス間で適用する上限は、以下のようにハンドラーのconfig()に設定してください(#3)。

ハンドラー単位のレート制限

ハンドラーのconfig()メソッドにレート制限を設定すると、すべてのディスパッチに適用されます。

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
        ];
    }
}

仕組み

レート制限はハンドラー名ごとに追跡されます。ジョブを取得した後、ワーカーはハンドラーの上限(config()から取得)を登録し、レートリミッターを確認します。上限に達している場合、ワーカーは遅延も試行回数の消費もなく、ジョブをpendingに戻してからQUEUETY_WORKER_SLEEP秒間待機し、再度ポーリングします。--onceを指定して起動したワーカーは、代わりに終了します。

各ワーカーはメモリ内カウンターを保持し、5秒ごとにqueuety_logsテーブルから更新します。このカウンターは、過去$window秒間におけるそのハンドラーのcompletedログエントリー数を数えます。カウントは共有ログテーブル(および設定されている場合は共有キャッシュ)から取得するため、ハンドラー単位の制限は1つのワーカー内だけでなく、すべてのワーカープロセスに適用されます。失敗した実行は上限に含まれません。

プログラムからのアクセス

レートリミッターに直接アクセスします。

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()とis_limited()は、現在のPHPプロセス内のリミッターに作用します。ここで上限を登録しても、別途実行中のワーカーが適用する制限は変わりません。

活用例

  • 外部APIの制限。 レート制限をAPIのクォータ(e.g例:OpenAIの60 RPM)に合わせます。
  • メール送信の抑制。 短時間に大量のメールを送信するのを防ぎます。
  • リソースの保護。 CPU負荷の高いハンドラーを制限し、他のジョブが滞らないようにします。