如何在不停止其他一切的情况下在 PHP 中执行一项长任务
How to execute a long task in PHP without stopping everything else
我希望能够通过电子邮件从我的服务器向所有订阅者发送时事通讯。
数据库中有超过一千个电子邮件地址需要处理。
我刚刚为我创建了一个后端系统来执行此操作,它允许我编写新闻通讯并开始发送它们,以及一个进度条来监控进度。出于测试目的而不是发送电子邮件,我调用 sleep(1)
然后我意识到,如果我尝试重新加载页面或 运行 另一个 PHP 脚本,而脚本正在 运行ning,什么也没有发生 - 批处理电子邮件过程必须先完成。
然后我想起 PHP 是单线程的,我的系统设计不当。
我知道有一种方法可以用 Thread class 模拟多线程,但我的主机服务器不支持这个。
另一种明显的解决方法是将任务分解并使用 cron 作业一点一点地发送几封电子邮件,但这意味着我必须反复验证我的电子邮件服务器,可能最多 100 次如果我希望我的网站保持活动状态,则需要相当短的时间。
由于我的服务器限制,这可能会引发问题。
显而易见的答案是找到一个限制较少的新服务器,或者将时事通讯错开到可以克服任何问题的程度,但这是最后的手段,在这种情况下我可能只会找到一种在本地进行批量电子邮件发送的方法。
有没有什么方法可以像这样执行一个长的 运行ning PHP 脚本而不延迟所有其他脚本直到它完成?
我是否在某处误解了一些相当基本的 PHP 知识?因为矛盾的是我发现我可以 运行 一些长的 运行ning 脚本(例如我有一个 php 脚本需要大约 5 秒才能完成,因为它将我的旧数据库转换为新格式)由于某种原因,它似乎可以 运行 与其他脚本并行。
是的,我很困惑。请帮忙。
编辑:正如 Wischi 正确指出的那样,发送电子邮件的脚本也调用 session_start(),因为它需要检查管理员是否登录并出于安全目的调用脚本。这就是为什么在这个批处理电子邮件脚本运行期间一切都停止的原因。
听起来您正在使用会话。
无法为单个会话并行 运行 多个 php 脚本,因为这会在使用会话变量时导致意外行为。
有关此主题的更多信息:
- http://konrness.com/php5/how-to-prevent-blocking-php-requests/
- PHP session_start serializes and blocks all others sharing the same session
长运行宁php脚本
修复会话锁定后,您可能正在寻找一些方法来防止脚本在客户端断开连接(关闭选项卡或取消加载)后被终止:
How do I stop PHP from sending data to client while still running PHP code in server?
你可以试试:
system('php my_mailing_script.php > /tmp/mail_logs.txt &');
不要忘记 &
符号,它基本上会说:"Use a new thread to do that".
我希望能够通过电子邮件从我的服务器向所有订阅者发送时事通讯。 数据库中有超过一千个电子邮件地址需要处理。 我刚刚为我创建了一个后端系统来执行此操作,它允许我编写新闻通讯并开始发送它们,以及一个进度条来监控进度。出于测试目的而不是发送电子邮件,我调用 sleep(1) 然后我意识到,如果我尝试重新加载页面或 运行 另一个 PHP 脚本,而脚本正在 运行ning,什么也没有发生 - 批处理电子邮件过程必须先完成。 然后我想起 PHP 是单线程的,我的系统设计不当。
我知道有一种方法可以用 Thread class 模拟多线程,但我的主机服务器不支持这个。
另一种明显的解决方法是将任务分解并使用 cron 作业一点一点地发送几封电子邮件,但这意味着我必须反复验证我的电子邮件服务器,可能最多 100 次如果我希望我的网站保持活动状态,则需要相当短的时间。 由于我的服务器限制,这可能会引发问题。
显而易见的答案是找到一个限制较少的新服务器,或者将时事通讯错开到可以克服任何问题的程度,但这是最后的手段,在这种情况下我可能只会找到一种在本地进行批量电子邮件发送的方法。
有没有什么方法可以像这样执行一个长的 运行ning PHP 脚本而不延迟所有其他脚本直到它完成?
我是否在某处误解了一些相当基本的 PHP 知识?因为矛盾的是我发现我可以 运行 一些长的 运行ning 脚本(例如我有一个 php 脚本需要大约 5 秒才能完成,因为它将我的旧数据库转换为新格式)由于某种原因,它似乎可以 运行 与其他脚本并行。
是的,我很困惑。请帮忙。
编辑:正如 Wischi 正确指出的那样,发送电子邮件的脚本也调用 session_start(),因为它需要检查管理员是否登录并出于安全目的调用脚本。这就是为什么在这个批处理电子邮件脚本运行期间一切都停止的原因。
听起来您正在使用会话。
无法为单个会话并行 运行 多个 php 脚本,因为这会在使用会话变量时导致意外行为。
有关此主题的更多信息:
- http://konrness.com/php5/how-to-prevent-blocking-php-requests/
- PHP session_start serializes and blocks all others sharing the same session
长运行宁php脚本
修复会话锁定后,您可能正在寻找一些方法来防止脚本在客户端断开连接(关闭选项卡或取消加载)后被终止:
How do I stop PHP from sending data to client while still running PHP code in server?
你可以试试:
system('php my_mailing_script.php > /tmp/mail_logs.txt &');
不要忘记 &
符号,它基本上会说:"Use a new thread to do that".