共计 1551 个字符,预计需要花费 4 分钟才能阅读完成。
本节将讲述如下三个问题:
PHP 自身的定时器介绍 Swoole 中定时器的应用办法 Swoole 定时器的底层原理
1、PHP 自身的定时器介绍
先说说原生 PHP 如何实现定时器,PHP 的定时器是通过 pcntl_alarm 实现的:
pcntl_alarm (int $seconds):int
pcntl_alarm 函数的作用是为过程设置一个 alarm 闹钟信号。调用这个办法后会创立一个计数器,在指定的秒数后向过程发送一个 SIGALRM 信号。每次对 pcntl_alarm 的调用都会勾销之前设置的 alarm 信号。
其中,$seconds 为期待的秒数,如果 $seconds 设置为 0,将不会创立 alarm 信号。调用这个函数后返回上次 alarm 调度残余的秒数,或者之前没有 alarm 调度时返回 0。
上面咱们看一个例子,pcntl_signal () 函数装置信号处理器,pcntl_signal_dispatch () 调用期待信号的处理器。
pcntl_alarm () 函数是基于时钟信号 + tick 函数实现的,存在一些缺点:
最大进反对到秒,而 Swoole Timer 能够到毫秒级别不反对同时设定多个定时器程序 pcntl_alarm () 依赖 declare (ticks = 1),性能很差
2、Swoole 中定时器的应用办法
Swoole 中的定时器能够达到毫秒精度,同时能够反对增加大量定时器。
在 Swoole 中能够应用 Timer::tick 来设置一个距离时钟定时器,调用 Timer::clear 来革除定时器。函数定义如下:
int Swoole\Timer::tick(int $msec, callable $callback, ……$params);
这个函数的别名是 swoole_timer_tick ()。$msec 为指定的工夫,单位是毫秒。$callback 为工夫到期后执行的函数。$callback 回调函数会接管多个参数,第一个是定时器的 ID。留神:定时器仅在以后过程空间内无效。定时器是纯异步实现的,不能与阻塞 IO 的函数一起应用,否则定时器的执行工夫会产生错乱。
上面是定时器在 websocket 的 onMessage 回调函数中的一个 demo,
触发 onMessage 回调后在客户端打印出如下信息,截图
除此之外 swoole 还提供了另外一个函数 Timer::after 来实现定时器,这个函数是的作用是在指定工夫后执行回调函数。函数原型如下:
int Swoole\Timer::after(int $after_time_ms, callable $callback_function, ……$params);
这个函数的别名是 swoole_timer_after。Timer::after 是一个一次性定时器,执行实现后就会销毁。示例代码如下:
除了设置定时器的函数外,Swoole 还提供了另外几个函数:
function Timer::set (array $array); // 设置定时器的参数
Timer\Iterator Timer::list ();// 返回定时器迭代器,可应用 foreach 遍历全局所有 timer 的 idarray
Timer::info (int $id);// 返回 timer 的信息
bool Swoole\Timer::clear (int $timer_id);// 应用定时器 ID 来删除定时器
bool Timer::clearAll ();// 革除当前工作过程内的所有定时器
3、Swoole 定时器的底层原理
Swoole 定时器底层是基于 epoll_wait 和 setitimer 实现,数据结构应用的是最小堆。
Swoole 定时器回调函数的执行工夫不影响下一次定时器执行的工夫。如果定时器回调函数的执行工夫过长,甚至笼罩了下一次定时器执行的工夫。底层会进行工夫校对,抛弃已过期的行为,在下一时间回调。