7、Workerman 基本使用 - Timer 定时器
hi,我是温新,一名 PHPer
定时器有 add
定时执行某个函数,del
删除一个定时器。本篇定时器的案例来自文档,主要是为了动手操作。
add
作用:定时执行某个函数。原型如下:
int \Workerman\Timer::add(float $time_interval, callable $callback [,$args = array(), bool $persistent = true])
参数:
- time_interval:定时器间隔时间,单位为秒,支持小数(可以精确到毫秒级别)
- callback: 定时器触发时调用的回调函数
- args:回调函数的参数数组,当定时器触发时,这些参数将传递给回调函数
- persistent:是否持久化,如果为 true,则定时器会在进程重启后自动重新添加;为 false 则只执行一次
返回值:返回一个整数,代表计时器的 timerid。
定时器为匿名函数
<?php
/**
* timer.php
*
* 定时器案例
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
// 开启多个进程时,需要注意业务是否有多进程并发问题
$worker->count = 1;
Timer::add(1, function (){
echo time() . PHP_EOL;
});
Worker::runAll();
指定进程执行定时器
<?php
/**
* timer.php
*
* 定时器案例
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
$worker->count = 4;
$worker->onWorkerStart = function (Worker $worker) {
// 编号为 2 的进程中执行定时器
if ($worker->id == 2) {
Timer::add(1, function () use ($worker) {
echo $worker->id . '==' . time() . PHP_EOL;
});
}
};
Worker::runAll();
定时器,闭包传递参数
<?php
/**
* timer.php
*
* 定时器案例
*/
use Workerman\Connection\TcpConnection;
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('tcp://0.0.0.0:8888');
$worker->count = 4;
$worker->onConnect = function (TcpConnection $connection) {
// 获取当前连接建立的时间并
$connectTime = date('Y-m-d H:i:s') . PHP_EOL;
// timer_id 保存为动态属性
// 使用闭包传递参数
$connection->timer_id = Timer::add(1, function($connectTime) use ($connection, $connectTime) {
$connection->send($connectTime);
});
};
$worker->onClose = function (TcpConnection $connection) {
// 删除定时器
Timer::del($connection->timer_id);
};
Worker::runAll();
执行一下看看情况
$ telnet 127.0.0.1 8888
# 思考下,时间为什么是一样的?
2024-02-29 07:30:12
2024-02-29 07:30:12
定时器,使用接口参数传递参数
<?php
/**
* timer.php
*
* 定时器案例
*/
use Workerman\Connection\TcpConnection;
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('tcp://0.0.0.0:8888');
$worker->count = 4;
$worker->onConnect = function (TcpConnection $connection) {
$connectTime = date('Y-m-d H:i:s') . PHP_EOL;
$connection->timer_id = Timer::add(1, function ($connection, $connectTIme) {
$connection->send($connectTIme);
}, [$connection, $connectTime]);
};
$worker->onClose = function (TcpConnection $connection) {
// 删除定时器
Timer::del($connection->timer_id);
};
Worker::runAll();
定时器为普通函数
<?php
/**
* timer.php
*
* 定时器案例
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
$worker->count = 1;
$worker->onWorkerStart = function (Worker $worker) {
$connectTime = date('Y-m-d H:i:s') . PHP_EOL;
// 定时器只执行一次
Timer::add(1, 'get_date', [$connectTime], false);
};
function get_date($connectTime) {
echo $connectTime;
};
Worker::runAll();
定时器为类的方法
<?php
/**
* timer.php
*
* 定时器案例,定时器方法为类的方法
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
class Person {
public function getName(string $name) {
echo $name . PHP_EOL;
}
}
$worker = new Worker();
$worker->count = 1;
$worker->onWorkerStart = function (Worker $worker) {
$person = new Person();
$name = '王美丽';
Timer::add(1, [$person, 'getName'], [$name]);
};
function get_date($connectTime) {
echo $connectTime;
};
Worker::runAll();
类中的方法使用定时器
<?php
/**
* timer.php
*
* 定时器案例,定时器方法为类的方法
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
class Person {
public function getName(string $name):void {
echo $name . PHP_EOL;
}
// 类的方法中使用定时器
public function handleTimer(string $name): void
{
Timer::add(1, [$this, 'getName'], [$name]);
}
}
$worker = new Worker();
$worker->onWorkerStart = function (Worker $worker) {
$person = new Person();
$name = '王美丽丽';
$person->handleTimer($name);
};
Worker::runAll();
定时器为类的静态方法
<?php
/**
* timer.php
*
* 定时器案例,定时器为类的静态方法
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
class Person {
public static function getName(string $name):void {
echo $name . PHP_EOL;
}
}
$worker = new Worker();
$worker->onWorkerStart = function () {
$name = '王小丽';
// 定时调用类的静态方法
Timer::add(1, [Person::class, 'getName'], [$name]);
};
Worker::runAll();
定时器为带有命名空间的类的静态方法
<?php
/**
* timer.php
*
* 定时器案例,定时器为类的静态方法
*/
namespace Task;
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
class Person {
public static function getName(string $name):void {
echo $name . PHP_EOL;
}
}
$worker = new Worker();
$worker->onWorkerStart = function () {
$name = '王小丽';
// 定时调用带命名空间的类的静态方法
Timer::add(1, [\Task\Person::class, 'getName'], [$name]);
};
Worker::runAll();
删除定时器
<?php
/**
* timer.php
*
* 定时器案例,删除定时器
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
$worker->onWorkerStart = function () {
$count = 1;
// 要把 $timerId 传递到函数内容,必须使用 &
$timerId = Timer::add(1, function () use (&$timerId, &$count) {
echo $count . PHP_EOL;
if ($count++ >= 3) {
echo '删除定时器 ' . $timerId . PHP_EOL;
Timer::del($timerId);
}
});
};
Worker::runAll();
传递参数的方式删除定时器
<?php
/**
* timer.php
*
* 定时器案例,删除定时器
*/
use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';
class Person
{
public function send(int $timerId):void
{
// 临时给当前对象添加一个count属性,记录定时器运行次数
$this->count = empty($this->count) ? 1 : $this->count;
echo $this->count . PHP_EOL;
if ($this->count++ >= 3) {
echo '定时器已删除' . PHP_EOL;
Timer::del($timerId);
}
}
}
$worker = new Worker();
$worker->onWorkerStart = function () {
$person = new Person();
$timerId = Timer::add(1, [$person, 'send'], [&$timerId]);
};
Worker::runAll();
关于定时器的注意事项请阅读文档,这里只摘抄一点:
- 只能在
onXXXX
回调中添加定时器。全局的定时器推荐在onWorkerStart
回调中设置,针对某个连接的定时器推荐在onConnect
中设置
crontab 定时器
workerman/crontab
是一个基于workerman的定时任务程序,类似linux的crontab。workerman/crontab
支持秒级别定时。
使用
workerman/crontab
需要先设置好php的时区,否则运行结果可能和预期的不一致。
时间说明
0 1 2 3 4 5
| | | | | |
| | | | | +------ day of week (0 - 6) (Sunday=0)
| | | | +------ month (1 - 12)
| | | +-------- day of month (1 - 31)
| | +---------- hour (0 - 23)
| +------------ min (0 - 59)
+-------------- sec (0-59)[可省略,如果没有0位,则最小时间粒度是分钟]
安装
$ composer require workerman/crontab --ignore-platform-req=ext-pthreads
crontab 使用
<?php
/**
* timer.php
*
* 定时器案例,每秒执行
*/
use Workerman\Worker;
use Workerman\Crontab\Crontab;
require_once __DIR__ . '/vendor/autoload.php';
date_default_timezone_set('PRC');
$worker = new Worker();
$worker->onWorkerStart = function () {
// 每秒执行一次
new Crontab('* * * * * *', function () {
echo date('Y-m-d H:i:s')."\n";
});
};
Worker::runAll();
请登录后再评论