使用 PHP 作为守护进程是否明智?
我希望创建一个后台进程,有人告诉我这些进程通常是用 C 或类似的东西编写的。 我最近发现 PHP 可以用来创建守护进程,如果我应该以这种方式使用 PHP,我希望得到一些建议。
这是我对守护进程的要求。
- 不断检查一行是否已被 添加到 MySQL 数据库表
- 在原来的内容上运行 FFmpeg 命令 从数据库检索
- 将输出插入 MySQL 表
我不确定我还能提供什么来帮助做出这个决定。 补充一下,我以前没有做过C。 仅 Java 和 PHP 以及基本的 bash 脚本。
它对性能有那么大的影响吗?
请原谅我的无知,我正在学习! :)
谢谢大家
I wish to create a background process and I have been told these are usually written in C or something of that sort. I have recently found out PHP can be used to create a daemon and I was hoping to get some advice if I should make use of PHP in this way.
Here are my requirements for a daemon.
- Continuously check if a row has been
added to MySQL database table - Run FFmpeg commands on what was
retrieved from database - Insert output into MySQL table
I am not sure what else I can offer to help make this decision. Just to add, I have not done C before. Only Java and PHP and basic bash scripting.
Does it even make that much of a performance difference?
Please allow for my ignorance, I am learning! :)
Thanks all
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
正如其他人所指出的,各种版本的 PHP 都存在垃圾收集器问题。 当然,如果您知道您的版本没有此类问题,则可以消除该问题。 关键是,在您编写守护程序并通过 valgrind 运行它以查看已安装的 PHP 在任何给定机器上是否泄漏之前,您不知道(肯定)。 因此,另一方面,您编写它可能只是为了发现 Zend 认为已修复的内容可能仍然存在错误,或者您正在处理稍旧版本的 PHP 或某些扩展。 恶心。
另一个问题是信号有些错误。 根据我的经验,使用 PHP 并不总是能正确输入信号处理程序,尤其是当信号排队而不是合并时。 这对您来说可能不是问题,即如果您只需要处理 SIGINT/SIGUSR1/SIGUSR2/SIGHUP。
所以,我建议:
如果守护进程很简单,请继续使用 PHP。 如果它看起来会变得相当复杂,或者分配大量内存,您可能会考虑在用 PHP 对其进行原型设计后用 C 语言编写它。
我是一个相当顽固的C型人。 然而,我认为使用 PHP 快速敲定一些东西并没有什么问题(除了我解释的情况之外)。 我也认为使用 PHP 来构建一些稍后可能会或可能不会用 C 重写的原型并没有什么问题。例如,如果使用 PHP,处理数据库内容将会比使用 C 中的其他接口管理回调要简单得多。例如,对于“一次性”,您肯定会更快地完成它。
As others have noted, various versions of PHP have issues with their garbage collectors. Of course, if you know that your version does not have such issues, you eliminate that problem. The point is, you don't know (for sure) until you write the daemon and run it through valgrind to see if the installed PHP leaks or not on any given machine. So on that hand, you may write it just to discover that what Zend thinks is fixed might still be buggy, or you are dealing with a slightly older version of PHP or some extension. Icky.
The other problem is somewhat buggy signals. In my experience, signal handlers are not always entered correctly with PHP, especially when the signal is queued instead of merged. That may not be an issue for you, i.e. if you just need to handle SIGINT/SIGUSR1/SIGUSR2/SIGHUP.
So, I suggest:
If the daemon is simple, go ahead and use PHP. If it looks like its going to get rather complex, or allocate lots of memory, you might consider writing it in C after prototyping it in PHP.
I am a pretty die hard C person. However, I see nothing wrong with hammering out something quick using PHP (beyond the cases that I explained). I also see nothing wrong with using PHP to prototype something that may or may not be later rewritten in C. For instance, handling database stuff is going to be much simpler if you use PHP, versus managing callbacks using other interfaces in C. So in that instance, for a 'one off', you will surely get it done much faster.
我倾向于使用 cron 作业来执行此任务,而不是在守护程序中轮询数据库。
您的 FFmpeg 命令可能需要一段时间才能完成它的任务,对吧? 在这种情况下,真的有必要不断轮询数据库吗? 每分钟(或每五分钟、十分钟或二十分钟)运行一次的 cronjob 不是实现相同目标的更简单方法吗?
I would be inclined to perform this task with a cron job, rather than polling the database in a daemon.
It's likely that your FFmpeg command will take a while to do it's thing, right? In that case, is it really necessary to be constantly polling the database? Wouldn't a cronjob running each minute (or every five, ten or twenty minutes for that matter) be a simpler way to achieve the same thing?
对于这种事情,Php 并不比任何其他常见脚本语言更好或更差。 它可以相当完整地访问完成此类工作所需的所有系统调用和库实用程序。 如果您最习惯使用 PHP 编写脚本,那么 php 会为您完成这项工作。
唯一的缺点是 php 不像 Perl 或 python 那样普遍,几乎所有版本的 UNIX 上都安装了后者。 Php 只能在提供动态 Web 内容的系统上找到。 并不是说 Php 解释器太大或安装成本太高,但如果您最关心的是让您的程序运行到许多系统上,那么这可能是一个小小的障碍。
Php isn't any better or worse for this kind of thing than any of the other common scripting languages. It has fairly complete access to all of the system calls and library utilities you would need to do this sort of work. If you are most comfortable using PHP for scripting, then php will do the job for you.
The only down side is that php is not quite as ubiquitous as, say, perl or python, which is installed on almost every flavor of unix. Php is only found on systems that are going to be serving dynamic web content. Not that a Php interpreter is too large or costly to install also, but if your biggest concern is getting your program to many systems, that may be a slight hurdle.
我会反对并建议您尝试 php 守护程序。 这显然是您最了解的语言。 无论如何,您可能会合并一个计时器,以便您可以复制数据库上的查询频率。 只要您不是天真地循环查询,实际上就没有任何惩罚。
如果它不经常执行,您也可以从 cron 运行 php,让您或代码排空队列,然后死亡。
但不要害怕坚持使用你最了解的作为第一个近似值。
尽量不要使用触发器。 它们会强加不必要的耦合,并且测试和调试没有乐趣。
I'll be contrary and recommend you try the php daemon. It's apparently the language you know the best. You'll presumably incorporate a timer in any case, so you can duplicate the querying frequency on the database. There's really no penalty as long as you aren't naively looping on a query.
If it's something not executed frequently, you could alternatively run the php from cron, letting youor code drain the queue and then die.
But don't be afraid to stick with what you know best, as a first approximation.
Try not to use triggers. They'll impose unnecessary coupling, and they're no fun to test and debug.
正确守护 PHP 脚本的一个问题是 PHP 没有 dup() 或 dup2() 系统调用的接口,而分离文件描述符需要这些接口。
One problem with properly daemonizing a PHP script is that PHP doesn't have interfaces to the dup() or dup2() syscalls, which are needed for detaching the file descriptors.
如果不需要近乎即时的操作,计划任务可能会工作得很好。
我即将启用我构建的基于排队守护进程“beanstalkd”的系统。 我从(在本例中为 PHP)网页调用向守护进程发送各种小消息,然后 PHP 脚本从队列中拾取它们并执行各种任务,例如调整图像大小或检查数据库(通常通过 Memcache 传回信息)的商店)。
为了避免长时间运行的进程,我将其包装在 BASH 脚本中,根据脚本返回的值(“exit(1);”)将重新启动脚本,每执行 50 个任务(例如) 。 如果它因为我的计划而重新启动,它会立即重新启动,任何其他退出值(默认为 0,所以我不使用它)都会在重新启动之前暂停几秒钟。
A cron-job would probably work just fine, if near-instant actions is not required.
I'm just about to put live, a system I've built, based on the queueing daemon 'beanstalkd'. I send various small messages from (in this case, PHP) webpage calls to the daemon, and a PHP script then picks them up from the queue and performs various tasks, such as resizing images or checking databases (often passing info back via a Memcache-based store).
To avoid long-running processes, I've wrapped it in a BASH script, that, depending on the value returned from the script ("exit(1);") will restart the script, for every (say) 50 tasks it's performed. If it's restarting because I plan it to, it will do so instantly, any other exit value (the default is 0, so I don't use that) would pause a few seconds before it was restarted.
作为具有合理确定的周期的 cron 作业运行,PHP 脚本可以完成这项工作,并且肯定可以实现生产稳定性。 您可能希望限制并发 FFMpeg 实例的数量,并确保具有完整的应用程序日志记录和异常处理。 我已经用 Java 实现了连续运行的轮询进程,以及每十分钟一次的 cron'd PHP 脚本,两者都很好地完成了工作。
Running as a cron job with sensibly determined periodicity, a PHP script can do the job, and production stability is certainly achievable. You might want to limit the number of simultaneous FFMpeg instances, and be sure to have complete application logging and exception handling. I have implemented continuously running polling processes in Java, as well as the every-ten-minute cron'd PHP script, and both do the job nicely.
您可能需要考虑制作一个 mysql 触发器 来执行系统命令(即FFmpeg)而不是一个守护进程。 如果延迟不是问题,您还可以在 cron 中放入每隔几分钟执行一次的内容来进行检查。 如果可以的话,Cron 将是我的选择。
为了回答你的问题,php 完全可以作为守护进程运行。 它不必在 C 中完成。
You might want to consider making a mysql trigger that executes a system command (i.e. FFmpeg) instead of a daemon. If some lag isn't a problem, you could also put something in cron that executes every few minutes to check. Cron would be my choice, if it is an option.
To answer your question, php is perfectly fine to run as a daemon. It does not have to be done in C.
如果你结合 Kent Fredric、tokenmacguy 和 Domster 的答案,你会得到一些有用的东西。
php 可能不适合长时间执行,
因此,让我们保持每个执行周期较短,并确保操作系统负责清理所有内存泄漏。
作为启动 php 脚本的工具,cron 是一个很好的工具。
如果你这样做的话,语言之间就没有太大区别。
然而,问题仍然存在。
php 是否能够作为普通守护进程运行很长时间(几年)?
或者各种内存泄漏会耗尽你所有的内存并杀死系统吗?
/约翰
If you combine the answers from Kent Fredric, tokenmacguy and Domster you get something useful.
php is probably not good for long execution times,
so let's keep every execution cycle short and make sure the OS takes care of the cleanup of any memoryleaks.
As a tool to start your php script cron can be a good tool.
And if you do it like that, there is not much difference between languages.
However, the question still stands.
Is php even capable to run as a normal daemon for long times (some years)?
Or will assorted memoryleaks eat up all your ram and kill the system?
/Johan
如果这样做,请注意内存泄漏。 根据 this,PHP 5.2 的垃圾收集器存在一些问题(已修复5.3)。 也许使用 cron 更好,这样脚本每次运行都会干净地开始。
If you do so, pay attention to memory leaks. PHP 5.2 has some problems with its garbage collector, according to this (fixed in 5.3). Perhaps its better to use cron, so the script starts clean every run.
对于你所描述的,我会选择一个守护进程。 确保在轮询循环中保持睡眠,这样在没有新任务时就不会轰炸数据库。 cronjob 更适合工作流/报告类型的作业,其中没有触发下一次运行的特定事件。
如前所述,PHP 在内存管理方面存在一些问题。 您需要确保测试代码是否存在内存泄漏,因为这些泄漏会随着时间的推移在长时间运行的脚本中累积。 PHP 没有真正的垃圾收集——它依赖于引用计数,这意味着循环引用会导致泄漏。 如果您意识到这一点,您可以围绕它编写代码。
For what you've described, I would go with a daemon. Make sure that you stick a sleep in the poll loop, so that you don't bombard the database when there are no new tasks. A cronjob works better for workflow/report type of jobs, where there isn't some particular event that triggers the next run.
As mentioned, PHP has some problems with memory management. You need to be sure that you test your code for memory leaks, since these would build up over time, in a long running script. PHP doesn't have real garbage collection - It relies on reference counting, which means that cyclic references will cause leaks. If you're aware of this, you can code around it.
如果您决定采用守护进程路线,有一个很棒的 PEAR 模块,名为
System_Daemon
,我最近在 PHP v5.3.0 安装中成功使用了它。 它记录在作者博客上: http://kevin.vanzonneveld.net/techblog/article /create_daemons_in_php如果您安装了 PEAR,您可以使用以下命令安装此模块:
您还需要创建一个初始化脚本:
/etc/init.d/
然后您可以:
/etc/init.d/projNotifMailDaemon start
/etc/init.d/projNotifMailDaemon stop
日志保存在:
/var/日志/.log
If you do decided to go down the daemon route, there is a great PEAR module called
System_Daemon
which I've recently used successfully on a PHP v5.3.0 installation. It is documented on the authors blog: http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_phpIf you have PEAR installed, you can install this module using:
You will also need to create a initialisation script:
/etc/init.d/<your_daemon_name>
Then you can:
/etc/init.d/projNotifMailDaemon start
/etc/init.d/projNotifMailDaemon stop
Logs are kept at:
/var/log/<your_daemon_name>.log
我不会推荐它。 PHP 并不是为长期执行而设计的。 它主要设计为寿命较短的页面。
根据我的经验,对于某些较大的任务,PHP 可能会出现内存泄漏问题。
I wouldn't recommend it. PHP is not designed for longterm execution. Its designed primarily with short lived pages.
In my experience PHP can have problems with leaking memory for some of the larger tasks.
听起来,一个 cron 作业和一点 bash 脚本应该就是您所需要的一切。 你可以做这样的事情:
所以 bash 比使用 PHP 更容易编写、移植和维护。
A cron job and a little bit of bash scripting should be everything you need by the sounds of it. You can do things like:
so bash would be easier to write, port and maintain IMHO than to use PHP.
如果你知道自己在做什么的话。 您需要很好地了解您的操作系统。 PHP 通常不适合大多数守护进程,因为它不是线程化的,并且没有一个适合所有任务的基于事件的系统。 不过,如果它适合您的需求,那就没问题了。 现代 PHP (5.3+) 非常稳定并且没有任何内存泄漏。 只要您启用 GC 并且不实现自己的内存泄漏等,就可以了。
以下是我正在运行的一个守护进程的统计信息:
正常运行时间 17 天(最后一次重启是由于 PHP 升级)。
写入字节数:200GB
连接数:数百
处理的连接数,数十万
处理的项目/请求:数以百万计
Node.js 通常更适合,尽管有一些小烦恼。 已经在相同领域进行了一些改进 PHP 的尝试,但效果并不是那么好。
If you know what you are doing sure. You need to understand your operating system well. PHP generally isn't suited for most daemons because it isn't threaded and doesn't have a decent event based system for all tasks. However if it suits your needs then no problem. Modern PHP (5.3+) is really stable and doesn't have any memory leaks. As long as you enable the GC and don't implement your own memory leaks, etc you'll be fine.
Here are the stats for one daemon I am running:
uptime 17 days (last restart due to PHP upgrade).
bytes written: 200GB
connections: hundreds
connections handled, hundreds of thousands
items/requests processed: millions
node.js is generally better suited although has some minor annoyances. Some attempts to improve PHP in the same areas have been made but they aren't really that great.
计划任务? 是的。
永远运行的守护进程? 不。PHP
没有垃圾收集器(或者至少,我上次检查时没有)。 因此,如果您创建循环引用,它永远不会被清理 - 至少在主脚本执行完成之前不会。 在守护进程中,这几乎是不可能的。
如果他们在新版本中添加了 GC,那么可以。
Cron job? Yes.
Daemon which runs forever? No.
PHP does not have a garbage collector (or at least, last time I checked it did not). Therefore, if you create a circular reference, it NEVER gets cleaned up - at least not until the main script execution finishes. In daemon process this is approximately never.
If they've added a GC in new versions, then yes you can.
大胆试试吧。 我也必须这样做一次。
正如其他人所说,这并不理想,但会完成的。 使用 Windows,对吗? 好的。
如果您只需要偶尔运行(每小时一次等)。
创建一个新的 Firefox 快捷方式,将其放置在相关的位置。
打开快捷方式的属性,将“目标”更改为:
转到“控制面板”>“计划任务”
将新的计划任务指向快捷方式。
如果您需要它持续运行或伪持续运行,您需要为脚本添加一些趣味。
:
如果脚本使用循环(如 while),则必须清除缓冲区
Go for it. I had to do it once also.
Like others said, it's not ideal but it'll get-er-done. Using Windows, right? Good.
If you only need it to run occasionally (Once per hour, etc).
Make a new shortcut to your firefox, place it somewhere relevant.
Open up the properties for the shortcut, change "Target" to:
Go to Control Panel>Scheduled Tasks
Point your new scheduled task at the shortcut.
If you need it to run constantly or pseudo-constantly, you'll need to spice the script up a bit.
Start your script with
If the script uses a loop (like while) you have to clear the buffer: