0

我有一个作为后台进程运行的 PHP 脚本。此脚本仅使用 fopen 从 Twitter Streaming API 读取。本质上是一个永不结束的 http 连接。不幸的是,我无法发布该脚本,因为它是专有的。Ubuntu 上的脚本运行正常,占用的 CPU 很少。但是在 BSD 上,脚本总是使用几乎 100% 的 CPU。该脚本在两台机器上都运行良好,并且是完全相同的脚本。谁能想到一些可能会指出我解决这个问题的正确方向的东西?这是我编写的第一个始终在后台运行的 PHP 脚本。

该脚本是一个无限循环,它每分钟读取一次数据并写入一个 json 文件。每当重新连接发生时,该脚本将写入 MySQL 数据库,这通常是在运行几天之后。该脚本不做其他任何事情,而且不是很长。我对 BSD 或编写运行无限循环的 PHP 脚本几乎没有经验。提前感谢您的任何建议,如果这属于另一个 StackExchange,请告诉我。我会尽快回答任何问题,因为我意识到这个问题非常模糊。

4

3 回答 3

1

在我看来,您的一个功能在 Linux 上会短暂阻塞,而不是 BSD。没有看到你的脚本很难得到具体的,但我建议的一件事是usleep()在下一次循环迭代之前添加一个:

usleep(100000); //Sleep for 100ms

你不需要长时间的睡眠......就足以让你不使用 100% 的 CPU。

编辑:既然您提到您现在没有在后台运行它的好方法,我建议您查看本教程以“守护”您的脚本。包括一些用于执行此操作的方便代码。它甚至可以init.d为您制作一个文件。

于 2011-10-13T20:27:45.413 回答
1

在没有看到脚本的情况下,很难给您一个明确的答案,但是您需要做的是确保您的脚本正在适当地等待数据。你绝对应该做的是调用stream_set_timeout($fp, 0);stream_set_blocking($fp, 0);在你的文件指针上。

做这样的事情应该避免赛车的脚本的基本结构是这样的:

// Open the file pointer and set blocking mode
$fp = fopen('http://www.domain.tld/somepage.file','r');
stream_set_timeout($fp, 1);
stream_set_blocking($fp, 1);

while (!feof($fp)) { // This should loop until the server closes the connection

  // This line should be pretty much the first line in the loop
  // It will try and fetch a line from $fp, and block for 1 second
  // or until one is available. This should help avoid racing
  // You can also use fread() in the same way if necessary
  if (($str = fgets($fp)) === FALSE) continue;

  // rest of app logic goes here

}

您也可以使用sleep()/usleep()来避免赛车,但更好的方法是依靠阻塞函数调用来进行阻塞。如果它适用于一个操作系统但不能在另一个操作系统上运行,请尝试明确设置阻塞模式/行为,如上所述。

如果您无法通过调用fopen()传递 HTTP URL 来实现此功能,则可能是 PHP 中的 HTTP 包装器实现存在问题。要解决此问题,您可以fsockopen()自己使用和处理请求。这并不太难,特别是如果您只需要发送一个请求并读取一个恒定的流响应。

于 2011-10-13T20:28:31.757 回答
0

代码看起来如何与实际阅读一样?您是否只是锤击插座直到得到一些东西?

解决这个问题的一种真正有效的方法是使用libevent 扩展,但这不适合头脑薄弱的人。

于 2011-10-13T20:28:47.627 回答