使用Laravel任务与队列限制外部API请求频率
在Laravel 6中实现Job调用外部API的10秒频率限制
下面给你两种实用的实现方式,可根据业务场景选择:
方法一:在Job内部通过缓存控制调用频率
适合单Job需要自主控制调用间隔的场景,每次Job执行时先校验调用条件,不满足则延迟重新入队:
<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Cache; class CallExternalApiJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function handle() { // 缓存键,用于记录上次API调用时间 $cacheKey = 'last_external_api_call'; $lastCallTime = Cache::get($cacheKey); // 检查距离上次调用是否不足10秒 if ($lastCallTime && now()->diffInSeconds($lastCallTime) < 10) { // 计算延迟时长,重新入队 $delay = 10 - now()->diffInSeconds($lastCallTime); $this->release($delay); return; } // 执行外部API调用逻辑 $this->callExternalApi(); // 更新缓存,记录本次调用时间,有效期设为15秒(避免缓存过期导致重复调用) Cache::put($cacheKey, now(), 15); } private function callExternalApi() { // 这里编写你的API调用代码,例如用Guzzle发送请求 // $client = new \GuzzleHttp\Client(); // $response = $client->get('https://your-external-api.com/endpoint'); } }
方法二:通过任务调度定时触发Job
如果需求是固定每10秒执行一次API调用,直接用Laravel任务调度触发Job更稳妥,避免队列堆积大量延迟任务:
- 在
app/Console/Kernel.php的schedule方法中添加调度规则:
protected function schedule(Schedule $schedule) { // 每10秒调度一次API调用Job $schedule->job(new \App\Jobs\CallExternalApiJob())->everyTenSeconds(); }
- 确保服务器配置了Laravel调度器的Cron任务,在服务器Cron中添加:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
这种方式下,Job只需专注编写API调用逻辑,频率控制由调度器自动处理。
注意事项
- 方法一需确保队列驱动支持延迟任务(Redis、数据库驱动均支持,sync驱动不支持)。
- 缓存建议使用Redis或Memcached,避免多进程环境下的时间校验误差。
- 若API调用失败需要重试,可在Job类中添加
public $tries = 3;设置重试次数。
内容的提问来源于stack exchange,提问作者xnor
相关产品推荐
相关产品推荐

