《 swooleThinkphp 》毫秒定时器【 十 】


毫秒定时器



在日常项目开发中定时任务是很常见的,我们在开发电商业务中抢购秒杀,拍卖等功能模块,例如:拍下订单后在30分钟后自动取消未付款的订单同时把库存加回去。

通常我们会使用 crontab,但是 crontab 的精度不够,最小单位是每分钟。Swoole 就为我提供高精度毫秒的定时器。

PHP 本身的 pcntl_alarm 虽然也提供了类似的实现,但是 pcntl_alarm 最小单位只是秒,而 Swoole 是提供毫秒。而且 pcntl_alarm 不支持同时设定多个定时器程序,并且不支持异步IO。

接下来我们演示使用 ThinkPHP5 和 Swoole 的 swoole_timer_tick 函数来演示毫秒定时器。


创建 ThinkPHP5 自定义命令行

1.创建命令行类

创建application/console/Timer.php文件


<?php

namespace app\Console;


use think\console\Command;
use think\console\Input;
use think\console\Output;

class Timer extends Command
{
    protected $server;
    // 命令行配置函数
    protected function configure()
    {
        // setName 设置命令行名称
        // setDescription 设置命令行描述
        $this->setName('timer:start')->setDescription('Start TCP(Timer) Server!');
    }
    // 设置命令返回信息
    protected function execute(Input $input, Output $output)
    {
        $this->server = new \swoole_server('0.0.0.0', 9501);
        $this->server->set([
            'worker_num' => 4,
            'daemonize'  => false,
        ]);
        $this->server->on('Start', [$this, 'onStart']);
        $this->server->on('WorkerStart', [$this, 'onWorkerStart']);
        $this->server->on('Connect', [$this, 'onConnect']);
        $this->server->on('Receive', [$this, 'onReceive']);
        $this->server->on('Close', [$this, 'onClose']);
        $this->server->start();
        // $output->writeln("TCP: Start.\n");
    }
    // 主进程启动时回调函数
    public function onStart(\swoole_server $server)
    {
        echo "Start" . PHP_EOL;
    }
    // Worker 进程启动时回调函数
    public function onWorkerStart(\swoole_server $server, $worker_id)
    {
        // 仅在第一个 Worker 进程启动时启动 Timer 定时器
        if ($worker_id == 0) {
            // 启动 Timer,每 1000 毫秒回调一次 onTick 函数,
            swoole_timer_tick(1000, [$this, 'onTick']);
        }
    }
    // 定时任务函数
    public function onTick($timer_id, $params = null)
    {
        echo 'Hello' . PHP_EOL;
    }
    // 建立连接时回调函数
    public function onConnect(\swoole_server $server, $fd, $from_id)
    {
        echo "Connect" . PHP_EOL;
    }
    // 收到信息时回调函数
    public function onReceive(\swoole_server $server, $fd, $from_id, $data)
    {
        echo "message: {$data} form Client: {$fd}" . PHP_EOL;
        // 将受到的客户端消息再返回给客户端
        $server->send($fd, "Message form Server: ".$data);
    }
    // 关闭连时回调函数
    public function onClose(\swoole_server $server, $fd, $from_id)
    {
        echo "Close" . PHP_EOL;
    }
}

2.修改配置文件

文件所在 application/command.php


<?php

return [
    'app\console\Timer',
];

接下来就可以通过命令行来启动毫秒定时器


$ > php think timer:start


我们会看到以下返回结果


Delevin、博客



当程序运行后,首次回调 onStart 函数输出 Start,之后每 1000毫秒(每秒),输出一次Hello,就完成了我们的毫秒定时器