将脚本函数卸载到响应后:方法和最佳实践?
-
20-09-2019 - |
题
第一的,
设置:
我有一个脚本,在用户点击“上传”按钮后执行多个任务,该按钮向脚本发送所需的数据。现在,这部分目前是强制性的,我们目前无法选择从实时源中删除上传和绘制。
这一段故意啰嗦来说明一点。如果你讨厌的话请跳过
现在,数据是使用正则表达式从一个非常时髦的源中解析出来的,然后分解成一个数组。然后,它检查数据库中是否存在已上传数据的日期范围内的任何数据。如果数据库中尚不存在数据日期范围,它会插入数据并向用户输出成功(还有一些安全检查、数据源验证和基本上传验证)...如果数据确实存在,则脚本会获取数据库中已有的数据,查找两组之间的差异,删除不匹配的旧数据,添加新数据,然后向受影响的每个人发送一封电子邮件这些更改(每人一封电子邮件,其中包含该电子邮件中的所有相关更改,这是另一个步骤)。电子邮件地址是通过 LDAP 搜索来提取的,因为我们的数据库有他们的工作电子邮件,但 LDAP 有他们的个人电子邮件,这确保他们在第二天进来之前收到电子邮件,并且不知情。最后,数据提取器被告知“已进行了更改,已发送电子邮件”。他们确实关心这一切。
现在,我可能会添加一个 Google Calendar API,将数据(当它是日程安排数据时)发布到用户的 Google Calendar。我会通过他们的工作日历来完成这件事,但我想在为 Exchange 设置 WebDav 系统之前我应该先熟悉一下 Google 的 API。
</backstory>
现在!
实际问题
此时,在 Google 集成之前,该脚本最多需要一秒半的时间来运行。这是相当令人印象深刻的,至少我是这么认为的(服务器,而不是我的编码)。但在测试中,谷歌的速度却很慢。我们也许可以解决这个问题,但这提出了更大的问题......
在用户确认数据库已更新后,卸载部分工作的最佳方法是什么?这是他最关心的部分,也是最关键的部分。电子邮件通知和 Google 日历更新只是为了那些受上传影响的人的利益,如果这些通知有问题,他会听到(然后我也会听到),无论脚本如何讲述他先。
那么有没有一种方法,例如,运行由脚本上次执行触发的 cronjob?PHP 可以创建 cronjobs exec()
能力?是否有一些标准化的方法来处理需要完成的执行后工作?
对此的任何建议都非常感激。我觉得脚本的臃肿反映了我的开发阶段以及我最终知道如何在网络应用程序中进行分工的需要。
但我也担心这没有完成,因为用户需要知道所有任务何时完成等。所以这就带来了:
最佳实践/更主观的问题
基本上,有没有一种想法是,进度条、实时卸载以及其他让用户束缚于脚本的方法——当然,当与代码优化相结合时——是更好、更优选的方法?说“我们已经完成了你的部分,如果你需要我们,我们会通知用户”等等。
有什么大的事情需要避免(除了明显不给用户任何反馈之外)?
谢谢阅读。编码部分至关重要,因此不要觉得有必要覆盖第二部分或忘记覆盖编码部分!
解决方案
有很多方法可以解决这个问题。您可以像上面所说的那样执行 exec(),但如果提交点击次数过多,您可能会遇到 DoS 情况。pcntl 扩展可以说更擅长管理这样的进程。查看 这个帖子 查看讨论(共有 3 部分)。
您可以使用 Javascript 发送第二个 ajax 帖子,然后运行适当的工作脚本。通过使用ignore_user_abort()并发送Content-Length,浏览器可以提前断开连接,但您的apache进程将继续运行并处理您的数据。优点是没有 forkbomb 的潜力,缺点是它会打开更多的 apache 进程。
另一种选择是在后台使用 cron,它会查看进程队列表以了解“稍后”要做的事情 - 您将项目粘贴到前端的此表中,在处理时在后端将其删除(请参阅 Zend_Queue).
另一种方法是使用更加分布式的作业框架,例如 吉尔曼德 - 可以在其他机器上处理物品。
这一切都取决于您的整体能力和要求。
其他提示
一个计划作业性好这一点。如果你想要做的,当用户上传数据是说“嘿用户,感谢您的数据!”那么这将是细
如果你喜欢一个更直接的方式,那么你可以使用exec()
启动一个后台进程。在Linux环境中它会是这个样子:
exec("php /path/to/your/worker/script.php >/dev/null &");
在&
部分说,“我跑在backgound。”所述>/dev/null
部分重定向输出到黑洞。至于处理所有错误,并通知有关各方 - 这是所有到你的工人脚本的设计
有关更灵活的跨平台的方式,检查出这个 PHP手册帖子