我正在开发一个需要延迟PHP事件的在线PHP应用程序.基本上我需要能够在初始命中URL之后执行任意PHP代码x很多秒(但可能是几天).我需要相当精确地执行这些PHP事件,我也希望它具有相当的可扩展性.我正在努力避免安排一个cron作业每秒运行一次.我正在研究Gearman,但它似乎没有提供任何计划事件的能力,据我所知,PHP并不真正意味着作为一个守护进程运行.
如果我能告诉一些外部进程在下一个事件应该运行的确切时间在PHP服务器上轮询"事件检查器"URL,那将是理想的.此轮询时间需要能够随意减少或增加,因为事件可以被删除并添加到队列中.有什么想法以优雅的方式来实现这一目标吗?从外部调用PHP(必须解析HTTP请求或通过CLI调用)只需要很多开销就可以满足我的需求.
我目前的计划是编写一个PHP守护程序,它将使用gearman从PHP服务器运行事件和接口.PHP守护进程将围绕SplMinHeap构建,所以希望性能不会太糟糕.这个想法在我的口中留下了不好的味道,我想知道是否有人有更好的主意?想法略有改变.阅读编辑2.
编辑:
我正在创建一个在线游戏,让玩家轮流使用可变时间限制.我正在使用XMPP和BOSH来允许我向客户推送消息,但是我已经完成了所有这些工作.现在我正在尝试添加一个任意事件,该事件在从客户端播放之后触发,以便让客户端(以及游戏中的其他人员)花费很长时间.我无法在客户端使用定时触发器,因为这样可以被利用(因为客户端可以自己玩).希望有所帮助.
编辑2:
谢谢大家的反馈.虽然我认为你的大多数想法在小范围内都能很好地发挥作用,但我觉得它们不能很好地扩展(外部事件管理器)或缺乏该项目所需的准确性(CRON).此外,在这两种情况下,它们都是外部部件,可能会失败并增加已经很复杂的系统的复杂性.
我个人觉得满足这个项目要求的唯一干净的解决方案是编写一个处理延迟事件的PHP守护进程.我已经开始编写我认为第一个 PHP runloop.它处理观察套接字和执行延迟的PHP事件.希望当我接近完成这个项目时,我可以发布源代码,如果你们有兴趣的话.到目前为止,在测试中它已经证明是有希望的解决方案(没有内存泄漏或不稳定的问题).
编辑3:这是一个名为LooPHP的PHP事件循环库的链接,供有兴趣的人使用.
TL; DR要求
在延迟的时间(从几秒到几天)调用(最好是原生的)PHP
任意处理事件的创建/更新/删除(我期待大量取消的电话).
处理预定的高负荷事件(每台服务器100-1000秒)
通话时间应在预定时间的一秒钟内
在这一点上,我不愿意将代码库重写为另一种语言(也许有一天我会)
Zak.. 10
让您的php脚本进行exec调用,以便在您需要时使用命令"at"安排PHP脚本运行
exec("在22:56/usr/bin/php myscript.php");
at在指定时间执行命令.
从手册页:
允许相当复杂的时间规范,扩展POSIX.2标准.它接受HH:MM形式的时间来在特定时间运行作业.(如果该时间已经过去,则假设第二天.)您也可以指定午夜,中午或下午茶时间(下午4点),并且您可以在上午或下午运行时间为AM或PM的时间.晚间.您还可以说明作业将在哪一天运行,方法是在月份名称日期中提供可选年份的日期,或者给出MMDDYY或MM/DD/YY或DD.MM.YY表格的日期.日期的具体规定必须遵循一天中的时间规范.您也可以给出像现在这样的时间+计算时间单位,其中时间单位可以是分钟,小时,天,
此外,如果您需要一个第二时间分辨率,让您的脚本在分钟开始运行,然后只需要睡眠n秒,直到执行为止.
让您的php脚本进行exec调用,以便在您需要时使用命令"at"安排PHP脚本运行
exec("在22:56/usr/bin/php myscript.php");
at在指定时间执行命令.
从手册页:
允许相当复杂的时间规范,扩展POSIX.2标准.它接受HH:MM形式的时间来在特定时间运行作业.(如果该时间已经过去,则假设第二天.)您也可以指定午夜,中午或下午茶时间(下午4点),并且您可以在上午或下午运行时间为AM或PM的时间.晚间.您还可以说明作业将在哪一天运行,方法是在月份名称日期中提供可选年份的日期,或者给出MMDDYY或MM/DD/YY或DD.MM.YY表格的日期.日期的具体规定必须遵循一天中的时间规范.您也可以给出像现在这样的时间+计算时间单位,其中时间单位可以是分钟,小时,天,
此外,如果您需要一个第二时间分辨率,让您的脚本在分钟开始运行,然后只需要睡眠n秒,直到执行为止.
我认为只有PHP的解决方案很难(几乎不可能)实现.我提出了两个解决问题的方法.
肯德尔问的问题:
redis有多稳定:
Redis非常稳定.开发人员真的写了一些干净的C代码.你应该在github上查看;).许多大型网站也在使用redis.例如github.他们有一个非常有趣的博客文章,他们如何快速制作github :).superfeedr也使用redis.有很多大公司正在使用redis;).我建议你去谷歌吧;).
PHP是如何友好的redis:
PHP非常友好.很多用户都在为redis编写PHP库.协议非常简单.您可以使用telnet调试它;).例如,快速查看predis已实现阻塞弹出.
我将如何删除事件:
我认为你应该使用像ZRemCommand这样的东西.
Redis是一家高级键值商店.它与memcached类似,但数据集不是易失性的,值可以是字符串,与memcached完全相同,但也可以是列表,集合和有序集.所有这些数据类型都可以通过原子操作来操作,以推送/弹出元素,添加/删除元素,执行服务器端并集,交集,集合之间的差异等等.Redis支持不同类型的排序功能.
我想出了什么(伪代码....):
processor.php:
client.php:
######----client.php ######The user/browser I guess should generate these events. #$key1: should be unique. #$millis: when event should run #$event: just the event to work on. if ("add event") { zadd($key1, $millis, $event); } else if ("delete event") { zremove($key1, $event) } #Get event which has to be scheduled first $first = zrange($key1, 0, 0); if ($oldfirst <> $first) { #got different first event => notify wakeup.php. lpush($key2, $first); } $oldfirst = $first;wakeup.php:
####wakeup.php #### 1 time do something like nohup php wakeup.php #http://code.google.com/p/redis/wiki/IntroductionToRedisDataTypes => read sorted set part. while(true) { $first = zrange($key1, 0, 0); $event = blpop($key2, $timeoutTillFirstEvent); if ($event == nill) { #Blockingqueue has timedout which means event should be run by 1 of blocking threads. blpop($key2, $first); } }你可以使用PHP编写一个非常有效的调度程序(Okay redis是C所以kickass fast :)),这也是非常有效的:).我也想编写这个解决方案,所以保持调整;).我想我可以在一天内写出一个可用的原型....
我的java解决方案
今天早上我想我创建了一个java程序,可以用来解决你的问题.
下载:
访问github的下载页面以下载jar文件(包含所有依赖项).
安装:
java -jar schedule-broadcaster-1.0-SNAPSHOT-jar-with-dependencies-1277709762.jar
运行简单的PHP代码段
第一
php -f scheduler.php
下一个
php -f receiver.php
问题
我创建了这些小片段,希望你能理解如何使用我的程序.WIKI中还有一些文档.
App Engine的TaskQueue
一个快速的解决方案是使用具有合理免费配额的Google的应用引擎任务队列.之后,你必须支付你使用的费用.
使用此模型,App Engine的任务队列API允许您将任务指定为HTTP请求(请求的内容作为其数据,请求的目标URL作为其代码引用).以这种方式以编程方式引用捆绑的HTTP请求有时被称为"Web钩子".
重要的是,Task Queue API的离线特性允许您提前指定Web挂钩,而无需等待其实际执行.因此,应用程序可能会立即创建许多Web挂钩,然后将其交给App Engine; 然后系统将在后台异步处理它们(通过'调用'HTTP请求).此Web挂钩模型支持高效的并行处理 - App Engine可以同时调用多个任务或Web挂钩.
总而言之,Task Queue API允许开发人员通过将该工作分块到脱机Web挂钩中来异步执行后台工作.系统将代表应用程序调用这些Web挂钩,通过可能并行执行多个webhook来调度最佳性能.这种基于HTTP标准的粒度工作单元模型允许App Engine以适用于任何编程语言或Web应用程序框架的方式高效地执行后台处理.