Yii 2: The Fast, Secure and Professional PHP Framework 定时任务调度:Cron 与 Queue 结合

Yii 2: The Fast, Secure and Professional PHP Framework 定时任务调度:Cron 与 Queue 结合

【免费下载链接】yii2 Yii 2: The Fast, Secure and Professional PHP Framework 【免费下载链接】yii2 项目地址: https://gitcode.com/gh_mirrors/yi/yii2

在Web应用开发中,定时任务调度是后台处理的关键组成部分。无论是数据备份、邮件发送还是定期报表生成,都需要可靠的任务执行机制。Yii 2框架通过Cron(定时触发器)与Queue(任务队列)的结合,提供了高效、灵活的解决方案。本文将详细介绍如何在Yii 2中实现这一机制,解决任务堆积、执行超时和失败重试等常见问题。

控制台命令基础

Yii 2的定时任务调度基于控制台命令系统实现。控制台应用程序的入口脚本为yii,位于项目根目录,通过它可以执行各种后台任务。控制台命令继承自[[yii\console\Controller]]类,每个命令对应一个控制器,其中的动作方法即为具体的任务实现。

基本使用方法

运行控制台命令的基本语法如下:

yii <route> [--option1=value1 --option2=value2 ... argument1 argument2 ...]

例如,执行缓存清理命令:

yii cache/flush-all

查看所有可用命令列表:

yii

Running ./yii command for help output

官方文档:docs/guide-zh-CN/tutorial-console.md

创建自定义定时任务

开发控制台控制器

创建自定义定时任务的第一步是开发控制台控制器。以下是一个示例,实现了一个简单的日志清理任务:

<?php
namespace app\commands;

use yii\console\Controller;
use yii\console\ExitCode;
use yii\helpers\FileHelper;

class LogController extends Controller
{
    /**
     * 清理过期日志文件
     * @param int $days 保留天数
     * @return int
     */
    public function actionClean($days = 30)
    {
        $logPath = \Yii::getAlias('@runtime/logs/');
        $expireTime = time() - $days * 86400;
        
        foreach (FileHelper::findFiles($logPath, ['only' => ['*.log']]) as $file) {
            if (filemtime($file) < $expireTime) {
                unlink($file);
                $this->stdout("Deleted expired log file: $file\n");
            }
        }
        
        return ExitCode::OK;
    }
}

命令选项与参数

通过重写[[yii\console\Controller::options()]]方法,可以为命令添加选项:

public function options($actionID)
{
    return array_merge(parent::options($actionID), ['days']);
}

使用选项别名简化输入:

public function optionAliases()
{
    return ['d' => 'days'];
}

现在可以通过以下命令执行带参数的清理任务:

yii log/clean -d=7

Cron:定时触发任务

Cron是Linux系统自带的定时任务调度工具,通过配置Cron表达式,可以定期触发Yii 2控制台命令。

基本Cron配置

编辑Cron表:

crontab -e

添加任务,例如每天凌晨2点执行日志清理:

0 2 * * * /path/to/yii log/clean -d=30 >> /var/log/yii-cron.log 2>&1

Yii 2中的Cron管理

虽然Yii 2核心未提供Cron管理模块,但可以通过社区扩展如yii2-cron实现更灵活的Cron任务管理。安装扩展后,可在配置文件中定义任务:

'components' => [
    'cron' => [
        'class' => 'mikehaertl\yii2\cron\Cron',
        'jobs' => [
            [
                'command' => 'log/clean -d=30',
                'schedule' => '0 2 * * *',
            ],
        ],
    ],
],

Queue:异步任务处理

对于耗时较长的任务(如邮件群发、大数据处理),直接通过Cron同步执行可能导致超时或阻塞。Yii 2的Queue组件提供了异步任务处理能力,支持多种驱动(如数据库、Redis、Beanstalkd)。

安装与配置Queue

composer.json中添加依赖:

"require": {
    "yiisoft/yii2-queue": "^2.0"
}

执行安装命令:

composer install

配置Queue组件(在config/console.php中):

'components' => [
    'queue' => [
        'class' => \yii\queue\db\Queue::class,
        'db' => 'db',
        'tableName' => '{{%queue}}',
        'channel' => 'default',
        'mutex' => \yii\mutex\MysqlMutex::class,
    ],
],

