php异步调用类方法

时间:2015-03-31 07:42:05

标签: php exec background-process popen

我需要异步调用循环中的PHP方法。

这就是我的尝试:

foreach ($batch_ids as $batch_id) {
          $this->launchBackgroundProcess( $this->sendBatchMail($batch_id) );
        }

public function launchBackgroundProcess($call) {

  // pclose( popen( $call.'/dev/null &', 'r'));     
  Proc_close( Proc_open( $call.' > /dev/null & ', 'r'));
  return true;
}

现在错误是我的函数sendBatchMail被直接调用,并且从不调用launchBackgroundProcess(使用echo / print / log来检查)。

因此,如果在批处理ID中有10k邮件,则下一批ID的endBatchcMail永远不会启动。

  

我希望在后台同时和异步调用sendBatchMail,以便检索所有批处理ID。

我对pthreads并不是很精通...而且似乎是我的最后一站。

2 个答案:

答案 0 :(得分:1)

这不是真正的方法。每个PHP进程都会针对每个请求启动并拆除。您不应该尝试直接从回答HTTP请求的PHP脚本中直接启动任何内容。它唯一的工作应该是尽快返回HTTP响应,然后挂机。任何大量的工作都应排队等待,以便稍后由更持久的后端工作人员处理。

直接将我带到消息队列和工作人员。查看Gearman这个非常简单的系统,尽管还有其他许多可能性,包括ØMQ,Redis和其他。您只需在此队列中填充大量消息,然后由一个或多个在后台运行作为cron作业或持久化工作者守护程序的PHP脚本处理,完全与前端HTTP处理程序分离。

答案 1 :(得分:1)

执行此操作的一种方法是使用带有发送代码的php脚本,然后执行:

shell_exec("theBackgroundScript.php >/dev/null &");

但这意味着您将同时拥有大量流程。此外,如果其中一个由于某种原因而失败,那么找到并再次运行它会很复杂。

相反,请考虑在数据库中创建一个表来保存所有邮件作业。它可能像:

CREATE TABLE email_jobs (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
executed TINYINT DEFAULT 0,
destination VARCHAR(255) NOT NULL,
subject VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME DEFAULT NULL);

然后,您只需在需要时添加每个作业的详细信息:

$db->query("INSERT INTO email_jobs (destination, subject, content, created_at) VALUES ('someperson@example.com', 'some subject', 'some email content', NOW())");

然后,您需要一个PHP脚本来查询数据库中尚未执行的作业:

$row = $db->query("SELECT * FORM email_jobs WHERE executed = 0 LIMIT 1");
// ... send email described in $row

脚本获取第一个未执行的作业(或前N个未执行的作业),并发送它。 然后你只需要将脚本放在cron中,然后让它发送所有电子邮件。

如果一个失败,再次发送它很容易,只需将执行设置为零,它就会被传递。