【问题标题】:Is it wise to use PHP for a daemon?将 PHP 用于守护进程是否明智?
【发布时间】:2010-10-13 09:55:41
【问题描述】:

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

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

  • 连续检查一行是否已经 添加到 MySQL 数据库表中
  • 对之前的内容运行 FFmpeg 命令 从数据库中检索
  • 将输出插入 MySQL 表

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

它甚至会产生这么大的性能差异吗?

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

谢谢大家

【问题讨论】:

  • 在 PHP 和 C 之间有很多语言!如果 PHP 不起作用(而且它是一种用于此类任务的糟糕语言),您可能会发现 Python 或其他通常被认为比 C 更快的“可靠”语言。

标签: php c linux daemon


【解决方案1】:

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

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

所以,我建议:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 思路不错。但据我了解,守护进程将继续为添加到数据库中的任何新内容创建子进程。因此,FFmpeg 可以随心所欲,这没关系,对吧?
    • 您可以使用 launchd (next gen cron) 进行检查
    • 取决于活动级别。启动进程比在单个进程中运行计时器要重得多,而且如果过于频繁,您需要添加逻辑来处理多个作业。在任何情况下,cron 作业都需要复制轮询逻辑。
    【解决方案3】:

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

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

    【讨论】:

    • 大多数发行版都包含 PHP 以及 perl 和 python
    • 是的,但不像默认安装那么频繁。
    【解决方案4】:

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

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

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

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

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

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            您可能需要考虑创建一个执行 system 命令(即 FFmpeg)而不是守护程序的 mysql trigger。如果一些延迟不是问题,您还可以在 cron 中放置一些每隔几分钟执行一次的内容来检查。如果可以选择,Cron 将是我的选择。

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

            【讨论】:

            • 啊,我不知道mysql触发器。是的,cron 作业也是一个选项,现在 mysql 触发器也是如此。 :)
            • 一般的坏主意:触发器将是同步的,在事务期间添加锁;他们使交易需要更长的时间(显然);并且更难测试和调试。
            • 我同意触发器,我只是提到它作为守护程序的替代品。如果它只是产生一个新进程并退出,它实际上不会那么糟糕。我的偏好可能仍然是使用 cron。
            【解决方案9】:

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

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

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

            /约翰

            【讨论】:

              【解决方案10】:

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

              【讨论】:

                【解决方案11】:

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

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

                【讨论】:

                  【解决方案12】:

                  如果您决定采用守护进程,有一个很棒的 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

                  【讨论】:

                  • 五。有帮助。感谢您提供链接以及有关启动和停止脚本的信息。
                  【解决方案13】:

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

                  根据我的经验,对于一些较大的任务,PHP 可能会出现内存泄漏问题。

                  【讨论】:

                  • 只要您充分规划您的范围,PHP 的垃圾收集功能就非常出色。
                  • 好吧,除了自引用数组结构,它会泄漏内存并将消息发送到控制台。哎呀。
                  【解决方案14】:

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

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

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

                  【讨论】:

                    【解决方案15】:

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

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

                    node.js 通常更适合,尽管有一些小烦恼。已经在相同领域进行了一些改进 PHP 的尝试,但效果并不理想。

                    【讨论】:

                      【解决方案16】:

                      定时任务?是的。

                      永远运行的守护进程?没有。

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

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

                      【讨论】:

                        【解决方案17】:

                        去吧。我也必须这样做一次。 就像其他人说的那样,这并不理想,但它会完成。使用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++;
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-11-07
                          • 2022-06-11
                          • 1970-01-01
                          • 2012-01-13
                          • 2010-10-19
                          • 1970-01-01
                          相关资源
                          最近更新 更多