本文分享了我在使用swoole毫秒定时器时遇到的一个坑,以及解决方法。希望对大家有所帮助。学习毫秒定时器之前,需要有基本的语法才能使用,请参考官方文档(https://wiki.swoole.com/#/timer),我就不照抄了。其中,使用毫秒定时器时要多注意一些注意事项,以防后面出错,不知道为什么。1、定时器只在当前进程空间有效。2.定时器是纯异步实现的,不能和同步IO功能一起使用。使用它,否则定时器的执行时间会紊乱。3.定时器的执行可能会出现一些错误。相信大家在看swoole的毫秒定时器的时候,都会按照官方的基础例子来做。但是在实际项目中如何结合呢?下面开始分享我在实际项目中是如何使用swoole定时器的。我们以think5.1框架为例。比如在某个controller中,使用毫秒定时器,按照官方文档写了这样一个例子。公共功能测试(){$param1='aaa';$path=__DIR__.'/demo.txt';//每隔两秒向demo.txt文件写入数据,用本例代替业务逻辑swoole_timer_tick(2000,function()use($param1,$path){file_put_contents($path,$param1.'|'.'1'.PHP_EOL,FILE_APPEND);});}你觉得有问题吗?现在运行一下,解释一下它是如何工作的:我们都知道swoole是以cli方式运行的,如果直接通过浏览器访问这个方法,肯定会报错。报表swoole只能在cli模式下运行。那么我们如何在cli下运行呢?在thinkphp中,我们可以在入口文件处通过如下方式运行swoole。phpindex.phpapi/task/testapi/task/testtp:modulename/controllername/methodname中访问方法发现错误。这个错误我google了半天,没看懂。问了官方作者后,解决了。你需要在程序末尾加入这样一段代码`publicfunctiontest(){$param1='aaa';$path=__DIR__.'/demo.txt';//每两秒去demo.txt文件写一次数据,用这个例子代替业务逻辑swoole_timer_tick(2000,function()use($param1,$path){file_put_contents($path,$param1.'|'.'1'.PHP_EOL,FILE_APPEND);});\Swoole\Event::wait();}`因为定时器是异步的,所以定时器执行完后,会继续执行,下面没有任何代码,程序就结束了。所以加一个wait操作,让程序阻塞在那里。这样定时器可以在两秒后继续执行,不会报错。联想:在swoole\server的onWorkerStart方法中使用定时器时,为什么不添加wait操作,因为wait操作其实是在server->start操作中添加的。swoole底层处理,让程序已经阻塞在start方法中。添加后,再次运行,发现没有报错,查看时文件中有数据。这时候,成功就已经过半了。这时发现程序一直在占用终端。如果我们按ctrl+c退出定时器,我们的业务逻辑就不会执行了。这时,另一个问题出现了。如果定时器能成为一个守护进程,一直在后台运行就好了。如何更改它在后台运行?分享我的两个做法。1.使用nohup命令(linux自带命令)。执行某条命令不挂断nohup/usr/local/php/bin/phpindex.phpapi/task/test>/dev/null2>&1&解释:在后台连续运行命令(/usr/local/php/bin/phpindex.phpapi/task/test),并将运行输出重定向到linxu的/dev/null(黑洞文件),2>&1为标准化输出。&是nohup的命令要求。这样,脚本就可以变成一个守护进程。如下图,不会占用光标,一直在后台运行。二、使用superviosr工具1、可以将一些脚本变成daemon进程。2、可以检测进程的情况,异常退出时自动重启。比如可以检测swoole的daemon进程是否异常退出,将脚本视为子进程,由supervisorr管理。区别:比如容错率优于nohup,适用于业务逻辑比较重要的场景。直接使用nohup更方便,无需下载supervisorr工具,适合边缘化的业务场景。我不会在本文中详细介绍superviosr。如果想了解更多可以看我的另一篇文章(https://segmentfault.com/a/11...),这里主要是给出解决问题的方向。好吧,这样我们就可以愉快的把swoole定时器和实际项目结合起来了。本文为叶宇文玲原创文章,转载无需联系本人,但请注明文章出处。文章来源:叶宇文玲的贴心文章(https://segmentfault.com/a/11...)
