本节将介绍以下三个问题:PHP本身的定时器介绍定时器在Swoole中的使用Swoole定时器的底层原理1.PHP本身的定时控制器介绍先说原生PHP是如何实现定时器的。PHP定时器是通过pcntl_alarm实现的:pcntl_alarm(int$seconds):intpcntl_alarm的作用是为进程设置一个报警信号。调用此方法会创建一个计数器,该计数器会在指定的秒数后向进程发送SIGALRM信号。每次调用pcntl_alarm都会取消先前设置的警报信号。其中,$seconds为等待的秒数,如果$seconds设置为0,则不会创建报警信号。返回调用此函数后距离最后一次警报调度剩余的秒数,如果没有先前的警报调度,则返回0。下面看一个例子,pcntl_signal()函数安装信号处理器,pcntl_signal_dispatch()调用等待信号的处理器。pcntl_alarm()函数是基于时钟信号+tick函数实现的,存在一些缺陷:最大进度支持到秒,SwooleTimer可以达到毫秒级别,不支持同时设置多个定时器.程序pcntl_alarm()依赖declare(ticks=1),性能很差2.Swoole中的定时器如何使用Swoole中的定时器可以做到毫秒级精度,可以支持添加大量的定时器。在Swoole中,可以使用Timer::tick设置一个间隔时钟定时器,调用Timer::clear清除定时器。函数定义如下:intSwoole\Timer::tick(int$msec,callable$callback,...$params);这个函数的别名是swoole_timer_tick()。$msec是以毫秒为单位的指定时间。$callback是时间到期后要执行的函数。$callback回调函数会接收多个参数,第一个是定时器的ID。注意:定时器只在当前进程空间有效。timer是纯异步实现的,不能和阻塞IO的函数一起使用,否则timer的执行时间会紊乱。下面是一个定时器在websocket的onMessage回调函数中的demo。触发onMessage回调后,客户端打印如下信息。除了截图,swoole还提供了另一个函数Timer::after来实现定时器。这个函数yes的作用是在指定时间后执行回调函数。函数原型如下:intSwoole\Timer::after(int$after_time_ms,callable$callback_function,...$params);这个函数的别名是swoole_timer_after。Timer::after是一个一次性定时器,执行完就会被销毁。示例代码如下:除了设置定时器的功能,Swoole还提供了其他几个功能:functionTimer::set(array$array);//设置定时器的参数Timer\IteratorTimer::list();//返回定时器迭代器,可以使用foreach遍历所有全局定时器idarrayTimer::info(int$id);//返回定时器信息boolSwoole\Timer::clear(int$timer_id);//使用定时器ID来删除定时器boolTimer::clearAll();//清除当前工作进程中的所有定时器三、Swoole定时器底层原理底层原理Swoole定时器的实现基于epoll_wait和setitimer,数据结构采用最小堆。Swoole定时器回调函数的执行时间不影响下一次定时器执行的时间。如果定时器回调函数的执行时间过长,甚至会覆盖定时器的下一次执行时间。底层会进行时间校正,丢弃过期的行为,下次再回调。
