实例解析PHP定时器的具体实现

admin3年前PHP教程44
目录
前言原因危险的做法正确的姿势CLI模式总结
前言

常见的定时器有两种:一种周期性定时执行,例如每天的凌晨三点出报表;另一种在指定时间后执行(一次),例如会员登录系统五分钟后发放每日登录奖励。两种情况对应shell中的cronat命令,与JavaScript中的setIntervalsetTimeout函数类似(严格来说setInterval是周期性执行,指定时间点执行需要自行处理)。

做web开发的PHP程序员对JavaScript中的两个定时器函数应该都还熟悉,回到PHP层面就有点傻眼:PHP中有sleep,但是没有(内置)定时器函数可用。sleep函数勉强可以做到,但会导致进程阻塞,期间不能做其他事(或无响应)。为什么PHP没能提供定时器(Timer)这个功能呢?

原因

个人认为,web开发中PHP不能使用定时器的本质原因是可控 常驻内存运行环境的缺失。两个要点:第一常驻内存,第二可控。CGI模式下,进程执行完脚本后直接退出,不能指望其到指定时间运行任务;PHP-FPM模式下,进程(绝大多数)常驻内存,但不可控。

不可控的意思是执行PHP的进程不受PHP代码影响,进程的入口点和退出时机由额外的程序控制。例如FPM模式下,PHP脚本中的exitdie函数只中断脚本的执行,不会对执行脚本的进程产生特别的影响(内存泄露除外)。PHP开发人员编写的脚本是进程的执行体,执行完毕后就从进程的执行上下文中卸载出去。这种情况下,执行PHP脚本的时机仍然由外部驱动,没有外部请求PHP代码就安详的躺在硬盘上,什么都不做,也就定时任务。

由于PHP主要面向web开发,PHP这种执行模式稳定可靠,开发效率快。比如省去资源释放这一步,就避免了开发中很多工作量和坑。想想某些第三方库代码中改时区、字符编码等还不还原,在常驻内存运行环境下几乎肯定会导致后续请求有问题。但在FPM模式下,这种坑无意中直接趟平,省去许多调试时间,为程序员保住发际线做出了不小的贡献。

问题已经了解,那么PHP中如何使用定时器执行定时任务?

危险的做法

在web环境下,PHP脚本默认有超时时间。去掉超时设置,就可以让程序一直在后台运行(如果进程不退出的话)。例如以下代码在响应请求后继续后台运行,并且每五秒钟输出一次时间到文件:

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# test.php
 
set_time_limit(0); # 取消超时设置,让脚本可一直运行
 
 
 
echo 'This is a background run forever script. Now you can leave me alone.';
 
 
 
fastcgi_finish_request();   # 结束当前请求
 
 
 
do{
 
   file_put_contents("/tmp/out.dat", "test script, now:" . date("Y-m-d H:i:s") . "\n", FILE_APPEND);
 
   sleep(5);
 
}while(true);

请求localhost:8080/test.php文件后,监测/tmp/out.dat文件,会发现不断有内容输出,无论客户端是否断开连接、关闭浏览器或者重启电脑(不能重启服务器)。这说明程序一直在执行,并且也实现了我们想要的定时器功能。如果把sleep改成usleeptime_nanosleep,还能实现微秒、纳秒级定时器,岂不美哉?

实践中应当尽量避免用这种方式实现定时器,不仅因为低效,还略有危险。原因之一是每次请求会占用一个进程,请求十万次需要十万个进程,基本上会导致系统崩溃或后续请求无响应;另外如果打开了session,但是忘记调用session_write_close,会导致同一个用户的后续请求被hang住(session活跃时处于加锁状态,不关闭session会导致后续进程无法打开session)。

web开发应当越快响应用户的请求越好,在web开发中用这种方式强行实现定时器,会让整个web应用处于不稳定、不可靠或不可预测状态。孟子曰:知而慎行,君子不立于危墙之下。不靠谱的做法要尽量避免,顺带也避免背锅和甩锅。

接下来看看PHP中使用定时器的正确姿势。

正确的姿势

PHP实现定时器的做法可简单归结为如下几种:

    使用cron、Jenkins等调度工具做周期性定时任务(既可以是执行脚本,也可以是请求某个网址);一次性执行任务通过消息队列、数据库等方式投递给第三方程序执行;像WordPress一样模拟定时任务,但要记住这种方式依赖于客户端请求,并需自行处理好进程并发问题;使用常驻内存型方式运行PHP程序,即CLI模式。

除了第三种做法,其他方式都是推荐的,具体方案请结合实际需求。作为PHP程序员,当然还是首选用PHP来做,也就是CLI模式。

CLI模式

摸着良心说,CLI模式让PHP发挥的空间拓展不少。在CLI模式下,程序的入口点就是脚本,且代码可以常驻内存,进程完全由PHP代码控制。在这种形式下,实现定时器就有多种玩法。本文列出几种做法,抛砖引玉:

    使用swooleworkerman等框架,内置(高精度)定时器;使用多进程(池)/多线程(池)技术(pcntlpthreads拓展在CLI模式下才可用);处理tick或者alarm等信号;使用libeventlibev等事件驱动库;sleep加循环或自己实现事件循环。

想折腾的话自己用2-5方案,不想折腾swooleworkerman等框架是首选,稳定可靠。

总结

区分HTTP请求和任务的关系,实现定时任务就简单了。至于用不用PHP来实现,那是另外一回事。当然作为web开发的首选语言,PHP实现定时任务也是轻而易举的。

到此这篇关于实例解析PHP定时器的具体实现的文章就介绍到这了,更多相关PHP 定时器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

免责声明:本文内容来自用户上传并发布,站点仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。请核实广告和内容真实性,谨慎使用。

相关文章

深入理解php底层之php生命周期

1、PHP的运行模式 PHP两种运行模式是WEB模式、CLI模式。无论哪种模式,PHP工作原理都是一样的,作为一种SAPI运行。1、当我们在终端敲入php这个命令的时候,它使用的是CLI。它...

韩国高防服务器购买方法主要看哪些方面

韩国高防服务器购买方法主要看哪些方面?购买韩国高防服务器的方法可以分为以下几步:确定需求:首先需要确定自己的需求,包括需要租用多少服务器、需要防御什么类型的攻击、需要的网络带宽等等。确定预算:根据自己...

如何用PHP实现分布算法之一致性哈希算法

目录传统算法缺陷算法思想算法实现总结传统算法缺陷对于服务器分布,我们要考虑的东西有如下三点:数据平均分布,查找定位准确,降低宕机影响。传统算法一般是将数据的键用算法映射出数字,对其用服务器数量取模,并...

勒索攻击到底该怎么防御?美国电信高防服务器如何防御DOSS攻击?

当前,勒索攻击、僵尸网络攻击、DDos攻击、APT攻击、挖矿攻击、供应链攻击、网站攻击、电信诈骗等各种攻击手段层出不穷。勒索攻击应该是今年网络安全行业讨论最多的话题,勒索钱财或者窃取商业数据是黑产最主...

海外多ip服务器被恶意攻击了怎么办

海外多ip服务器被恶意攻击的解决方法:1、对网站攻击进行评估,根据具体的攻击进行具体的防御;2、建立镜像网站,将网站的客户引到镜像网站中去;3、建立预防DDoS策略,并定期对服务器进行查毒杀毒,能降低...

法国服务器租用注意什么问题

法国服务器租用注意什么问题?租用法国服务器时需要注意以下几个问题:法律合规性:在法国进行服务器租赁的企业必须遵守法国的相关法律法规,包括税务法、金融法、数据隐私法等。数据安全:为了保护企业的数据安全,...