12 March 2023 - 字数统计：1312 - 阅读大约需要4分钟 - Hits: Loading...

# PHP异步执行的探索

by mayx

这是一篇创建于 天前的文章，其中的信息可能已经有所发展或是发生改变。

AI摘要

这篇文章主要探讨了PHP实现异步执行的挑战和尝试。作者在ThinkPHP项目中遇到需要立即返回数据并继续后台耗时操作的问题。以前采用的file_get_contents函数虽然解决了返回速度慢的问题，但涉及到使用危险的函数和服务器配置限制。作者对于使用消息队列、Swoole框架及popen函数等方法持保留态度，认为它们可能带来安全风险或超出项目规模。 作者发现fastcgi_finish_request函数可以输出内容并结束请求，但需注意与session管理和PHP-FPM的交互。存在问题包括对Apache环境的限制、进程数量限制以及在TP框架下无法使用return。作者总结到，PHP处理多线程问题有困难，对于频繁遇到这类问题的项目，可能需要考虑使用其他语言。

- 起因
- 探索异步的方法
- 感想

看来异步总是个难以解决的问题啊……

#
起因

最近，我在写一个ThinkPHP框架为基础的代码时遇到了一个问题，我希望在执行完一个操作后立马返回数据，然后在后台继续运行一个比较耗时的东西。我以前写的一个图片机器人其实也遇到过这种问题，为了解决返回很慢的问题，我采用了“离弦之箭”——使用file_get_contents函数请求自己，并且使用’timeout’参数来防止页面挂起，另外接收的部分使用`ignore_user_abort(true)`和`set_time_limit(0)`保证在请求结束时让程序依然继续运行。不过我用的是TP框架啊，不知道用那两个函数会不会出问题，还有这个“timeout”到底填多少比较合适也不确定，所以就想试试别的方法。

#
探索异步的方法

对于正规的情况来说，直接去网上搜如何让PHP异步执行代码，估计大多会说使用什么消息队列或者用什么Swoole框架吧，或者简单点用popen函数来fork一个进程，或者用什么fsockopen，貌似原理和我用file_get_contents函数差不多？其实吧我觉得从本质来说那个所谓的Swoole框架已经不算PHP的东西了，我觉得它更像是一个能通过http请求的popen函数，通过某种方式也一样是在本地去调用PHP脚本，只是可能用了些什么比如线程啥的特性提高了性能而已。

我看完这些选择之后很不满意，我不希望代码里出现popen这样的函数，说实话这是个危险的函数，绝大多数情况下服务器应该要禁用这种函数的，毕竟如果因为某些原因被人上传了PHP木马，他们可以直接用这个函数去执行命令了。至于什么乱七八糟的异步框架，想不想学是一方面，主要是我的项目还没有达到用这种东西的规模。那难不成我只能继续用之前图片机器人的那个“离弦之箭”的办法了吗？

后来我找到了一个很不错的函数，叫做fastcgi_finish_request，它可以在程序结束前把要输出的东西输出并且结束请求，不过使用它以后看文档说明好像说推荐再执行一下session_write_close函数，不然在这个程序执行完成前session会被锁住，没法操作。

不过这个函数只能在使用PHP-FPM的时候使用，如果是像Apache那样使用模块的方式运行PHP估计就用不了了，当然目前大多数环境应该都用的是Nginx+PHP-FPM吧，我反正是很少见到有人用Apache，虽然听说那样性能似乎会更好？

还有一个问题就是如果这个需要运行的脚本的时间太长了，以至于同时运行这个脚本的进程数量超过了pm.max_children，那么PHP-FPM就不能接受新的请求了，这也是一个缺陷。

另外在这种情况下我使用了TP框架还会遇到一个问题，那就是我不能使用return返回内容了，毕竟return了之后就不能执行其他函数了啊，所以就只能提前用echo之类的东西输出，执行完fastcgi_finish_request和所有需要长时间运行的代码后就只能return空值或者直接exit吧。

#
感想

看来用PHP来做异步果然是难事啊，不如说大多数程序想要处理好多线程的问题都挺难的吧，也许如果项目经常遇到这种问题，应该考虑用其他语言来编写了呢。

tags: PHP - 异步 查看原始文件

#### 推荐文章

Loading...

上一篇：使用CF Workers Cron触发器进行签到
下一篇：关于最近人工智能的探索
想问这篇文章
召唤伊斯特瓦尔