使用PHP作为守护进程是否明智?

21
我希望创建一个后台进程,据说通常用C或类似的语言编写。最近发现PHP也可用于创建守护进程,希望能得到一些建议是否应该利用PHP这种方式。
以下是我对守护进程的要求:
  • 持续检查MySQL数据库表中是否已添加行
  • 对从数据库检索到的内容运行FFmpeg命令
  • 将输出插入到MySQL表中
我不确定还能为此决策提供什么帮助。只想补充一下,我之前没有用过C,只用过Java和PHP以及基本的Bash脚本。
使用PHP会有多大的性能差异呢?请原谅我的无知,我正在学习中! :)
感谢各位。

PHP和C之间有很多语言可供选择!如果PHP无法胜任(对于这样的任务来说,它是一种糟糕的语言),您可能会发现Python或其他被普遍认为“可靠”的语言比C更快。 - Nicholas Wilson
17个回答

28

正如其他人所指出的,PHP的不同版本存在垃圾收集器问题。如果您知道您的版本没有这样的问题,那么您就可以消除这个问题。关键是,在编写守护程序并通过valgrind运行它以查看安装的PHP是否在任何给定的机器上泄漏之前,您不能(确定地)知道。因此,在这方面,您可能编写它只是为了发现Zend认为已经修复的问题仍然存在漏洞,或者您正在处理略旧的PHP版本或某些扩展。让人不爽。

另一个问题是有点毛病的信号。根据我的经验,使用PHP时信号处理程序并不总是正确进入,特别是当信号排队而非合并时。这对您可能不是个问题,例如,如果您只需要处理SIGINT / SIGUSR1 / SIGUSR2 / SIGHUP。

因此,我建议:

如果守护程序很简单,请继续使用PHP。如果它看起来会变得相当复杂,或者分配大量内存,您可能需要在用PHP原型设计后再用C编写它。

我是一个非常热衷于C的人。但是,我认为使用PHP快速解决某些问题也没有问题(除了我解释的情况之外)。我也认为,使用PHP原型设计可能会在以后重写成C时更好。例如,如果您使用PHP处理数据库事务,将比使用其他C接口管理回调函数要简单得多。因此,在这种情况下,对于“一次性”的任务,您肯定可以更快地完成它。


16

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

你的FFmpeg命令可能需要一段时间才能完成,对吧?如果是这样,那么频繁地轮询数据库是否真的有必要呢?每分钟运行一次cronjob(或者每五分钟、十分钟或二十分钟等)是否更简单地实现了相同的功能呢?


不错的思路。但据我所知,守护进程将继续为添加到数据库中的任何新内容创建子进程。因此,FFmpeg 可以花费尽可能长的时间,这并不重要,对吧? - Abs
你可以考虑使用launchd(下一代cron)。 - Jeremy L
2
根据活动水平而定。启动进程比在单个进程中运行计时器要重。此外,如果太频繁,您需要添加处理多个作业的逻辑。无论如何,cron作业都需要复制轮询逻辑。 - dkretz

8

对于这种类型的工作,Php并不比其他常见的脚本语言更好或更差。它可以很好地访问所有系统调用和库实用程序,以完成此类工作。如果您最熟悉使用PHP进行脚本编写,则php可以胜任该工作。

唯一的缺点是,与Perl或Python等语言相比,Php并不像它们那样普及,只能在用于提供动态Web内容的系统上找到。并不是说安装Php解释器太大或太昂贵,但如果您最关心的是使程序运行在多个系统上,那可能会有一些障碍。


大多数发行版都包含PHP,就像Perl和Python一样。 - Jeremy L
2
是的,但通常不会默认安装。 - SingleNegationElimination

7
我建议您尝试使用php守护进程来完成任务,因为这是您最熟悉的语言。您可以在任何情况下都加入一个定时器,以便在数据库上复制查询频率。只要不是简单地循环查询,就不会有任何惩罚。
如果您不经常执行某些操作,也可以从cron中运行php代码,让您的代码排空队列然后退出。
但是,作为第一次尝试,不要害怕坚持自己最熟悉的方法。
尽量不要使用触发器,因为它们会引入不必要的耦合,并且测试和调试起来也不方便。

4

在正确地将PHP脚本转化为守护进程的过程中,一个问题是PHP没有dup()或dup2()系统调用的接口,而这些调用是分离文件描述符所必需的。


3
如果不需要即时操作,可以使用 cron-job。
我即将上线的系统基于队列守护进程 'beanstalkd',通过 PHP 网页调用向守护进程发送各种小消息,然后 PHP 脚本从队列中获取这些消息并执行各种任务,例如调整图像大小或检查数据库(通常通过基于 Memcache 的存储返回信息)。
为了避免长时间运行的进程,我将其封装在一个 BASH 脚本中,根据脚本返回的值("exit(1);"),每执行50个任务就重新启动脚本。如果是因为计划重启,它将立即重启;任何其他退出值(默认为0,因此我不使用它)都会在几秒钟后重新启动。

2

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


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


非常有帮助。感谢提供链接以及关于启动和停止脚本的提示。 - Joe

1

你可能想考虑创建一个mysql 触发器,执行一个系统命令(如FFmpeg),而不是一个守护进程。如果一些延迟不是问题,你也可以在cron中放置一些东西,每隔几分钟执行一次检查。如果可以选择的话,我会选择Cron。

回答你的问题,php作为守护进程运行是完全可以的。它不必用C来完成。


啊,我不知道mysql触发器。是的,cron job也是一个选项,现在mysql触发器也是。 :) - Abs
总的来说,这是一个不好的想法:触发器会是同步的,在事务期间添加锁定;它们会使事务变得更加耗时(显然);并且更难以测试和调试。 - dkretz
我同意关于触发器的想法,我只是提到它作为守护进程的替代方案。如果它只是生成一个新进程并退出,那其实也不会太糟糕。但我更倾向于使用cron。 - gpojd

1

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

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

然而,问题仍然存在。php是否能够作为正常守护进程运行很长时间(几年)?或者各种内存泄漏会耗尽所有的内存并杀死系统?

/ Johan


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接