12. swoole基础-swoole之定时器
说起定时器,大家都不陌生。我最早接触定时器的概念,是javascript的setInterval和setTimeout这两个函数,前者会持续执行,后者仅会执行一次。
在后端开发中,一些涉及到定时器相关的需求,比如数据库备份,排行榜数据更新等,通常我们可以借助linux的crontab工具实现。但是对于一些想精确到秒级别或者想暂停定时器的需求,就相对麻烦一些了。
直到swoole的诞生,异步毫秒级的定时器真的是好用到没得说。
相对与javascript的setInterval和setTimeout,swoole也提供了永久性定时器和一次性定时器,我们分别来看下怎么玩。
永久性定时器
所谓的永久性定时器,就是在设定好定时器之后,该定时器就会按照一定的时间间隔执行,直到该定时器被删除。
这种类型的定时器,我们可以使用swoole_timer_tick函数创建,该函数接收3个参数,原型如下
int swoole_timer_tick(int $ms, callable $callback, mixed $params);
- $ms 指时间,单位毫秒
- $callback 回调函数,定时器创建后会调用该函数
- $params 传递给回调函数的参数
即创建一个\(ms毫秒后执行\)callback的定时器。
来看一个简单的例子
swoole_timer_tick(1000, function () {
echo "This is a tick.\n";
});
案例中我们创建了一个永久性定时器,每1000毫秒即每秒执行一次回调函数,输出"This is a tick.\n"。
定时器的清除,可以使用swoole_timer_clear函数操作,该函数接收一个参数,定时器的id,函数原型如下
bool swoole_timer_clear(int $timerId)
再来看一个稍微完整的例子
<?php
$i = 0;
swoole_timer_tick(1000, function ($timeId, $params) use (&$i) {
$i ++;
echo "hello, {$params} --- {$i}\n";
if ($i >= 5) {
swoole_timer_clear($timeId);
}
}, 'world');
事例中我们创建了一个定时器,该定时器每秒执行一次,swoole_timer_tick的第二个参数即回调函数,该函数的参数$timeId是创建的定时器的id, \(params是swoole_timer_tick的第三个参数传递的值,use闭包中我们取了变量\)i的地址,在回调函数中,我们对\(i ++处理,当\)i >= 5的时候,用swoole_timer_clear函数清除了定时器。运行下该文件,我们看看结果

需要说明的是,swoole_timer_tick函数是全局性的,通常情况下是可以在任意地方调用。
另外,如果在事件的回调函数内,我们还可以通过swoole_server->tick函数创建永久性定时器,并使用swoole_server->clearTimer函数清除定时器,比如上面的例子我们可以在回调函数onWorkerStart中这样写
<?php
$serv->set([
'worker_num' => 2,
]);
$serv->on('WorkerStart', function ($serv, $workerId){
if ($workerId == 0) {
$i = 0;
$params = 'world';
$serv->tick(1000, function ($timeId) use ($serv, &$i, $params) {
$i ++;
echo "hello, {$params} --- {$i}\n";
if ($i >= 5) {
$serv->clearTimer($timeId);
}
});
}
});
代码总体上就不分析了,只看一点,为什么在onWorkerStart回调内判断了$workerId是否等于0?
注意到我们开启了两个Worker进程,如果不判断,那么就会在两个Worker进程内各注册一个定时器,实际上也就是我们注册了两个相同的定时器,这是没有必要的。
注:swoole_server->tick等价于swoole_timer_tick,swoole_server->clearTimer等价于swoole_timer_clear。
一次性定时器
一次性定时器执行完一次之后,便会自动销毁。这种场景往往是当xxx几秒之后再执行。
同样也有两个函数供我们使用,全局的swoole_timer_after和回调内可调用的swoole_server->after。
前者的参数等同于swoole_timer_tick,只有一点不同,该函数所支持的最大毫秒数是86400000。
同样我们看两个简单的demo
swoole_timer_after(3000, function () {
echo "only once.\n";
});
回调内执行,我们这回举一个在onReceive内为例
$serv->on('Receive', function ($serv, $fd, $fromId, $data) {
$serv->after(3000, function () {
echo "only once.\n";
});
});
以后再也不用crontab了,这随随便便简简单单的就实现了定时器的功能,so easy~
代码已上传到github,需要的可以参考

浙公网安备 33010602011771号