首先需要解释的是什么是守护进程.
守护进程就是在后台一直运行的进程. 比如我们启动的 httpd,mysqld 等进程都是常驻内存内运行的程序.
针对需求进行分析:
需求: 有一个常驻队列 messageQueue(假设在 Redis 内存中), 这个队列会有可能有请求不定期的往队列中增加元素. 同时我们要求在队列中有元素的时候, 按照队列顺序将元素 pop 出来, 并进行处理 (假设这个处理只是 echo 'test');
解决方法:
现在假设已经有了两个函数
function oPopMessageQueue(){ ...} // 获取队列最后一个元素;
function vDealElement($element) { ...} 处理元素;
要求写出一个守护程序, 完成上面的需求.
程序:
好了, 这个程序很容易想到, 可以使用 while 循环来做
- while(true)
- {
- if( $element = oPopMessageQueue())
- {
- vDealElement($element);
- }
- }
考虑 1 : 这个程序如果一直跑的话已经可以满足上面的需求了.
但是考虑到: 1 用 PHP 进程跑有可能会由于各种情况 (比如运行时间过长), 进程挂了, 这样程序就无法自动重连了.
方法: 使用 cron
我们在定时脚本中每 10 分钟起一个进程跑这个程序.
然后设置这个程序的运行时间为 10 分钟, 10 分钟后自动取消, 于是代码变成
- while(true)
- {
- if($element = oPopMessageQueue())
- {
- vCheckTimeLimit();
- vDealElement($elemnt);
- }
- }
- $timeStart = 0;
- function vCheckTimeLimit()
- {
- global $timeStart;
- if(empty($timeStart))
- {
- $timeStart = time();
- }
- if(time() - $timeStart> 60*10)
- {
- exit;
- }
- }
考虑 2, 可能会有这种需求: 需要有随时让脚本暂停的功能:
于是考虑使用文件来增加暂停功能
- while(true)
- {
- if($element = oPopMessageQueue())
- {
- vCheckTimeLimit();
- vCheckEnd();
- vDealElement($elemnt);
- }
- }
- function vCheckEnd()
- {
- if(file_exists("/home/JesephYe/end"))
- {
- exit;
- }
- }
考虑 3, 是否可以改成多线程的程序, 让运行的效率更高?
这个只要把 cron 的 10 分钟起一个进程的限制改成每 1 分钟起一个进程就好了
这样能保证有 10 个线程在运行程序
但是有一个基本要求是: oPopMessageQueue() 是一个原子操作
来源: http://www.bubuko.com/infodetail-2880303.html