热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于Swoole构建高性能Laravel应用系列——基于Swoole定时器实现毫秒级任务调度

Swoole提供了异步高精度定时器功能,该功能类似JavaScript的需要注意的是,Swoole实现的定时器与PHP自带的Swoole提供了两种类型的定时器,一种是每隔一定时间执行的定时器,一种是指定时间后一次性执行的定时器,下面我们分别看看这两种定时器的实现和使用。

Swoole 定时器简介

Swoole 提供了异步高精度定时器功能,该功能类似 Javascript 的 setInterval / setTimeout ,粒度为毫秒级,底层基于 epoll_wait (异步)和 setitimer (同步)实现,数据结构使用 最小堆 。定时器的添加和删除,全部为内存操作,无 IO 消耗,因此性能是非常高的。

需要注意的是,Swoole 实现的定时器与 PHP 自带的 pcntl_alarm 不同, pcntl_alarm 是基于时钟信号和 tick 函数实现的,最大仅支持到秒,此外不支持同时设定多个定时器程序,性能也很差。

Swoole 提供了两种类型的定时器,一种是每隔一定时间执行的定时器,一种是指定时间后一次性执行的定时器,下面我们分别看看这两种定时器的实现和使用。

Swoole 定时器的使用

间隔时钟定时器

在 Swoole 中,我们可以通过 Timer::tick 实现间隔时钟定时器,该定时器会每隔指定时间触发回调函数的执行:

\Swoole\Timer::tick(1000, function () {
    echo "Swoole 很棒\n";
});

Swoole 定时器需要在 PHP CLI 模式下才能运行,上述代码的意思是每隔 1000ms 执行一次回调函数打印字符串:

基于 Swoole 构建高性能  Laravel  应用系列 —— 基于 Swoole 定时器实现毫秒级任务调度

指定时钟定时器

此外,还可以通过 Timer::after 定义一个指定时间后执行的定时器,与间隔时钟定时器不同,这种定时器是一次性的,执行完成后就会销毁:

\Swoole\Timer::after(3000, function () {
    echo "Laravel 也很棒\n";
});

上述定义器的含义是 3000ms 后执行指定的回调函数,并且执行之后就退出程序:

基于 Swoole 构建高性能 Laravel 应用系列 —— 基于 Swoole 定时器实现毫秒级任务调度

清除定时器

对于一次性执行的指定时钟定时器,不用关心清除问题,而对于间隔时钟定时器,如果不定义清楚逻辑的话,会永远执行下去,直到程序退出,我们可以通过 Timer::clear 删除定时器来达到清除的目的,在具体实现的时候,将定时器 ID 传入该方法即可,上述两种定时器定义方法都会返回对应的定时器 ID, 因此,清除定义器可以作用于上述两种定时器:

/*$timerId = \Swoole\Timer::tick(1000, function () {
    echo "Swoole 很棒\n";
});*/

$timerId = \Swoole\Timer::after(1000, function () {
    echo "Laravel 也很棒\n";
});

\Swoole\Timer::clear($timerId);

这种情况下,两个定时器都不会调用,对于间隔时钟定时器,还可以这么清除:

$count = 0;
\Swoole\Timer::tick(1000, function ($timerId, $count) {
    global $count;
    echo "Swoole 很棒\n";
    $count++;
    if ($count == 3) {
        \Swoole\Timer::clear($timerId);
    }
}, $count);

这种情况下,定时器会在执行三次后退出:

基于 Swoole 构建高性能 Laravel 应用系列 —— 基于 Swoole 定时器实现毫秒级任务调度

基于 Swoole 定时器实现毫秒级任务调度

我们可以基于 Swoole 定时器实现毫秒级调度任务来替代 Linux 自带的 Cron Job(最小粒度是分钟),以 Laravel 框架为例,我们可以基于 LaravelS 扩展包 来定义一个继承自 CronJob 基类的调度任务类:

i, microtime(true)]);
        $this->i++;
        Log::info(__METHOD__, ['end', $this->i, microtime(true)]);

        if ($this->i == 3) { // 总共运行3次
            Log::info(__METHOD__, ['stop', $this->i, microtime(true)]);
            $this->stop(); // 清除定时器
        }
    }

    // 每隔 1000ms 执行一次任务
    public function interval()
    {
        return 1000;   // 定时器间隔,单位为 ms
    }

    // 是否在设置之后立即触发 run 方法执行
    public function isImmediate()
    {
        return false;
    }
}

然后到 config/laravels.php 配置文件中修改 timer 配置项如下:

'timer'  => [
    'enable' => true,
    'jobs'   => [
        // Enable LaravelScheduleJob to run `php artisan schedule:run` every 1 minute, replace Linux Crontab
        // \Hhxsv5\LaravelS\Illuminate\LaravelScheduleJob::class,
        // Two ways to configure parameters:
        // [\App\Jobs\XxxCronJob::class, [1000, true]], // Pass in parameters when registering
        \App\Jobs\Timer\TestCronJob::class, // Override the corresponding method to return the configuration
    ],
    'max_wait_time' => 5, // Max waiting time of reloading
],

接下来,我们启动或重启 Swoole 服务器:

php bin/laravels start

storage/logs 下的最新日志里就可以看到上述定时任务的输出了:

[2019-05-29 22:37:20] local.INFO: App\Jobs\Timer\TestCronJob::run ["start",0,1559140640.694025] 
[2019-05-29 22:37:20] local.INFO: App\Jobs\Timer\TestCronJob::run ["end",1,1559140640.752043] 
[2019-05-29 22:37:21] local.INFO: App\Jobs\Timer\TestCronJob::run ["start",1,1559140641.752905] 
[2019-05-29 22:37:21] local.INFO: App\Jobs\Timer\TestCronJob::run ["end",2,1559140641.754724] 
[2019-05-29 22:37:22] local.INFO: App\Jobs\Timer\TestCronJob::run ["start",2,1559140642.694884] 
[2019-05-29 22:37:22] local.INFO: App\Jobs\Timer\TestCronJob::run ["end",3,1559140642.696726] 
[2019-05-29 22:37:22] local.INFO: App\Jobs\Timer\TestCronJob::run ["stop",3,1559140642.698137]

我们重点关注三个「start」的日志记录,对应的时间戳正好相差 1 秒,符合我们的预期。注意定时器在执行的过程中可能存在一定误差,所以这个毫秒数是数量级级别的,并不是完全相等,而且时间单位越小,误差可能越大,不过这已经比 Linux 自带的任务调度只能精确到分钟要好很多了。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 我们


推荐阅读
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • 本文介绍了使用readlink命令获取文件的完整路径的简单方法,并提供了一个示例命令来打印文件的完整路径。共有28种解决方案可供选择。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文介绍了Oracle存储过程的基本语法和写法示例,同时还介绍了已命名的系统异常的产生原因。 ... [详细]
  • 利用空间换时间减少时间复杂度以及以C语言字符串处理为例减少空间复杂度
    在处理字符串的过程当中,通常情况下都会逐个遍历整个字符串数组,在多个字符串的处理中,处理不同,时间复杂度不同,这里通过利用空间换时间等不同方法,以字符串处理为例来讨论几种情况:1: ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
author-avatar
小石子Sandra
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有