在Windows上运行PHP应用程序 – 守护程序或cron?

我需要一些实施build议。 我有一个MYSQL数据库,将远程写入任务在本地进行处理,而且我需要使用PHP编写的应用程序,在他们进来时执行这些任务。

当然,我的PHP应用程序需要被告知什么时候运行。 我想过使用cron作业,但我的应用程序是在Windows机器上。 其次,我需要每隔几秒钟检查一次,而cron只能每分钟做一次。

我想写一个PHP的守护进程,但我已经得到了很好的工作,如果它甚至是一个好主意!

我将不胜感激任何build议,最好的方式来做到这一点。

Solutions Collecting From Web of "在Windows上运行PHP应用程序 – 守护程序或cron?"

pyCron是Windows的一个很好的CRON替代品:

pyCron

由于这个任务非常简单,我只需要设置pyCron就可以每分钟运行一下脚本:

set_time_limit(60); // one minute, same as CRON ;) ignore_user_abort(false); // you might wanna set this to true while (true) { $jobs = getPendingJobs(); if ((is_array($jobs) === true) && (count($jobs) > 0)) { foreach ($jobs as $job) { if (executeJob($job) === true) { markCompleted($job); } } } sleep(1); // avoid eating unnecessary CPU cycles } 

这样,如果电脑出现故障,你将会有60秒的最坏情况延迟。

您可能还想要查看信号量或某种锁定策略,如使用APC变量或检查是否存在锁定文件以避免竞争状况,例如使用APC:

 set_time_limit(60); // one minute, same as CRON ;) ignore_user_abort(false); // you might wanna set this to true if (apc_exists('lock') === false) // not locked { apc_add('lock', true, 60); // lock with a ttl of 60 secs, same as set_time_limit while (true) { $jobs = getPendingJobs(); if ((is_array($jobs) === true) && (count($jobs) > 0)) { foreach ($jobs as $job) { if (executeJob($job) === true) { markCompleted($job); } } } sleep(1); // avoid eating unnecessary CPU cycles } } 

如果你坚持使用PHP守护进程,请自己帮忙,放弃这个想法,改用Gearman。

编辑 :我问了一个相关的问题,可能会让你感兴趣: 在PHP分布式​​系统的解剖 。

我会提出一些不寻常的建议:你说你需要在数据写入MySQL的时候运行这个任务。 这意味着MySQL“知道”应该执行的事情。 这听起来像MySQL的UDF sys_exec完美的场景。

基本上,如果一旦发生了事情,MySQL可以调用外部程序,那就太好了。 如果你使用上面提到的UDF,你可以从内部执行一个php脚本,比如INSERT或UPDATE触发器。 另一方面,你可以使它更加资源友好,创建MySQL事件(假设你使用合适的版本),它将使用sys_exec来调用一个PHP脚本,该脚本以预定的时间间隔进行某些更新 – 这减少了对Cron或任何类似的程序,可以执行预定义的时间间隔。

我肯定不会建议使用这个cronjobs。

cronjobs是一件好事,对于很多目的来说非常有用和容易,但是当你描述你的需求的时候,我认为它们可以产生更多的复杂性。 这里有一些要考虑的事情:

  • 如果职位重叠会发生什么? 执行一分钟需要更长的时间? 有没有共享资源/死锁/临时文件? – 最常用的方法是使用锁定文件,如果在程序开始时占用权限,则停止执行。 但是该计划在完成之前还需要寻找更多的工作。 – 然而,这也可以在Windows机器上变得复杂,因为他们AFAIK不支持开箱即用的写锁

  • cronjobs是一个痛苦的屁股维护。 如果你想监视它们,你必须在程序最后一次运行时执行额外的逻辑,比如检查。 然而,如果你的程序只能按需运行,这可能会变得困难。 最好的方法是在数据库中的某种“作业完成”字段或删除已处理的行。

  • 在大多数基于Unix的系统上,cronjobs现在是相当稳定的,但是有很多situatoos可以打破你的cronjob系统。 其中大部分是基于人为错误的。 例如,在编辑模式下没有正确退出crontab编辑器的系统管理员可能会导致所有的cronjob被删除。 由于上述原因,很多公司也没有适当的监控系统,只要服务出现问题就会通知。 在这一点上往往没人写下/放在哪个cronjob应该运行的版本控制下,野外的猜测和重建工作就开始了。

  • 当使用外部工具时,cronjob维护可能会变得更加复杂,并且环境不是本地unix系统。 系统管理员必须获得更多的程序的知识,他们可能会有潜在的错误。

