pcntl_fork如何在PHP中运行?

use*_*856 19 php fork pcntl

pcntl_fork在PHP中感到困惑.

我认为它确实是多线程的,但它是如何工作的,我将如何在脚本中使用它?

Mar*_*hal 45

PCNTL无法创建线程.它只是"分叉"当前的PHP进程.这是什么意思?当您致电时pcntl_fork(),当前流程分为两个流程.父进程的整个命名空间被复制到子进程中,并且两个进程继续并行执行,只有一个区别:pcntl_fork()在父进程和子进程中返回子进程的PID 0.

一些提示:

  • 默认情况下禁用它.如果您设法启用它,则仅针对CLI执行此操作.永远不要在网络服务器上使用它!它将以非确定性的方式表现.它也可以降低整机性能.请保持禁用并继续阅读.
  • 进程之间的通信是可能的,但可怕的(通过共享内存中的序列化对象).
  • 文件描述符(和数据库连接)是共享的,这经常导致问题.您必须在分叉后重新连接数据库,否则MySQL server has gone away当第一个分叉进程关闭连接时,您将收到来自所有分叉进程的错误.
  • 父进程必须等待子进程完成,否则将使僵尸进程消耗系统资源.

以下是文档中的示例:

<?php

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     // we are the child
}
Run Code Online (Sandbox Code Playgroud)

但请记住,PHP只是脚本语言.它不是为并行计算而设计的.根据您的需要,您可以更好地同时运行CRON,消息队列或低级语言程序.

分叉的PHP程序很难阅读,理解和调试.维持该计划将是一场噩梦.

不要犯错误,避免分叉.你不需要它.你真正需要的是异步任务运行器.好消息,有RabbitMQ很好的教程 ;-)你也可以尝试有前途的RabbitMQ库叫做Bunny

PS:使用消息队列而不是分叉为您提供了另一个优势.您可以使用多个服务器处理队列,并在流量增长时水平扩展.