【问题标题】:Redis throttling Laravel job "has been attempted too many times or run too long"Redis 限制 Laravel 作业“尝试次数过多或运行时间过长”
【发布时间】:2020-07-30 14:52:19
【问题描述】:

我想使用带有 Redis 的 Laravel Queue 发送带有 nexmo 的短信,但是有些作业失败了,我不明白为什么。 在我的本地环境中,我每 10 秒发送 1 条短信,所以这是我工作的处理方法:

public function handle()
    { 
        Redis::throttle('throttle:sms')->allow(1)->every(10)->then(function(){
            Log::info($this->notifId." start : ".date('H:m:s'));
            try{
                $before = microtime(true);
                $response = Nexmo::message()->send([
                                'to'   => $this->to,
                                'from' => '16105552344',
                                'text' => $this->message
                            ]);
                $notif = NotificationHistory::find($this->notifId);
                $notif->nexmo_message_id=$response->getMessageId();
                $notif->save();

                $after = microtime(true);
                Log::info(($after-$before)." sec\n");
            }catch(Exeption $e){
                log::warning($e);
            }
        },function($error){
            Log::error($error);
            return $this->release(10);//release job in X second
        });
    }

但是当我达到尝试次数限制时,我得到了一些 Illuminate\Contracts\Redis\LimiterTimeoutException 和最后的 MaxAttemptsExceededException

我以php artisan queue:work --queue=sms --timeout=60 开始我的工作人员 我像这样派遣我的工作:

foreach($someEntities as $entitiy) {
            $notif = new NotificationHistory();
            $notif->notifiable()->associate($entity);
            $notif->message=$entity->message;
            $notif->status=NotificationHistory::$statusList[-1];
            $notif->save();
            dispatch(new SendSMS($entity->message."_".$notif->id,$entity->phone,$notif->id))->onConnection('redis')->onQueue('sms');
    }

当尝试发送 8 条短信时,前 5 条或 6 条有效,但其他的却例外。

编辑 如果没有nexmo,我也会遇到同样的错误:

public function handle()
    { 
        Redis::throttle('throttle:sms')->allow(1)->every(10)->then(function(){
            Log::info($this->notifId." startAt : ".date('H:m:s'));
        },function($error){
            Log::error($error);
            return $this->release(10);//release job in X second
        });
    }

【问题讨论】:

  • 您是否能够看到单个工作本身失败的原因? API 确实会限制每秒 30 次调用(尽管电话运营商施加了自己的限制,因此在我们接受消息后可能会发生内部限制)。 SDK 将尝试自我限制,但通常只有在您每秒执行 30 次以上 API 调用时才会发生这种情况。
  • @dragonmantank 现在,我将请求重定向到假端点,因此没有 API 限制。由于LimiterTimeoutException,个人请求多次失败,当他们失败太多次时,MaxAttemptsExceededException 被抛出。

标签: php laravel redis queue nexmo


【解决方案1】:

问题是强制尝试次数为 3 的“水平”文件。

队列工作者实际上并不是每 10 秒运行一次,如果队列中有东西,它会连续运行。 当它处理一个作业时,如果它在过去 10 秒内已经处理了一个作业,它将从队列中删除它的当前作业并在 X 秒内将其放回(在release(x) 中定义),生成一个LimiterTimeoutException 并增加它的尝试价值。 所以当工人在同一个工作上达到 3 次尝试时,它就会失败。

【讨论】:

    猜你喜欢
    • 2019-04-04
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多