在Laravel的业务场景中,异步队列是处理耗时任务的核心组件,而队列优先级决定了不同任务的执行先后顺序。当我们需要验证不同优先级调度策略的效果时,就可以通过AB测试机制来实现,对比不同策略下的任务处理效率和系统负载情况。

AB测试与队列优先级的基础准备
首先需要在Laravel中配置好队列驱动,这里以常用的Redis驱动为例,先确保config/queue.php中的Redis配置正确:
<?php
// config/queue.php 部分配置
return [
'default' => 'redis',
'connections' => [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
],
];
AB测试需要区分两个测试组,我们可以通过用户ID或者请求标识来分配用户到A组或B组,这里先定义一个简单的分组逻辑:
<?php
// 定义AB测试分组方法
function getAbTestGroup($userId) {
// 根据用户ID取模,50%用户到A组,50%到B组
return $userId % 2 === 0 ? 'A' : 'B';
}
定义不同优先级的队列任务
我们需要创建两个不同优先级的任务类,分别对应高优先级和低优先级任务,任务类需要继承Laravel的IlluminateContractsQueueShouldQueue接口:
<?php
namespace AppJobs;
use IlluminateBusQueueable;
use IlluminateContractsQueueShouldQueue;
use IlluminateFoundationBusDispatchable;
use IlluminateQueueInteractsWithQueue;
use IlluminateQueueSerializesModels;
class HighPriorityTask implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $userId;
public function __construct($userId)
{
$this->userId = $userId;
}
public function handle()
{
// 高优先级任务处理逻辑,比如发送重要通知
Log::info('高优先级任务执行,用户ID:' . $this->userId);
}
}
<?php
namespace AppJobs;
use IlluminateBusQueueable;
use IlluminateContractsQueueShouldQueue;
use IlluminateFoundationBusDispatchable;
use IlluminateQueueInteractsWithQueue;
use IlluminateQueueSerializesModels;
class LowPriorityTask implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $userId;
public function __construct($userId)
{
$this->userId = $userId;
}
public function handle()
{
// 低优先级任务处理逻辑,比如生成统计报表
Log::info('低优先级任务执行,用户ID:' . $this->userId);
}
}
实现AB测试的优先级调度逻辑
AB测试的核心是让A组和B组使用不同的优先级策略,比如A组采用默认优先级,B组采用高优先级任务优先执行的策略。我们可以通过自定义队列驱动或者在分发任务时指定队列名称来实现:
首先在config/queue.php中定义两个队列,分别对应A组和B组的优先级策略:
<?php
// config/queue.php 新增队列配置
return [
// 其他配置...
'ab_test' => [
'A' => 'default', // A组使用默认队列,优先级按默认规则
'B' => 'high_priority_first', // B组使用自定义队列,高优先级优先
],
];
然后在任务分发时根据用户的AB分组指定对应的队列:
<?php
use AppJobsHighPriorityTask;
use AppJobsLowPriorityTask;
// 分发任务时根据AB分组选择队列
function dispatchTaskByAbGroup($userId, $isHighPriority) {
$group = getAbTestGroup($userId);
if ($isHighPriority) {
if ($group === 'A') {
// A组高优先级任务放到默认队列
HighPriorityTask::dispatch($userId)->onQueue('default');
} else {
// B组高优先级任务放到高优先级队列
HighPriorityTask::dispatch($userId)->onQueue('high_priority_first');
}
} else {
if ($group === 'A') {
// A组低优先级任务放到默认队列
LowPriorityTask::dispatch($userId)->onQueue('default');
} else {
// B组低优先级任务放到普通队列,优先级低于high_priority_first
LowPriorityTask::dispatch($userId)->onQueue('normal');
}
}
}
队列消费者的优先级配置
为了让B组的高优先级队列优先被消费,我们需要配置队列消费者进程,优先监听高优先级队列。可以通过Supervisor配置两个消费者进程,一个优先处理B组的高优先级队列:
# Supervisor配置示例 [program:laravel_queue_b_high] command=php /path/to/your/project/artisan queue:work redis --queue=high_priority_first,normal --sleep=3 --tries=3 autostart=true autorestart=true user=www-data numprocs=2 redirect_stderr=true stdout_logfile=/path/to/your/project/storage/logs/queue_b_high.log [program:laravel_queue_default] command=php /path/to/your/project/artisan queue:work redis --queue=default --sleep=3 --tries=3 autostart=true autorestart=true user=www-data numprocs=2 redirect_stderr=true stdout_logfile=/path/to/your/project/storage/logs/queue_default.log
测试效果验证
我们可以通过模拟用户请求来验证AB测试的效果,分别向A组和B组用户分发高低优先级任务,然后查看任务执行的日志顺序:
<?php
// 模拟测试
for ($i = 1; $i <= 10; $i++) {
// 前5个用户分发高优先级任务,后5个分发低优先级任务
$isHigh = $i <= 5;
dispatchTaskByAbGroup($i, $isHigh);
}
执行后查看日志,A组的任务会按照分发顺序执行,而B组的高优先级任务会优先于低优先级任务执行,这样就能对比两种优先级策略的处理效率。如果需要更精准的测试数据,可以记录每个任务的入队时间和执行时间,统计不同组的平均处理延迟,从而验证哪种优先级策略更符合业务需求。