php异步调用类方法


php call class method asynchronously

我需要在循环中异步调用一个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永远不会启动。

我希望在后台为检索到的所有批ID同时异步调用sendBatchMail。

我不是很精通pthreads。。。似乎是我的最后一站。

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

这直接将我带到消息队列和工作者。看看Gearman,可以找到一个非常简单的这样的系统,尽管还有很多其他的可能性,包括websphere MQ、Redis和其他。您只需在这个队列中填充一些消息,然后由一个或多个作为cron作业或后台持久工作进程运行的PHP脚本来处理,这些脚本与前端HTTP处理程序完全解耦。

实现这一点的一种方法是使用带有发送代码的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中,让它发送所有的电子邮件。

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