搜尋

首頁  >  問答  >  主體

laravel 4 佇列使用beanstalkd,如何在failed時記錄到failed_job表

使用supervisor監聽佇列的job,

php artisan queue:listen --timeout=0

使用

php artisan queue:failed-table

建立了失敗的佇列記錄,但是現況是失敗的總是重複執行,並沒有寫入到failed_job

laravel文檔中有

php artisan queue:listen connection-name --tries=3

connection-name指的是什麼?

php artisan queue:listen --timeout=0 --tries=3時,佇列執行錯誤

exception 'Swift_TransportException' with message 'Expected response code 250 but got code "", with message ""'

這些問題該怎麼解決?

滿天的星座滿天的星座2738 天前768

全部回覆(2)我來回復

  • 高洛峰

    高洛峰2017-05-16 16:58:46

    在laravel中可以選擇多種隊列服務,常見的有redis和beanstalk,由於redis是單純的db,數據完全透明所以這裡用redis作為講解對象會更加好理解。

    laravel中隊列的啟動方式有queue:listenqueue:work, 其中queue:work表示单独运行下一个job. 关于区别请看:queue:listen 和 queue:work --daemon 的区别 。queue:listen内部也是一次次的调用queue:work实现的,现在我们来看work指令。

    IlluminateQueueConsoleWorkCommand中是不是看见了我们熟悉的fire方法?對就是它。繼續追,
    呼叫runWork方式查找job并且执行.这里有一个daemon選項, 表示是否作為守護運行。直接將daemon認為false(因為daemon其實就是一個while(true) ):joy:。

    看到runWork其实是调用的IlluminateQueueWorker::pop方法

    public function pop($connectionName, $queue = null, $delay = 0, $sleep = 3, $maxTries = 0)
    {
        $connection = $this->manager->connection($connectionName); //这里就是你说的连接名称,实际就是选择一个合理的queue服务,只要你没有用某个队列服务的特有的方法,那么各个队列可以随时切换使用的.
    
        $job = $this->getNextJob($connection, $queue);  //查找一个job对象
    
        // If we're able to pull a job off of the stack, we will process it and
        // then immediately return back out. If there is no job on the queue
        // we will "sleep" the worker for the specified number of seconds.
        if ( ! is_null($job))
        {
            //如果job存在则执行任务
            return $this->process(
                $this->manager->getName($connectionName), $job, $maxTries, $delay
            );
        }
        $this->sleep($sleep);
        return ['job' => null, 'failed' => false];
    }
    

    到了最終執行job的位置(刪掉了空行和註釋,因為我要來上蹩腳的中文註釋了.(逃 ):

    public function process($connection, Job $job, $maxTries = 0, $delay = 0)
    {
        if ($maxTries > 0 && $job->attempts() > $maxTries){ //看见了吗,运行的时候先查看了job的执行次数如果超过了最大次数,则直接进入logFailedJob过程,也就是将失败的job存储到指定的数据库中, 观察`Illuminate\Queue\Jobs\RedisJob`中的`attempts `方法和`release`方法。一个查看attempts次数,一个增加attempts次数(当然release还有其他操作).那么找找谁调用了release方法(看下面的trycatch,就是在出现异常之后并且job没有被删除的情况下会调用release)?如果没有抛出异常?那么attempts是不会变化的。
            return $this->logFailedJob($connection, $job); 
        }
        try{
            $job->fire();// job的fire方法实际已经将我们指定的JobClass用Container::make并且执行了fire方法.
            if ($job->autoDelete()) $job->delete();
            return ['job' => $job, 'failed' => false];
        } catch (\Exception $e){
            if ( ! $job->isDeleted()) $job->release($delay);
    
            throw $e;
        }
    }
    

    恩,差不多就是這麼回事了。

    你那個拋出來的Swift_TransportException是发送邮件程序swiftmailer拋出的錯誤

    回覆
    0
  • phpcn_u1582

    phpcn_u15822017-05-16 16:58:46

    config/queue.php裡的connections配置中,sync,beanstalkd,sqs等就是那個connection-name。

    回覆
    0
  • 取消回覆