我有一个应用程序运行许多不同类型的作业,运行几秒钟到一个小时。这要求我有两个独立的队列连接,因为retry_after被绑定到一个连接,而不是一个队列(尽管它们都使用Redis,这很烦人,但现在不是问题)。一个连接的retry_after为600秒,另一个为3600秒(或一小时)。我的工作实现了ShouldQueue并使用了特性Queueable, SerializesModels, Dispatchable, InteractsWithQueue。
现在是问题所在。我创建了一个睡眠900秒的TestJob,以确保我们通过了retry_after限制。当我试图使用:dispatch(new Somejob)->onConnection('redis-long-run')或以前在作业的构造函数中(过去总是工作)分配特定连接上的作业时:
public function __construct() {
$this->onConnection('redis-long-run');
}作业由队列工作人员拾取,运行600秒后,员工重新启动作业,注意到它已经运行了一次,并失败了。300秒后,作业处理成功。如果我的工作人员允许多次尝试,重复作业将并行运行300秒。
在我的测试工作中,我还打印出了$this->connection,它确实显示了正在使用的正确连接,所以我猜广播公司只是完全忽略了它。
我在Docker环境中使用Laravel5.8.35和PHP7.3。主管处理我的工人。
编辑:我已经确认在升级到Laravelv6.5.1之后,这种行为仍然存在。
复制步骤:
redis,其retry_after值为600,另一个名为redis-long-run,retry_after为3600。在我的例子中,它们也有不同的队列,尽管我不确定这个测试是否需要这样做。 'connections' => [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 600,
'block_for' => null,
],
'redis-long-run' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'long_run',
'retry_after' => 3600,
'block_for' => null,
]
]<?php
namespace App\Console\Commands;
use App\Jobs\TestFifteen;
use Illuminate\Console\Command;
class TestCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'test:fifteen';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
for ($i = 1; $i <= 3; $i++) {
dispatch(new TestFifteen($i))->onConnection('redis-long-run');
}
}
}<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use function sleep;
use function var_dump;
class TestFifteen implements ShouldQueue
{
use Queueable, SerializesModels, Dispatchable, InteractsWithQueue;
private $testNumber;
public function __construct($testNumber)
{
$this->onConnection('redis-long-run');
$this->testNumber = $testNumber;
}
public function handle()
{
var_dump("Started test job {$this->testNumber} on connection {$this->connection}");
sleep(900);
var_dump("Finished test job {$this->testNumber} on connection {$this->connection}");
}
}[program:laravel-queue-default]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan queue:work redis --queue=default --tries=3 --timeout=600
numprocs=8
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:laravel-queue-long-run]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan queue:work redis --queue=long_run --tries=1 --timeout=3540
numprocs=8
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0执行手工命令php artisan test:fifteen的
那么,我是做错了什么,还是应用的联系真的不受尊重?
此外,不能够根据每个作业或队列来决定retry_after应该是什么,从而能够使用REDIS作为实际的队列驱动程序,背后的设计理念是什么?为什么我不能选择Redis作为队列处理程序,并决定队列-60秒后重试1次,120秒后重试2次队列?当他们使用完全相同的Redis实例和所有东西时,我觉得必须为此建立两个连接是非常不自然的。
不管怎么说,我希望一些人能在这个问题上有所启发。提前谢谢你。
发布于 2019-11-19 08:33:26
据我所知,您的连接始终是redis,因此您应该在分派时指定队列:
dispatch(new TestFifteen($i))->onQueue('long_run');connection 是一个不同的驱动程序,如redis、sync、AWS等,而queue是与该连接不同的配置或多个作业堆栈。
https://stackoverflow.com/questions/58914428
复制相似问题