我有一个简单的报告脚本需要5-10分钟才能运行。它通过fsockopen调用异步触发,在后台运行。它在某些时候非常有效。但是,如果用户刷新主页面,而从前一个页面加载触发的异步报告仍在运行,则主页面将挂起,直到第一页面加载的异步过程完成。
以下是我的脚本背后的粗略逻辑,然后是有效的和不可用的更多细节......
main.php
if last report was already run within the hour (mysql select last report time)
display existing report, that's it.
else
log latest report process request
run report asynchronously in the background (async.php)
notification when updated report is completed (simple ajax pinger every 10s)
async.php
run report
update last report request table with "complete" status
the ajax pinger in main.php pulls the "complete" record and triggers notification
问题
用户加载main.php
结果: 很棒。立即加载,记录新的报告请求并按预期触发异步调用。 Async.php现在需要5-10分钟才能完成报告。全部在后台。
用户在20分钟后(在async.php完成后)加载main.php
结果: 很棒,即时加载,但跳过运行异步报告流程,因为它是在上次请求的一小时内。
用户等待一小时后再次加载main.php
结果: 一切顺利,如第1步
到目前为止一切都很好,但是......
现在,用户仅在步骤3后2分钟加载main.php。
结果: 失败!此页面加载将一直挂起,直到步骤3中触发的异步过程完成。即使具有请求日志时间的mysql表在步骤3中立即更新。因此,步骤4应该只是跳过调用而只是渲染现有报告,如步骤2.
世界上有什么?你建议怎么调试这个?如果另一个用户想要在用户1在步骤4中挂起时运行相同的报告,则该另一个用户可以正常运行新报告。
我的代码中没有做任何奇特的事情。只需简单的if / then和mysql选择查找。异步脚本主要从外部源引入,因此它不会锁定可能阻止请求日志时间查找的mysql表(完整报告可能只在10分钟内运行一百五十毫秒的查询,而且没有一个触及请求日志)。 / p>
一个解决方案就是完成这些流程,但我担心我会运行很多永远不会被看到的报告。而不是报告只需要5-10分钟,如果我更频繁地运行报告,它将会成倍增长。
所以,坚持我上面的攻击计划(现在),你推荐什么?为什么第2步会正确加载,而不是第4步?是否存在某种我不知道的用户脚本锁定或限制?
答案 0 :(得分:0)
生成报告时会出现问题,对吧?
如果是这样,您可以在报表开始生成时创建文件,并在结束时将其删除,并在启动新一代报表之前检查它是否存在。在您的async.php文件中:
check if 'running.txt' file exists
if it exists:
display 'report is already running, you need to wait ! '
stop
else :
create file 'running.txt'
run report
delete file 'running.txt'
update last report request table with "complete" status
the ajax pinger in main.php pulls the "complete" record and triggers notification
答案 1 :(得分:0)
我最终接受了regilero的建议。我设置了一个cron来运行每一分钟并获取队列中的任何新请求。这完全消除了滞后问题。谢谢regilero!