这篇文章主要介绍了关于PHP定时器的说明,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

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

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

原因

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

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

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

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

危险的做法

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

请求http://localhost:8080/test.php文件后,监测/tmp/out.dat文件,会发现不断有内容输出,无论客户端是否断开连接、关闭浏览器或者重启电脑(不能重启服务器)。这说明程序一直在执行,并且也实现了我们想要的定时器功能。如果把sleep改成usleep、time_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代码控制。在这种形式下,实现定时器就有多种玩法。本文列出几种做法,抛砖引玉:使用swoole、workerman等框架,内置(高精度)定时器;

使用多进程(池)/多线程(池)技术(pcntl、pthreads拓展在CLI模式下才可用);

处理tick或者alarm等信号;

使用libevent、libev等事件驱动库;

sleep加循环或自己实现事件循环。

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

总结

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

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

php定时器使用,PHP定时器的说明相关推荐

  1. STM32F4 定时器TIM(1)定时器控制输出【使用库函数】

    高级时钟控制定时器TIM1&TIM8简介: STM32F4的高级控制定时器包含一个自动重装载计数器,计数器的输入是一个被预分频的系统时钟. 这个定时器有多种用途,包括车辆输入信号长度(输入捕获 ...

  2. STM32定时器学习---基本定时器

    STM32F1系列的产品,除了互联型产品外,工位8个定时器  TIM6.TIM7:基本定时器  TIM2/3/4/5:通用定时器  TIM1.TIM8:高级定时器 三种定时器的区别:  基本定时器:  ...

  3. 实现quartz定时器及quartz定时器原理介绍

    今天研究定时器,在网上看了一篇不错的文章,推荐给大家! 实现quartz定时器及quartz定时器原理介绍

  4. mysql查看是否开启定时器_Mysql 查看定时器 打开定时器 设置定时器时间

    1.查看是否开启evevt与开启evevt. 1.1.MySQL evevt功能默认是关闭的,可以使用下面的语句来看evevt的状态,如果是OFF或者0,表示是关闭的. show VARIABLES ...

  5. TCP的定时器系列 — 保活定时器(有图有代码有真相!!!)

    转载 主要内容:保活定时器的实现,TCP_USER_TIMEOUT选项的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 原理 HTTP有Keepa ...

  6. TCP的定时器系列 — SYNACK定时器

    转载 主要内容:SYNACK定时器的实现,TCP_DEFER_ACCPET选项的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 在上一篇博客中,已 ...

  7. java 定时器框架_java定时器

    java定时器 什么是Java定时器? Java 定时器就是在给定的间隔时间执行自己的任务; Java实现定时器有以下几种: 通过Timer来实现定时任务 Timer 是来自 java.util.Ti ...

  8. 定时器中断实验 编写程序使定时器0或者定时器1工作在方式2,自动重装载模式,定时500ms使两位数码管从00、01、02……98、99每间隔500ms加1显示。

    编写程序使定时器0或者定时器1工作在方式2,自动重装载模式,定时500ms使两位数码管从00.01.02--98.99每间隔500ms加1显示. 程序: #include <reg51.h> ...

  9. 定时器中断实验 编写程序使定时器0或者定时器1工作在方式1,定时500ms使两位数码管从00、01、02……98、99每间隔500ms加1显示。

    编写程序使定时器0或者定时器1工作在方式1,定时500ms使两位数码管从00.01.02--98.99每间隔500ms加1显示. 程序: #include <reg51.h> #defin ...

  10. 定时器中断实验 编写程序使定时器0或者定时器1工作在方式1,定时50ms触发蜂鸣器。

    编写程序使定时器0或者定时器1工作在方式1,定时50ms触发蜂鸣器. 程序: #include<reg51.h> sbit fm=P2^3; unsigned char cnt; int ...

最新文章

  1. 美团某程序员爆料:绩效背c的都要签pip!网友:pip就是变相劝退!
  2. Apache Flink Meetup · 上海站,超强数据湖干货等你!
  3. How to resolve Unable to load groups error message
  4. .写一个方法 void printScore(int score),输出相应的等级。score代表分数,等级格式如下:
  5. 《C++语言入门经典》一第3章 重要的逻辑工具——判断与循环 3.1 条件判断...
  6. C中的volatile用法
  7. [转帖]规模化敏捷-简要对比SAFe、LeSS和DAD模式
  8. oracle缺少控制文件,关于oracle丢失控制文件的恢复办法
  9. 2022最新软件库iApp源码+简约唯美/对接hybbs
  10. 误用分区助手的沉痛教训
  11. 【论文笔记】ASNet:基于生成对抗网络(GAN)的无监督单模和多模配准网络(范敬凡老师)
  12. 直播 编解码、 协议、网络传输
  13. Xshell键盘数字键不能用怎么办?
  14. 五种常用的Web安全认证方式
  15. matlab偏最小二乘截距,matlab代写偏最小二乘回归(PLSR)和主成分回归(PCR)
  16. 统计出库数,sql查询数据,sqldf做透视表,循坏处理数据
  17. 第六章 林冲为什么休妻
  18. IDEA查看历史记录【文件历史和项目历史】
  19. Test Renderer
  20. Linux---进程调度及CFS调度器

热门文章

  1. dump mysql database,Mysql Database 逻辑备份: mysqldump
  2. react-native 发送接收“广播”
  3. android 上下滑动重影
  4. Java的ATM界面任务台选择同时有文本和数据库登陆注册
  5. 基于JAVA+SpringBoot+Mybatis+MYSQL的高校运动会管理系统
  6. Notes on how to use Webots, especially how to make a robot fly in the air
  7. Innobackupx工具命令简单解析
  8. Ubuntu16.04下配置laravel
  9. IOS - plist使用
  10. tdbgrid 数据类型输入错误 vb_VB编程从起始到普及历程了解一下