跳转到正文

速率限制

Queuety 支持按处理器进行速率限制,以防止外部 API 或其他受限资源过载。处理器达到限制后,工作进程会让其作业保持待处理状态,并在窗口有空余时再次领取。

设置速率限制

分发作业时应用速率限制:

PHP
use Queuety\Queuety;

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

这两个参数分别是:

  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 日志条目。由于计数来自共享日志表(配置了共享缓存时也会读取共享缓存),处理器级限制会在所有工作进程间生效,而不只是在单个工作进程内生效。失败的执行不会计入限制。

编程方式访问

直接访问速率限制器:

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 较多的处理器,以免其他作业得不到资源。