22

我希望创建一个后台进程,有人告诉我这些通常是用 C 或类似的东西编写的。我最近发现 PHP 可以用来创建一个守护进程,如果我应该以这种方式使用 PHP,我希望能得到一些建议。

这是我对守护进程的要求。

  • 不断检查是否有行已添加到 MySQL 数据库表中
  • 对从数据库检索到的内容运行 FFmpeg 命令
  • 将输出插入 MySQL 表

我不确定我还能提供什么来帮助做出这个决定。只是补充一下,我以前没有做过C。只有 Java 和 PHP 以及基本的 bash 脚本。

它甚至会产生如此大的性能差异吗?

请原谅我的无知,我正在学习!:)

谢谢大家

4

17 回答 17

29

正如其他人所指出的,各种版本的 PHP 都存在垃圾收集器的问题。当然,如果您知道您的版本没有此类问题,您就可以消除该问题。关键是,在您编写守护程序并通过 valgrind 运行它以查看安装的 PHP 是否在任何给定机器上泄漏之前,您不知道(肯定)。因此,在这方面,您可能编写它只是为了发现 Zend 认为已修复的内容可能仍然存在错误,或者您正在处理稍微旧版本的 PHP 或某些扩展。恶心。

另一个问题是有些错误的信号。以我的经验,信号处理程序并不总是用 PHP 正确输入,尤其是当信号排队而不是合并时。这对您来说可能不是问题,即如果您只需要处理 SIGINT/SIGUSR1/SIGUSR2/SIGHUP。

所以,我建议:

如果守护程序很简单,请继续使用 PHP。如果它看起来会变得相当复杂,或者分配大量内存,您可以考虑在 PHP 中对其进行原型设计后用 C 语言编写它。

我是一个相当顽固的C人。但是,我认为使用 PHP 快速完成一些事情并没有错(除了我解释的情况)。我也认为使用 PHP 对以后可能会或可能不会用 C 重写的东西进行原型设计没有任何问题。例如,如果您使用 PHP,处理数据库内容会比使用 C 中的其他接口管理回调要简单得多。所以在在那种情况下,对于“一次性”,您肯定会更快地完成它。

于 2009-03-15T13:20:47.223 回答
16

我倾向于使用 cron 作业执行此任务,而不是在守护进程中轮询数据库。

您的 FFmpeg 命令可能需要一段时间才能完成,对吧?在那种情况下,真的有必要不断地轮询数据库吗?每分钟(或每五、十或二十分钟)运行的 cronjob 不是实现相同目标的更简单方法吗?

于 2009-03-14T23:35:18.877 回答
7

对于这种事情,Php 并没有比任何其他常见的脚本语言更好或更差。它可以完全访问完成此类工作所需的所有系统调用和库实用程序。如果您最喜欢使用 PHP 编写脚本,那么 php 将为您完成这项工作。

唯一的缺点是 php 不像 perl 或 python 那样无处不在,它们几乎安装在每一种风格的 unix 上。Php 只能在将要提供动态 Web 内容的系统上找到。并不是说 Php 解释器太大或安装成本太高,但如果您最关心的是让您的程序适用于许多系统,那可能是一个小障碍。

于 2009-03-14T23:35:32.153 回答
6

我会相反,建议您尝试使用 php 守护程序。这显然是你最了解的语言。在任何情况下,您都可能会合并一个计时器,因此您可以复制数据库上的查询频率。只要您不天真地循环查询,就没有任何惩罚。

如果它不经常执行,您也可以从 cron 运行 php,让您或代码排空队列然后死掉。

但不要害怕坚持你最了解的东西,作为第一个近似值。

尽量不要使用触发器。它们会强加不必要的耦合,而且测试和调试也没有乐趣。

于 2009-03-15T00:45:33.530 回答
4

正确守护 PHP 脚本的一个问题是 PHP 没有到 dup() 或 dup2() 系统调用的接口,而这些接口是分离文件描述符所必需的。

于 2009-03-16T21:17:00.783 回答
3

如果不需要近乎即时的操作,cron-job 可能会工作得很好。

我即将上线,一个我建立的系统,基于排队守护进程'beanstalkd'。我从(在本例中为 PHP)网页调用向守护程序发送各种小消息,然后 PHP 脚本从队列中提取它们并执行各种任务,例如调整图像大小或检查数据库(通常通过 Memcache 传回信息基于商店)。

为了避免长时间运行的进程,我将它包装在一个 BASH 脚本中,根据脚本返回的值 ("exit(1);") 将重新启动脚本,对于它执行的每(比如说)50 个任务. 如果它因为我的计划而重新启动,它将立即执行,任何其他退出值(默认值为 0,所以我不使用它)将在重新启动前暂停几秒钟。

于 2009-03-15T13:00:04.777 回答
2

作为具有合理确定的周期性的 cron 作业运行,PHP 脚本可以完成这项工作,并且生产稳定性当然是可以实现的。您可能希望限制同时 FFMpeg 实例的数量,并确保具有完整的应用程序日志记录和异常处理。我已经在 J​​ava 中实现了连续运行的轮询进程,以及每 10 分钟一次的 cron'd PHP 脚本,两者都很好地完成了这项工作。

于 2009-03-15T12:15:58.953 回答
1