创建队列任务

生成任务类:

yii generate/queue-job SendEmail

编辑任务类(位于commands/jobs/SendEmailJob.php):

<?php
namespace app\commands\jobs;

use yii\base\BaseObject;
use yii\queue\JobInterface;
use yii\mail\MailerInterface;

class SendEmailJob extends BaseObject implements JobInterface
{
    public $to;
    public $subject;
    public $body;

    public function execute($queue)
    {
        \Yii::$app->mailer->compose()
            ->to($this->to)
            ->subject($this->subject)
            ->textBody($this->body)
            ->send();
    }
}

将任务加入队列

在控制器或模型中:

Yii::$app->queue->push(new \app\commands\jobs\SendEmailJob([
    'to' => 'user@example.com',
    'subject' => 'Welcome',
    'body' => 'Thank you for registering.',
]));

运行队列监听进程

启动队列监听进程,处理任务:

yii queue/listen

或使用queue/run命令一次性处理所有任务:

yii queue/run

Cron与Queue结合实现高级调度

架构设计

通过Cron定时触发控制台命令,将任务加入Queue,再由Queue Worker异步处理,形成完整的定时任务调度系统。

定时任务调度架构

实现步骤

  1. 创建任务分发命令
class TaskController extends Controller
{
    public function actionDispatch()
    {
        // 从数据库或配置中获取待执行任务
        $tasks = Task::find()->where(['status' => Task::STATUS_PENDING])->all();
        
        foreach ($tasks as $task) {
            Yii::$app->queue->push(new ProcessTaskJob([
                'taskId' => $task->id,
            ]));
            $task->status = Task::STATUS_QUEUED;
            $task->save();
        }
        
        return ExitCode::OK;
    }
}
  1. 配置Cron定时触发分发命令
*/5 * * * * /path/to/yii task/dispatch >> /var/log/yii-task.log 2>&1
  1. 启动Queue Worker
yii queue/listen --verbose

监控与错误处理

日志记录

配置日志组件记录任务执行情况(在config/console.php中):

'log' => [
    'targets' => [
        [
            'class' => 'yii\log\FileTarget',
            'categories' => ['queue', 'cron'],
            'logFile' => '@runtime/logs/queue-cron.log',
        ],
    ],
],

失败重试机制

Queue组件内置失败重试功能,配置重试次数和延迟:

'queue' => [
    'class' => \yii\queue\db\Queue::class,
    'ttr' => 300, // 任务执行超时时间(秒)
    'attempts' => 3, // 最大重试次数
],

管理界面

通过yii2-queue-admin扩展可以实现任务管理界面,查看任务状态、重试失败任务等:

composer require --prefer-dist yiisoft/yii2-queue-admin

配置模块:

'modules' => [
    'queue' => [
        'class' => \yii\queue\admin\Module::class,
    ],
],

访问管理界面:http://your-app/queue

最佳实践与性能优化

任务拆分

将大型任务拆分为小型子任务,提高并行处理效率和失败恢复能力。

资源限制

在Cron任务中设置合理的资源限制,避免影响Web应用性能:

0 2 * * * /usr/bin/timeout 3600 /path/to/yii heavy/task >> /var/log/yii-cron.log 2>&1

使用进程管理工具

为确保Queue Worker持续运行,使用进程管理工具进行进程管理:

[program:yii-queue]
command=/path/to/yii queue/listen
directory=/path/to/app
user=www-data
autostart=true
autorestart=true
stderr_logfile=/var/log/yii-queue.err.log
stdout_logfile=/var/log/yii-queue.out.log

总结

Yii 2通过Cron与Queue的结合,提供了强大的定时任务调度能力。Cron负责定时触发,Queue处理异步任务,两者相辅相成,既保证了任务的及时执行,又避免了长时间任务对系统的影响。通过合理配置和优化,可以满足各种复杂场景下的任务调度需求。

官方文档:docs/guide-zh-CN/tutorial-console.md Queue组件源码:framework/queue/ Cron示例配置:config/console.php

【免费下载链接】yii2 Yii 2: The Fast, Secure and Professional PHP Framework 【免费下载链接】yii2 项目地址: https://gitcode.com/gh_mirrors/yi/yii2

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值