• 每个程序员都应该知道的Swoole知识-定时器


    本节将讲述如下三个问题:

    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 c a l l b a c k , … … callback, …… callback,……params);

    这个函数的别名是 swoole_timer_tick() m s e c 为指定的时间,单位是毫秒。 msec 为指定的时间,单位是毫秒。 msec为指定的时间,单位是毫秒。callback 为时间到期后执行的函数。$callback 回调函数会接收多个参数,第一个是定时器的ID。注意:定时器仅在当前进程空间内有效。定时器是纯异步实现的,不能与阻塞IO的函数一起使用,否则定时器的执行时间会发生错乱。

    下面是定时器在 websocket 的 onMessage 回调函数中的一个 demo,

    在这里插入图片描述

    触发 onMessage 回调后在客户端打印出如下信息,截图

    在这里插入图片描述

    除此之外swoole还提供了另外一个函数 Timer::after 来实现定时器,这个函数是的作用是在指定时间后执行回调函数。函数原型如下:

    int Swoole\Timer::after(int $after_time_ms, callable c a l l b a c k f u n c t i o n , … … callback_function, …… callbackfunction,……params);

    这个函数的别名是 swoole_timer_after。Timer::after是一个一次性定时器,执行完成后就会销毁。示例代码如下:

    在这里插入图片描述

    除了设置定时器的函数外,Swoole还提供了另外几个函数:

    function Timer::set(array $array); //设置定时器的参数
    Timer\Iterator Timer::list();//返回定时器迭代器, 可使用foreach遍历全局所有timer的id
    array Timer::info(int $id);//返回timer的信息
    bool Swoole\Timer::clear(int $timer_id);//使用定时器ID来删除定时器
    bool Timer::clearAll();//清除当前工作进程内的所有定时器

    3、Swoole定时器的底层原理

    Swoole定时器底层是基于epoll_wait 和 setitimer 实现,数据结构使用的是最小堆。

    Swoole定时器回调函数的执行时间不影响下一次定时器执行的时间。如果定时器回调函数的执行时间过长,甚至覆盖了下一次定时器执行的时间。底层会进行时间校正,丢弃已过期的行为,在下一时间回调。

  • 相关阅读:
    语雀故障事件——P0级别事故启示录 & 发生肾么事了? 怎么回事?
    二叉树的前序、中序、后序、层序遍历
    MySQL库的操作『增删改查 ‖ 编码问题 ‖ 备份与恢复』
    千呼万唤openGauss资源池化系列培训来了
    【AcWing】829. 模拟队列
    bfc块级格式化上下文
    车载导航进阶「不输」手机,哪些供应商在领跑导航引擎赛道
    【数据结构(三)】双向链表(2)
    Java-单列集合Collection详解
    [LeetCode]-160. 相交链表-141. 环形链表-142.环形链表II-138.随机链表的复制
  • 原文地址:https://blog.csdn.net/CRMEB/article/details/126701098