我正在使用最新版本的Homestead。 我也设置了Laravel Horizon。 我使用Redis作为队列驱动程序。 Laravel是5.6版本,是一个全新的安装。
发生的事情是我的工作都失败了(即使工作正确退出)。
我使用自定义命令通过命令行运行作业:
vagrant@homestead:~/myapp$ artisan crawl:start
vagrant@homestead:~/myapp$ <-- No CLI errors after running
<?php
namespace MyApp\Console\Commands;
use Illuminate\Console\Command;
use MyApp\Jobs\Crawl;
class crawl extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'crawl:start';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Start long running job.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
Crawl::dispatch();
}
}
<?php
namespace MyApp\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class Crawl implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* The number of seconds the job can run before timing out.
*
* @var int
*/
public $timeout = 3600;
/**
* The number of times the job may be attempted.
*
* @var int
*/
public $tries = 1;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$crawl = new Crawl();
$crawl->start();
}
}
<?php
namespace MyApp;
class Crawl
{
public function start()
{
ini_set('memory_limit','256M');
set_time_limit(3600);
echo "Started.";
sleep(30);
echo "Exited.";
exit();
}
}
[2018-03-21 10:14:27][1] Processing: MyApp\Jobs\Crawl
Started.
Exited.
[2018-03-21 10:15:59][1] Processing: MyApp\Jobs\Crawl
[2018-03-21 10:15:59][1] Failed: MyApp\Jobs\Crawl
Failed At 18-03-21 10:15:59
Error Illuminate\Queue\MaxAttemptsExceededException:
MyApp\Jobs\Crawl has been attempted too many
times or run too long. The job may have previously
timed out. in /home/vagrant/app/vendor/laravel
/framework/src/Illuminate/Queue/Worker.php:396
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/vagrant/myapp/artisan queue:work --sleep=3 --tries=1 --timeout=3600
autostart=true
autorestart=true
user=vagrant
numprocs=1
redirect_stderr=true
stdout_logfile=/home/vagrant/myapp/worker.log
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'default',
'retry_after' => 90,
'block_for' => null,
],
QUEUE_DRIVER=redis
查看我的worker.log
我可以看到我班级的输出有效:
Started.
Exited.
但据报道这项工作失败了。为什么?
奇怪的是,同样在worker.log
,它为一项工作说了Processing
两次:
[2018-03-21 10:15:59][1] Processing: MyApp\Jobs\Crawl
[2018-03-21 10:15:59][1] Failed: MyApp\Jobs\Crawl
非常感谢任何帮助!
删除exit()
已解决了这个问题 - 这很奇怪,因为PHP手册说您可以使用exit()
“正常”退出程序:
<?php
//exit program normally
exit;
exit();
exit(0);
答案 0 :(得分:2)
删除
exit()
已解决了这个问题 - 这很奇怪,因为PHP手册说您可以使用exit()
“正常”退出程序
对于常规程序也是如此,但Laravel中的排队作业不遵循相同的生命周期。
当队列系统处理作业时,该作业将在现有队列工作进程中执行。具体来说,队列工作者从后端获取作业数据,然后调用作业的handle()
方法。当该方法返回时,队列工作程序运行一些代码来完成作业。
如果我们通过调用exit()
,die()
或通过触发致命错误退出作业,PHP也会停止运行作业的工作进程,因此队列系统永远不会完成作业生命周期,工作从未标记为“完成”。
我们不需要明确退出工作。如果我们想尽早完成工作,我们可以简单地从handle()
方法返回:
public function handle()
{
// ...some code...
if ($exitEarly) {
return;
}
// ...more code...
}
Laravel还包含一个特性InteractsWithQueue
,它提供了一个API,可以让作业自行管理。在这种情况下,我们可以从展示此特征的作业中调用delete()
方法:
public function handle()
{
if ($exitEarly) {
$this->delete();
}
}
但据报道这项工作失败了。为什么?奇怪的是,同样在worker.log中,它表示为一个作业处理两次
如上所述,作业无法成功完成,因为我们调用了exit()
,因此队列系统尽职地尝试重试作业。