2011-03-20 47 views
7

我有一张地图。在这张地图上,我想显示从几个表中收集的实时数据,其中一些表的行数惊人。不用说,获取这些信息需要花费很长的时间。此外,涉及ping。根据离线或远离的服务器,这些数据的收集时间可能会在1到10分钟之间变化。为什么连续运行PHP脚本这么糟糕?

我希望地图能够快速响应,因此我决定向我的数据库添加一个只包含地图所需数据的新表。这意味着我需要一个后台进程来不断更新我的新表中的信息。 Cron工作当然是一种可能性,但我希望在前一个时间间隔完成后立即刷新数据。如果离线IP地址的数量突然增加,并且循环运行时间比Cron作业的时间间隔更长,会怎样?

我自己的解决方案是在PHP中通过命令行创建一个无限循环。此循环会刷新映射到MySQL的数据,并记录其他有用的数据,例如循环时间和Ping失败尝试等,然后在短暂停顿(几秒钟)后重新启动。

但是 - 人们反复告诉我,一个永远运行的PHP脚本是坏的。经过一段时间后,它会消耗千兆字节的RAM(以及其他可怕的东西)

部分我正在写这个问题来确认事实是否如此,但是关于如何去写一个干净的东西的一些技巧和窍门循环不会泄漏内存(如果可能的话)不会出错。关于这个问题的意见也将不胜感激。

我认为这个问题的答案对我将标记为正确的问题最为重视。

+0

一个令人难以置信的小问题,但请不要添加签名/签收问题。 (除此之外,这是一个构建得非常好的问题。):-) – 2011-03-20 22:58:05

+0

对不起,谢谢:-) – Hubro 2011-03-20 23:03:54

回答

4

循环应该在一个脚本中,它将激活/调用实际的脚本作为一个不同的过程...很像cron正在做的事情。
这样,即使内存泄漏,并且未收集的内存正在累积,它在每个周期之后都应该是空闲的。

+0

我喜欢一个例子。你的意思是这样吗? http://pastebin.com/SJeq9Xge – Hubro 2011-03-20 23:10:45

2

但是 - 人们反复告诉我,一个永远运行的PHP脚本是坏的。经过一段时间后,它会消耗千兆字节的RAM(以及其他可怕的东西)

这曾经是非常真实的。以前的PHP版本有可怕的garbage collection,所以长时间运行的脚本很容易意外地消耗比实际使用的更多的内存。 PHP 5.3 introduced a new garbage collector可以理解和清理循环引用,这是“内存泄漏”的头号原因。它默认启用。查看更多信息和漂亮图形的链接。

只要你的代码采取措施允许变量在适当的时候超出范围,否则取消设置不再使用的变量,你的脚本不应该因为它是PHP而消耗不必要的内存量。

1

我不认为它很糟糕,就像你想要连续运行的任何事情一样,你必须更加小心。

有些图书馆可以帮助你完成任务。看看System_Daemon,它在一个月前发布了RC 1,它允许您“设置最大RAM使用率等选项”。

1

而不是运行一个无限循环我会试着去与您提到的cron选项结合使用数据库表项或平面文件来存储“当前有效”状态位以确保你没有重叠的进程试图同时运行。

虽然我知道这将意味着一个小延迟执行下一次迭代之前,这可能是一个更好的主意反正为:

  1. 这将让RDBMS执行任何未决低优先级更新等等,因为您一直在进行的活动量很可能已被搁置。尽管最近的改进(5.2引入了一个新的内存管理系统和垃圾收集在5.3中进行了彻底检查),但即使您整齐地取消了所有使用的临时变量,PHP仍会“泄漏”内存,尽管如此,应该有希望的意思是这个问题较少。

一般情况下,它也将是比较容易处理的其他问题(如数据库连接暂时下降由于配置改变和重新启动的例子),如果你在一个理想的使用cron的办法,虽然无论如何,你会在代码中迎合这样的可能性。 (也就是说,我上次检查时,这远远不是一个理想的世界。)

+0

1.使用无限循环时,情况也不例外,只要每个间隔之间有一个暂停?就我而言,这个脚本无论如何都会在专用服务器上运行。 2.可以通过运行一个PHP文件来解决这个问题:当循环执行另一个PHP文件时,然后休息一下? – Hubro 2011-03-20 23:21:08

+0

@Codemonkey 1.是的。 2.理论上是。不过,我仍然觉得它不会那么可靠。也就是说,在事实之后转换你提到的使用cron的方法是很简单的,所以这很可能是一条可行的路。 (即:尝试PHP脚本以不同的“模式”方式产生其自身副本,并且如果这看起来随着时间推移而降级,则只需通过cron调用相同的脚本)。只要定期记录'memory_get_usage'的结果, memory_get_peak_usage'等,那么应该很容易监控事情进展情况。 – 2011-03-21 07:56:22

0

首先我没有看到你需要一个守护进程脚本来提供你描述的功能。

Cron作业当然是可能的,但我想数据的刷新尽快先前区间已完成

的既不是cron作业,也不是一个守护进程是解决方式发生该问题(除非守护进程成为脚本的数据接收器)。当数据可用时使用锁定策略来实现并发性,我会产生一个分离的进程。

长时间运行的PHP脚本本质上并不坏 - 但引用计数垃圾回收器并不处理清理内存的所有可能场景 - 但更近期的实现有更高级的收集器,它应该清理更多(循环引用检查)。