我真的认为只是一个小的脚本,你从控制台开始,让开放就好了。

 <?php while(true) { $job = fetch_from_db(); if(!$job) { sleep(10) } else { $job->process(); } } 

你也可以在每个循环中触摸一个文件(修改修改时间戳),你可以编写一个nagios脚本来检查时间戳是否过时,这样你就知道你的作业还在运行。

如果你想要启动系统,我推荐一个deamon。

ps:在我工作的公司里,我们的网站有很多后台活动(爬行,更新流程,计算等等),当我开始时,cronjobs真是一团糟。 他们分布在负责不同任务的不同服务器上。 数据库被广泛的访问互联网。 一吨nfs filesytems,samba股份等等到位共享资源。 这个地方充满了单点故障,瓶颈和不断破裂的事情。 有太多的技术涉及到维护非常困难,当某些事情不起作用时,需要几个小时的时间来追踪这个问题,还有一小时这个部分甚至应该做什么。

现在我们有一个统一的更新程序,负责字面上的everyhing,它运行在几个服务器上,他们有一个配置文件,定义要运行的工作。 eveyrthing从一个父进程派生出来,进行无限循环。 它易于监控,自定义,同步和一切运行顺利。 它是多余的,它是同步的,粒度很好。 所以它可以并行运行,我们可以扩展到尽可能多的服务器。

我真的建议坐下来休息一下,把所有事情都作为一个整体来思考,并且看看整个系统的情况。 然后投入时间和精力来实施一个将来会很好的解决方案,并且不会在整个系统中传播大量不同的程序。

PPS:

我读了很多关于cronjobs / tasks的1/5分钟的最小交互。 您可以轻松地使用任意脚本来解决这个问题:

 // run every 5 minutes = 300 secs // desired interval: 30 secs $runs = 300/30; // be aware that the parent interval needs to be a multiple of the desired interval for($i=0;$i<$runs;$i++) { $start = time(); system('myscript.php'); sleep(300/10-time()+$start); // compensate the time that the script needed to run. be aware that you have to implement some logic to deal with cases where the script takes longer to run than your interavl - technique and problem described above } 

这看起来像一个工作服务器的工作;)看看Gearman 。 这种方法的额外好处是,这是由远程方触发的,当时只有这样才能做,而不是轮询。 特别是在小于(可以说)的时间间隔中,5分钟轮询不再是非常有效的,取决于任务执行的任务。

快速和肮脏的方法是创建一个循环,不断检查是否有新的工作。

伪代码

 set_ini("max_execution_time", "3600000000"); $keeplooping = true; while($keeplooping){ if(check_for_work()){ process_work(); } else{ sleep(5); } // some way to change $keeplooping to false // you don't want to just kill the process, because it might still be doing something } 

你有没有尝试Windows调度(默认情况下,Windows自带)? 在这个你将需要提供的PHP路径和您的PHP文件路径。 它运作良好

你不能只写一个java / c + +程序,将通过设定的时间间隔为您查询? 你可以将它包含在启动程序列表中,以便它始终运行。 一旦找到任务,它可以在单独的线程上处理它,并处理更多的请求并标记其他人完成。

最简单的方法是使用嵌入式Windows计划。

用php-cli.exe运行你的脚本,用你的脚本需要的扩展名填充php.ini。

但是我应该说,在实践中,你不需要那么短的时间间隔来运行你的预定工作。 只是做一些测试,以获得最佳的时间间隔值为您的一个。 建议不要将时间间隔设置为小于1分钟。

另一个小小的建议:在脚本开始时(php flock函数)制作一些锁定文件,检查是否有可用性写入这个锁定文件,以防止两个或多个副本同时工作,并在脚本的末尾解除链接解锁。

如果您必须将输出结果写入数据库,请尝试使用MySQL TRIGGERS而不是PHP。 或者在MySQL中使用事件。