33、Hyperf 3 快速使用 - Hyperf 3 通过配置和注解两种方式使用定时任务

作者: 温新

分类: 【Hyperf 3 基础系列】

阅读: 1422

时间: 2023-04-25 16:12:52

hi,我是温新,一名 PHPer

Hypref 版本:Hyperf 3.0

学习目标:掌握定时任务的使用方式

Hypref 通过 hyperf/crontab 组件提供了一个 秒级 定时任务的功能。执行定时任务会通过 Linux 中的 crontab 命令实现。

配置定时任务

第一步:安装组件包

composer require hyperf/crontab

第二步:发布配置文件

php bin/hyperf.php vendor:publish hyperf/crontab

该命令会在 config/autoload 目录下生成 crontab.php 配置文件,生成内容如下:

<?php

declare(strict_types=1);

return [
    // 开启定时任务
    'enable' => true,
    'crontab' => [
    ],
];

第三步:启用任务调度器进程

在使用定时任务组件之前,需要先在 config/autoload/processes.php 内注册一下 Hyperf\Crontab\Process\CrontabDispatcherProcess 自定义进程,如下:

<?php
// config/autoload/processes.php

declare(strict_types=1);

return [
   	// 分发定时任务
    \Hyperf\Crontab\Process\CrontabDispatcherProcess::class,
];

到这里定时任务基础配置已经完成,接下来只要编写定时任务脚本即可。

高能提示:

1、服务启动,定时任务也就启动了,但是定时任务不会立即执行;

2、服务启动后,定时任务不会立即执行,而是等到下一分才开始执行。 举例:比如定时启动时间是 23:05:05 ,那么定时任务会在 23:06:00 才正式执行。

两种方式实现定时任务

方式一:使用配置文件方式实现定时任务

第一步:定义定时任务类

<?php

namespace App\Task;

// 使用配置文件的方式执行定时任务
use Hyperf\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;

class TestTask
{
    protected LoggerInterface $logger;

    public function __construct(LoggerFactory $loggerFactory)
    {
        $this->logger = $loggerFactory->get('log', 'default');
    }
    
    public function demoTask()
    {
        // 执行定时任务
        $this->logger->info(date('Y-m-d H:id') . ' 我是王美丽呀');
    }
}

第二步:配置定时任务

<?php
// config/autoload/crontab.php
declare(strict_types=1);

return [
    'enable' => true,
    'crontab' => [
        (new \Hyperf\Crontab\Crontab())->setName('TestTask')->setRule('* * * * *')->setCallback([\App\Task\TestTask::class, 'demoTask'])->setMemo('我是备注:测试定时任务'),
    ],
];

第三步:启动服务

php bin/hyperf start

方式二:使用注解方式实现定时任务

第一步:定义定时任务类

<?php

namespace App\Task;

use Hyperf\Crontab\Annotation\Crontab;
use Hyperf\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;

#[Crontab(name: "DemoTask", rule: "*\/1 * * * * *", callback: "demoTask", memo: "注解定时任务说明'")]
class DemoTask
{
    protected LoggerInterface $logger;

    public function __construct(protected LoggerFactory $loggerFactory)
    {
        $this->logger = $this->loggerFactory->get('log', 'default');
    }

    public function demoTask()
    {
        $this->logger->info(date('Y-m-d H:is') . ' DemoTask  使用注解实现定时任务');
    }
}

第二步:启动服务

php bin/hyperf start

了解一下定时任务的参数

public function __construct(
    public ?string $rule = null,
    public ?string $name = null,
    public string $type = 'callback',
    public ?bool $singleton = null,
    public ?string $mutexPool = null,
    public ?int $mutexExpires = null,
    public ?bool $onOneServer = null,
    public array|string|null $callback = null,
    public ?string $memo = null,
    public array|string|bool $enable = true
) {
}

失败任务任务

当定时任务执行失败时,会触发 FailToExecute 事件。因此,可以编写一个监听器类监听该事件,拿到对应的定时任务异常

第一步:定义异常任务类,用于模拟定时任务失败

<?php

namespace App\Task;

use _PHPStan_1292afebc\Nette\Neon\Exception;
use Hyperf\Crontab\Annotation\Crontab;
use Hyperf\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;

#[Crontab(name: "PostTask", rule: "*\/1 * * * * *", callback: "posts", memo: "post任务'")]
class PostTask
{
    protected LoggerInterface $logger;

    public function __construct(protected LoggerFactory $loggerFactory)
    {
        $this->logger = $this->loggerFactory->get('log', 'default');
    }

    public function posts()
    {
        // 此处报了异常
        throw new Exception('测试定时任务');

        // 正常业务逻辑
        $this->logger->info('文章定时任务');
    }
}

第二步:定义异常监听器

<?php

namespace App\Listener;

use Hyperf\Crontab\Event\FailToExecute;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;

#[Listener]
class FailToExecuteCrontabPostListener implements ListenerInterface
{
    protected LoggerInterface $logger;

    public function __construct(protected LoggerFactory $loggerFactory)
    {
        $this->logger = $this->loggerFactory->get('log', 'default');
    }

    public function listen(): array
    {
        return [
            FailToExecute::class
        ];
    }

    public function process(object $event): void
    {
        $msg =  '定时任务执行失败' .  $event->crontab->getName() . '----' . $event->throwable->getMessage();

        $this->logger->info($msg);
    }
}

$event->crontab->getName() 用于获取出现异常的定时任务名称;

$event->throwable->getMessage() 用于获取定时任务出现异常消息。

第三步:测试

php bin/hyperf.php start
    
tail -f runtime/logs/hyperf.log
# 输出内容如下
[2023-03-18 15:33:12] log.INFO: 定时任务执行失败PostTask----测试定时任务 [] []
[2023-03-18 15:33:13] log.INFO: 定时任务执行失败PostTask----测试定时任务 [] []

调度分发策略

定时任务在设计上允许通过不同的策略来调度分发执行任务,目前仅提供了 多进程执行策略协程执行策略 两种策略,默认为 多进程执行策略

案例:修改为协程风格时,只需要修改config/autoload/dependencies.php文件,配置如下:

<?php

declare(strict_types=1);
return [
    'HttpServer' => Hyperf\HttpServer\Server::class,
    // 修改为协程风格
    \Hyperf\Crontab\Strategy\StrategyInterface::class =>  \Hyperf\Crontab\Strategy\CoroutineStrategy::class
];

本篇文章结束,我是温新。

请登录后再评论