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

问题描述 投票:0回答:2

我想使用

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

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

exit(json_encode(['response' => 1]));

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

php fibers
2个回答
6
投票

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

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

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

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

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

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

据我所知,使用 PHP 不可能做你正在尝试的事情。更好的解决方案可能是将电子邮件发送给单独的进程 - 例如由

cron
触发的后台任务。这是一个相当典型的模式:PHP 收到一个请求,要求它发送电子邮件。它将请求记录在数据库表中,然后退出。后台任务按计划执行,从数据库表中提取所有未完成的任务并运行它们,然后更新表以表明它们已完成。这样,如果后台任务花费更长的时间,其实并不重要,因为它不会减慢网站或最终用户的速度。


0
投票

这是一个老问题,但您可以使用

fastcgi_finish_request()
功能向用户发送响应并继续进行其他操作。 您可以阅读此回复https://stackoverflow.com/a/4236290/1931953

© www.soinside.com 2019 - 2024. All rights reserved.