PHP中的异步函数调用

Har*_*ngh 73 php asynchronous network-programming

我正在开发一个PHP Web应用程序,我需要在请求中执行一些网络操作,例如根据用户的请求从远程服务器获取某人.

是否有可能在PHP中模拟异步行为,因为我必须将一些数据传递给函数并且还需要从它输出.

我的代码是这样的:

<?php

     $data1 = processGETandPOST();
     $data2 = processGETandPOST();
     $data3 = processGETandPOST();

     $response1 = makeNetworkCall($data1);
     $response2 = makeNetworkCall($data2);
     $response3 = makeNetworkCall($data3);

     processNetworkResponse($response1);
     processNetworkResponse($response2);
     processNetworkResponse($response3);

     /*HTML and OTHER UI STUFF HERE*/

     exit;
?>
Run Code Online (Sandbox Code Playgroud)

在发出3个请求时,每个网络操作大约需要5秒钟才能完成为应用程序的响应时间添加总计15秒.

makeNetworkCall()函数只是执行HTTP POST请求.

远程服务器是第三方API,所以我没有任何控制权.

PS:请不要回答关于AJAX或其他事情的建议.我目前正在寻找是否可以通过PHP实现这一点,可能是C++扩展或类似的东西.

alj*_*o f 13

如今,它是更好地使用队列比线程(对于那些谁不使用Laravel有吨其他实现在那里像这样).

基本思想是,您的原始PHP脚本将任务或作业放入队列中.然后,您在其他地方运行队列作业工作者,将作业从队列中取出并开始独立于原始PHP处理它们.

优点是:

  1. 可伸缩性 - 您只需添加工作节点即可满足需求.通过这种方式,任务可以并行运行.
  2. 可靠性 - 现代队列管理器,如RabbitMQ,ZeroMQ,Redis等,都非常可靠.


Col*_*n M 7

cURL 将是您唯一真正的选择(要么是这样,要么使用非阻塞套接字和一些自定义逻辑)。

此链接应该会将您引向正确的方向。PHP 中没有异步处理,但如果您尝试同时发出多个 Web 请求,cURL multi 将为您处理。


Seb*_*ers 6

我没有直接的答案,但是您可能需要研究以下这些问题:


JVE*_*999 6

pcntl_fork()一种方法是在递归函数中使用。

function networkCall(){
  $data = processGETandPOST();
  $response = makeNetworkCall($data);
  processNetworkResponse($response);
  return true;
}

function runAsync($times){
  $pid = pcntl_fork();
  if ($pid == -1) {
    die('could not fork');
  } else if ($pid) {
    // we are the parent
    $times -= 1;
    if($times>0)
      runAsync($times);
    pcntl_wait($status); //Protect against Zombie children
  } else {
    // we are the child
    networkCall();
    posix_kill(getmypid(), SIGKILL);
  }
}

runAsync(3);
Run Code Online (Sandbox Code Playgroud)

有一件事pcntl_fork()是,当通过 Apache 运行脚本时,它不起作用(Apache 不支持它)。因此,解决该问题的一种方法是使用 php cli 运行脚本,例如:exec('php fork.php',$output);从另一个文件运行脚本。为此,您将有两个文件:一个由 Apache 加载,另一个exec()在 Apache 加载的文件内部运行,如下所示:

apacheLoadedFile.php

exec('php fork.php',$output);
Run Code Online (Sandbox Code Playgroud)

fork.php

function networkCall(){
  $data = processGETandPOST();
  $response = makeNetworkCall($data);
  processNetworkResponse($response);
  return true;
}

function runAsync($times){
  $pid = pcntl_fork();
  if ($pid == -1) {
    die('could not fork');
  } else if ($pid) {
    // we are the parent
    $times -= 1;
    if($times>0)
      runAsync($times);
    pcntl_wait($status); //Protect against Zombie children
  } else {
    // we are the child
    networkCall();
    posix_kill(getmypid(), SIGKILL);
  }
}

runAsync(3);
Run Code Online (Sandbox Code Playgroud)


Jim*_*mmy 5

这个老问题有了新答案。现在有一些 PHP 的“异步”解决方案(它们相当于 Python 的多进程,因为它们产生新的独立 PHP 进程而不是在框架级别管理它)

我见过的两种解决方案是

试一试吧!