我正在创建一个 PHP 脚本,它允许用户登录网站并执行数据库查询并执行其他可能需要一些时间才能完成的操作。如果 PHP 脚本运行这些操作并且花费的时间过长,则浏览器页面在用户端超时,并且该操作永远不会在服务器端完成。如果我将用户重定向到另一个页面,然后尝试在 PHP 脚本中运行该操作,即使用户不在该页面上,服务器也会运行它吗?动作还能超时吗?
4 回答
在像这样的 Web 应用程序中长时间运行的服务器端操作的情况下,一个好的方法是将操作的排队(应该由 Web 应用程序处理)与操作的运行(应该处理由不同的服务器端应用程序)。
在这种情况下,它可以像 Web 应用程序向数据库表中插入一条记录一样简单,该记录表明用户 X 已请求在时间 Z 处理操作 Y。后端进程(始终运行的守护程序、预定脚本等)您更喜欢)将不断轮询该数据库表以查找新条目。(“新”可能由该表中的“IsComplete”列表示。)它可以每分钟、每几分钟、每小时轮询一次……无论是服务器性能和动作开始的响应性之间的舒适平衡。当它被要求时。
操作完成后,运行该操作的服务器端应用程序将在数据库中将其标记为完成,并将结果存储在您需要存储的任何位置。(另一个数据库表或一组表?一个文件?等等。)Web 应用程序可以在您需要时检查这些结果(例如在每个页面加载时,可能会有某种排队操作的“当前状态”在每个页面上,以便用户可以看到它何时准备就绪)。
所有这一切的原因仅仅是为了保持面向用户的 Web 应用程序响应。即使你做了一些诸如增加超时之类的事情,用户的浏览器仍然可能会放弃。或者用户自己可能会在盯着空白页和旋转光标太久后放弃。用户界面应始终快速响应用户。
您可以考虑使用类似的东西,ignore_user_abort
但在我看来这仍然不理想。我会考虑推迟这些操作并通过消息队列运行它们。PHP 带有Gearman - 这是一种选择。使用消息队列可以很好地扩展,并且可以更好地确保请求操作实际完成。
关于这个主题的很多内容...... PHP(CakePHP)中的异步处理或消息队列......但不要使用Cake :)
set_time_limit()是你的朋友。
如果是我,我会在用户界面中放一个加载图标动画,告诉他们等待。然后我将使用异步AJAX
调用执行“漫长的过程”,然后返回一个答案,正面或负面,您将通过JavaScript
.
就像您将图片上传到 Facebook 时一样,您可以告诉用户发生了什么事。很干净!