您可能需要考虑制作一个执行系统命令(即 FFmpeg)而不是守护进程的 mysql触发器。如果一些滞后不是问题,您还可以在 cron 中放置一些每隔几分钟执行一次的内容来检查。如果可以选择,Cron 将是我的选择。

要回答您的问题,php 作为守护程序运行是完全可以的。它不必在 C 中完成。

于 2009-03-14T23:36:44.117 回答
1

如果你结合 Kent Fredric、tokenmacguy 和 Domster 的答案,你会得到一些有用的东西。

php 可能不适合较长的执行时间,所以让我们缩短每个执行周期,并确保操作系统负责清理任何内存泄漏。作为启动 php 脚本的工具,cron 可以是一个很好的工具。如果你这样做,语言之间没有太大区别。

然而,问题仍然存在。php 甚至能够长时间(几年)作为普通守护进程运行吗?或者各种内存泄漏会吃掉你所有的内存并杀死系统?

/约翰

于 2009-03-15T00:19:27.397 回答
1

如果这样做,请注意内存泄漏。据此(在 5.3 中修复),PHP 5.2 的垃圾收集器存在一些问题。也许使用 cron 会更好,所以脚本每次运行都会开始清理。

于 2009-03-15T01:34:31.523 回答
1

对于你所描述的,我会选择一个守护进程。确保您在轮询循环中保持睡眠,这样您就不会在没有新任务时轰炸数据库。cronjob 更适合工作流/报告类型的作业,其中没有触发下一次运行的特定事件。

如前所述,PHP 在内存管理方面存在一些问题。您需要确保测试代码是否存在内存泄漏,因为这些会随着时间的推移在长时间运行的脚本中累积。PHP 没有真正的垃圾回收——它依赖于引用计数,这意味着循环引用会导致泄漏。如果您知道这一点,您可以围绕它编写代码。

于 2009-03-15T12:52:29.490 回答
1

如果你决定走守护进程路线,有一个很棒的 PEAR 模块System_Daemon,我最近在 PHP v5.3.0 安装中成功使用了它。它记录在作者博客上:http: //kevin.vanzonneveld.net/techblog/article/create_daemons_in_php

如果您安装了 PEAR,您可以使用以下命令安装此模块:

pear install -f System_Daemon

您还需要创建一个初始化脚本:/etc/init.d/<your_daemon_name>

那么你就可以:

  • 启动守护进程:/etc/init.d/projNotifMailDaemon start
  • 停止守护进程:/etc/init.d/projNotifMailDaemon stop

日志保存在:/var/log/<your_daemon_name>.log

于 2009-11-12T08:05:02.593 回答
0

我不会推荐它。PHP 不是为长期执行而设计的。它的设计主要是短暂的页面。

以我的经验,PHP 在一些较大的任务中可能会出现内存泄漏问题。

于 2009-03-14T23:34:41.560 回答
0

听起来,一个 cron 作业和一点点 bash 脚本应该是您所需要的一切。您可以执行以下操作:

$file=`mysqlquery -h server < "select file from table;"`
ffmpeg $file -fps 50 output.a etc.

所以 bash 比使用 PHP 更容易编写、移植和维护恕我直言。

于 2009-03-15T00:44:00.053 回答
0

如果你知道你在做什么肯定。您需要很好地了解您的操作系统。PHP 通常不适合大多数守护进程,因为它不是线程的,并且没有适合所有任务的基于事件的系统。但是,如果它适合您的需求,那么没问题。现代 PHP (5.3+) 非常稳定,没有任何内存泄漏。只要您启用 GC 并且不实现自己的内存泄漏等,就可以了。

以下是我正在运行的一个守护进程的统计信息:正常运行时间 17 天(由于 PHP 升级而最后重新启动)。写入的字节数:200GB 连接数:处理了数百个连接,处理了数十万个项目/请求:数百万

node.js 通常更适合,尽管有一些小烦恼。已经在相同领域进行了一些改进 PHP 的尝试,但它们并不是真的那么好。

于 2015-11-09T09:33:14.587 回答
-2

克朗工作?是的。

永远运行的守护进程?不。

PHP 没有垃圾收集器(或者至少,上次我检查它没有)。因此,如果您创建循环引用,它永远不会被清理 - 至少在主脚本执行完成之前不会。在守护进程中,这几乎是永远不会发生的。

如果他们在新版本中添加了 GC,那么可以。

于 2009-03-15T08:11:24.113 回答
-5

去吧。我也必须这样做一次。就像其他人说的那样,这并不理想,但它会完成。使用Windows,对吗?好的。

如果您只需要它偶尔运行(每小时一次等)。为您的 Firefox 创建一个新的快捷方式,将其放在相关的地方。打开快捷方式的属性,将“目标”更改为:

"C:\Program Files\Mozilla Firefox\firefox.exe" http://localhost/path/to/script.php

转到控制面板>计划任务将您的新计划任务指向快捷方式。

如果您需要它持续运行或伪持续运行,则需要为脚本添加一些趣味。

开始你的脚本

set_time_limit(0);
ob_implicit_flush(true);

如果脚本使用循环(如while),则必须清除缓冲区:

$i=0;
while($i<sizeof($my_array)){
     //do stuff
     flush();           
     ob_clean();
     sleep(17);
     $i++;
}
于 2009-03-16T21:02:45.950 回答