1. Fastadmin与think-queue队列整合概述
在Fastadmin项目中集成think-queue队列系统,本质上是在ThinkPHP框架基础上实现异步任务处理能力。这种组合特别适合需要处理耗时操作(如邮件发送、数据导出、报表生成)的业务场景,能有效提升系统响应速度和用户体验。
think-queue作为ThinkPHP官方推荐的队列服务,支持多种驱动方式(Redis、Database、Topthink等)。在Fastadmin中使用时,我们通常选择Redis作为队列存储介质,主要基于以下考量:
- Redis的高性能特性(10万+/秒的吞吐量)
- 原生支持消息持久化和失败重试机制
- 与Fastadmin的缓存系统天然兼容
实际项目中,我们曾用这种组合将用户导出Excel的响应时间从35秒降至0.5秒(前端立即返回,后台异步生成文件)。这种提升在电商大促期间尤为明显,当同时有上百个导出请求时,系统仍能保持流畅。
2. 环境准备与基础配置
2.1 组件安装与依赖检查
首先通过Composer安装必要组件:
composer require topthink/think-queue composer require predis/predis # Redis客户端检查Fastadmin的config/queue.php配置文件(不存在则新建),基础配置示例如下:
return [ 'default' => 'redis', 'connections' => [ 'redis' => [ 'type' => 'redis', 'queue' => 'default', 'host' => '127.0.0.1', 'port' => 6379, 'password' => '', 'select' => 0, 'timeout' => 0, 'persistent' => false, 'expire' => 60, 'retry_after' => 90, ], ], ];重要提示:确保Redis服务已启动且PHP安装了redis扩展。可通过
php -m | grep redis验证扩展状态。
2.2 队列进程管理配置
创建Supervisor配置文件/etc/supervisor/conf.d/fastadmin_queue.conf:
[program:fastadmin_queue] command=php think queue:listen --queue default --tries 3 --sleep 3 --memory 128 directory=/var/www/fastadmin autostart=true autorestart=true user=www numprocs=2 redirect_stderr=true stdout_logfile=/var/log/supervisor/fastadmin_queue.log关键参数说明:
--tries 3:任务失败最大重试次数--sleep 3:队列空时休眠时间(秒)--memory 128:进程内存限制(MB)numprocs=2:启动的进程数(根据CPU核心数调整)
执行以下命令使配置生效:
sudo supervisorctl update sudo supervisorctl start fastadmin_queue3. 队列任务开发实战
3.1 创建基础任务类
在application/common/job目录下新建ExportExcel.php:
namespace app\common\job; use think\queue\Job; use think\facade\Filesystem; class ExportExcel { public function fire(Job $job, $data) { try { // 业务逻辑处理 $filename = 'export_'.date('YmdHis').'.xlsx'; $filepath = $this->generateExcel($data); // 保存到公开存储 Filesystem::putPublicFile($filename, file_get_contents($filepath)); // 更新数据库记录 \app\common\model\ExportLog::updateStatus($data['log_id'], 1); $job->delete(); } catch (\Exception $e) { if ($job->attempts() >= 3) { $job->delete(); \app\common\model\ExportLog::updateStatus( $data['log_id'], 2, $e->getMessage() ); } else { $job->release(60); // 延迟1分钟后重试 } } } private function generateExcel($params) { // 实际Excel生成逻辑 // 返回临时文件路径 } }3.2 任务派发与控制
在控制器中派发任务:
public function export() { $params = input('post.'); $logId = \app\common\model\ExportLog::createRecord($this->auth->id, $params); \think\Queue::push(\app\common\job\ExportExcel::class, [ 'log_id' => $logId, 'params' => $params, 'user_id' => $this->auth->id ], 'default'); return json(['status' => 'success', 'msg' => '任务已提交后台处理']); }高级任务控制方法:
// 延迟执行(60秒后) \think\Queue::later(60, \app\common\job\ExportExcel::class, $data); // 指定队列 \think\Queue::pushOn('high_priority', \app\common\job\ExportExcel::class, $data); // 批量派发 foreach ($items as $item) { \think\Queue::push(\app\common\job\BatchProcess::class, $item); }4. 性能优化与监控
4.1 队列性能调优
Redis配置优化(/etc/redis/redis.conf):
maxmemory 2gb maxmemory-policy allkeys-lru save 900 1 save 300 10 save 60 10000PHP进程配置建议:
- 每个队列进程内存限制建议128-256MB
- 进程数 = CPU核心数 × 1.5(四核机器建议6个进程)
- 使用
--timeout参数防止僵尸进程(建议设置为任务最长执行时间的2倍)
4.2 监控方案实现
创建自定义监控命令app/command/QueueMonitor.php:
namespace app\command; use think\console\Command; use think\console\Input; use think\console\Output; use think\facade\Cache; class QueueMonitor extends Command { protected function configure() { $this->setName('queue:monitor')->setDescription('Monitor queue status'); } protected function execute(Input $input, Output $output) { $redis = new \Redis(); $redis->connect('127.0.0.1', 6379); $stats = [ 'pending' => $redis->llen('queues:default'), 'failed' => $redis->zcard('queues:default:delayed'), 'timestamp' => time() ]; Cache::set('queue_stats', $stats, 3600); if ($stats['pending'] > 1000) { // 触发告警(邮件/短信) $this->triggerAlert($stats); } $output->writeln(json_encode($stats, JSON_PRETTY_PRINT)); } }设置定时任务(Crontab):
* * * * * php /var/www/fastadmin think queue:monitor >> /var/log/fastadmin_queue_monitor.log5. 常见问题排查与解决方案
5.1 任务不执行排查流程
- 检查Supervisor状态:
sudo supervisorctl status确保进程状态为RUNNING
- 查看日志文件:
tail -f /var/log/supervisor/fastadmin_queue.log- 手动测试队列:
php think queue:work --once- 检查Redis连接:
redis-cli monitor5.2 典型错误与修复
问题1:Predis\Connection\ConnectionException: Connection refused
- 解决方案:检查Redis服务状态
sudo systemctl status redis,确认配置中的host/port正确
问题2:Serialization of 'Closure' is not allowed
- 原因:任务数据中包含闭包
- 修复:确保队列数据只包含可序列化的简单类型
问题3:任务重复执行
- 配置
retry_after大于任务最长执行时间 - 实现任务幂等性检查:
if (\app\common\model\ExportLog::isProcessed($data['log_id'])) { $job->delete(); return; }6. 高级应用场景
6.1 优先级队列实现
修改Redis配置:
'connections' => [ 'redis' => [ // ... 'queue' => 'high,default,low', // 优先级从高到低 ], ]派发任务时指定队列:
// 高优先级任务 \think\Queue::pushOn('high', \app\common\job\PaymentProcess::class, $data); // 普通任务 \think\Queue::pushOn('default', \app\common\job\EmailNotification::class, $data);6.2 分布式队列方案
多服务器配置要点:
- 共享Redis配置(使用独立Redis实例)
- 统一队列名称前缀:
'prefix' => env('APP_ENV').'_queue'- 负载均衡策略:
- 按任务类型划分(服务器A处理导出任务,服务器B处理邮件任务)
- 按哈希取模分配
6.3 与Workerman集成
创建自定义命令处理实时队列:
namespace app\command; use think\console\Command; use think\console\Input; use think\console\Output; use Workerman\Worker; class QueueWorker extends Command { protected function configure() { $this->setName('queue:worker')->setDescription('Start queue worker'); } protected function execute(Input $input, Output $output) { $worker = new Worker(); $worker->count = 4; $worker->onWorkerStart = function() { $queue = new \think\queue\Worker(); $queue->run('default'); }; Worker::runAll(); } }启动命令:
php think queue:worker