【问题标题】:asynchronous processing with PHP - one worker per job使用 PHP 进行异步处理 - 每个作业一个工人
【发布时间】:2011-03-31 14:21:19
【问题描述】:

考虑一个 PHP Web 应用程序,其目的是接受用户请求以启动通用异步作业,然后创建一个工作进程/线程来运行该作业。这些作业不是特别占用 CPU 或内存,但预计会经常阻塞 I/O 调用。每秒启动的作业不应超过一到两个,但由于运行时间较长,可能同时运行许多作业。

因此,并行运行作业至关重要。此外,每个作业都必须由负责杀死挂起的工作人员、根据用户请求中止工作人员等的管理器守护进程进行监控。

实施此类系统的最佳方法是什么?我可以看到:

  1. 从经理那里分派一个工人 - 这似乎是最低级别的选项,我必须自己实施一个监控系统。 Apache 是 Web 服务器,因此该选项似乎需要通过 FastCGI 启动任何 PHP 工作程序。
  2. 使用某种作业/消息队列。 (gearman、beantalkd、RabbitMQ 等) - 最初,这似乎是显而易见的选择。经过一些研究,我对所有选项都有些困惑。例如,Gearman 看起来像是为大型分布式系统设计的,其中有固定的工人池……所以我不知道它是否适合我的需要(每个工作一个工人)。

【问题讨论】:

    标签: php asynchronous message-queue task-queue gearman


    【解决方案1】:

    好吧,如果你在 Linux 上,你可以使用 pcntl_fork 来 fork children。 “主人”然后看着孩子们。每个孩子都完成了自己的任务,然后正常存在。

    就我个人而言,在我的实现中,我从来不需要消息队列。我只是在“master”中使用了一个带锁的数组。当一个孩子找到工作时,它会写一个带有工作ID号的锁文件。然后主人会等到那个孩子退出。如果孩子退出后锁定文件仍然存在,那么我知道任务没有完成,并重新启动具有相同作业的孩子(删除锁定文件后)。根据您的情况,您可以在一个简单的数据库表中实现队列。在表中插入作业,并每隔 30 或 60 秒检查一次主表中的新作业。然后只有在孩子完成后才从表中删除它们(并且孩子删除了锁定文件)。如果您一次运行多个“主”,这会出现问题,但您可以实现一个全局“主 pid 文件”来检测和防止多个实例...

    我不建议使用 FastCGI 进行分叉。它可能会导致一些非常模糊的问题,因为环境是要持续存在的。相反,如果您必须拥有 Web 界面,请使用 CGI,但最好使用 CLI 应用程序(一个守护程序)。要与来自其他进程的主进程交互,您可以使用套接字进行 TCP 通信,或者创建一个FIFO file 进行通信。

    至于检测挂起的工作人员,您可以实现一个“心跳”系统,其中子进程每隔这么多秒向主进程发出一个SIG_USR1。那么如果你在那个时间两三次都没有收到孩子的消息,它可能会被挂起。但问题是由于 PHP 不是多线程的,你无法判断一个孩子是否挂起,或者它是否只是在等待阻塞资源(如数据库调用)......至于实现“心跳” ,您可以使用tick function 来自动执行心跳(但请记住,阻塞呼叫仍然不会执行)...

    【讨论】:

    • 谢谢。我现在已经这样做了几次,而且效果非常好。好吧,我应该说如果您的用例与系统的限制一致(IPC 相当昂贵等),它会非常有效。如果它们不是很好对齐,您应该使用真正的线程实现和 PHP 以外的语言......
    • 小心pcntl_fork(),不过。我遇到了在父进程和子进程之间以奇怪的方式共享数据库连接的问题。如果某些 PECL 扩展有类似的怪癖,我不会感到惊讶。我会避免在 PHP 中分叉,并通过exec() 等产生单独的进程,只是为了保持简单
    • 好吧,出于这个原因,我在分叉后明确地重新打开了孩子中的所有连接。分叉没什么好怕的(我经常使用它)。但这需要大量的试验和错误,因为没有很多关于该主题的文档。通过exec 执行的问题是,它使通信和监控变得更加困难(因为一方面exec 是阻塞的,另一方面是更难获得非阻塞exec 调用的进程ID(一个调用最后附上&))...
    • 关于 FastCGI 的有趣评论。不知道,但这是有道理的。有了这个特定的应用程序,主/管理器没有理由不能成为 CLI 守护程序,所以我可以尝试这种方法。
    【解决方案2】:
    【解决方案3】:

    虽然您确实使用 pcntl_fork 运行具有许多作业的异步任务,或者您将每 (s) 秒创建持久性查询,但请注意高 CPU 消耗,您可能会因为无法再次分配内存而挂起处理内存,我认为您可以使用 Gearman 完全构建的最佳选择,或者您可以尝试使用 IronWorker 等云工作者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多