这个问题大概几种解决方案 1 基于linux cron定时任务 (laravel也有针对cron比较优秀的解决方案) 2 基于队列的延时执行 3 通过redis的数据过期 等
这次采用的是基于队列任务的延时执行,相较于cron 这种方案在执行时效性和后期拓展性上更胜一筹,官方推荐采用redis作为laravel队列服务的驱动,但是因为这次案子比较急(没怎么用过redis,懒得去配置),我就直接采用了mysql作为驱动
首先我们进行队列配置
1、更改系统默认队列驱动(.env)
QUEUE_CONNECTION=database
2、创建存储队列数据的sql
php artisan queue:table
php artisan migrate
3、创建任务文件
php artisan make:job OrderJob
4、编辑任务文件,对任务进行一些安全性配置(参考)
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Order;
//use Log;
class OrderJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 5;//最大尝试次数
public $timeout = 5;//最大尝试时间
public $order;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Order $order)
{
//
$this->order = $order;/*
Log::info('队列任务初始化了');
Log::info($this->order);
Log::info(now()); */
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
/* Log::info('队列任务执行了');
Log::info($this->order);
Log::info(now()); */
// 判断订单状态是否为1,自动删除未支付订单
if($this->order->status ==1){
$this->order->delete();
}
}
}
5、在合适的时机进行任务分发,我是在模型观察者中监测订单的创建,同时进行任务分发
namespace App\Observers;
use App\Order;
use App\OrderItem;
use App\CensusOrderDate;
use App\CensusOrderArea;
use Carbon\Carbon;
use EasyWeChat\Factory;
use Log;
use App\Jobs\OrderJob;
class OrderObserver
{
/**
* Handle the order "created" event.
*
* @param \App\Order $order
* @return void
*/
public function created(Order $order)
{
//
// 分发延时30min任务到队列
OrderJob::dispatch($order)->delay(now()->addMinutes(30));
}
}
到这一步结束的时候,我们基本配置就已经完成了,然后可以通过laravel自带的队列进程来进行测试了
php artisan queue:work
如果测试没有定时删除,那检查前面几步看看哪里错了。
接下来要配置 Supervisor
为了保持队列进程 queue:work 持续在后台运行,需要使用进程守护程序Supervisor
官方文档提供了Ubuntu的快捷安装指令,我是centos7
1、centos安装Supervisor
#sudo su
# yum install epel-release
# yum install -y supervisor
# systemctl enable supervisord # 开机自启动
# systemctl start supervisord # 启动supervisord服务
# systemctl status supervisord # 查看supervisord服务状态
# ps -ef|grep supervisord # 查看是否存在supervisord进程
2、配置Supervisor
找到Supervisor 主配置文件,我安装完成后配置文件是/etc/Supervisord.conf,和laravel官方文档的不太一样,不知道是不是Supervisor 针对Ubuntu和centos的不同版本造成的。
打开查看:
[include]
files = supervisord.d/*.ini
可以找到配置文件引入目录和引入后缀,进入引入目录,创建一个子配置文件laravel-worker.ini
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /www/wwwroot/blog/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=blog
numprocs=8
redirect_stderr=true
stdout_logfile=/www/wwwroot/blog/worker.log
3、重启supervisor
# systemctl restart supervisord
到这一步,我们基本就可以收工了
如果想记录处理失败的任务
1、创建相关数据表
php artisan queue:failed-table
php artisan migrate
创建完成后,队列任务执行失败会被记录到这个表