PHP Fiber 等待完成,但我不想等待

Hel*_*ine 3 php fibers

我想使用Fiber(PHP 8.1)创建一个线程来发送电子邮件(电子邮件发送需要 10 秒,所以我决定使用线程)。这是我的代码

<?php
$fiber = new Fiber(function () {
    send_email();
});
$fiber->start();

exit(json_encode(['response' => 1]));
Run Code Online (Sandbox Code Playgroud)

结果send_email()并不重要,但启动光纤后,光纤会等到send_email()完成然后exit(json_encode(['response' => 1]));发生!!!我希望它立即退出,但也发送电子邮件!问题是什么?

ADy*_*son 6

根据https://www.php.net/manual/en/language.fibres.php,Fiber是可中断的,但没有提到它是完全异步或多线程 - 它不允许主函数继续自动执行...根据我对它的阅读,只有当您暂停 Fiber 时才会发生这种情况 - 事实上,这就是您在代码中报告的体验。

PHP 是单线程的,并且没有任何类型的适当的基于任务的异步编程模型(不幸的是,与其他服务器端语言(如 NodeJS 或 C#)相比,这是现在的一个主要弱点)。

https://php.watch/versions/8.1/fibres还说

重要的是并发执行并不意味着同时执行。Fiber 和主执行流程不会同时发生。由主执行流程来启动一个Fiber,当它启动时,该Fiber是独占执行的。

Fiber 本身不允许同时执行多个 Fiber 或主线程和一个 Fiber。

...所以我认为您可能误解了此功能及其功能 - 它无法帮助您满足您的要求。

AFAIK 使用 PHP 不可能做你正在尝试的事情。更好的解决方案可能是将电子邮件发送交给单独的进程 - 例如由 触发的后台任务cron。这是一个相当典型的模式:PHP 收到一个请求,要求它发送电子邮件。它将请求记录在数据库表中,然后退出。后台任务按计划执行,从数据库表中提取所有未完成的任务并运行它们,然后更新表以表明它们已完成。这样,如果后台任务花费更长的时间,其实并不重要,因为它不会减慢网站或最终用户的速度。