我有一个带有两个动作的控制器。一个执行非常长的计算,并且在几个步骤中,将状态存储在会话容器中:
public function longAction()
{
$session = new Container('SessionContainer');
$session->finished = 0;
$session->status = "A";
// do something long
$session->status = "B";
// do more long jobs
$session->status = "C";
// ...
}
第二个控制器:
public function shortAction()
{
$session = new Container('SessionContainer');
return new JsonModel(
array(
'status' => $session->status
)
);
}
这些都是通过AJAX调用的,但我可以在使用浏览器选项卡时证明相同的行为。我首先调用/ module / long来做它的事情。当它完成任务时,调用/ module / short(我认为只会回显JSON)就完成了档位/模块/ long!
提起这一点,一些ZFers认为这是对抗竞争条件的有效保护;但我不能成为唯一一个真正不关心后者的用例。
任何避免前往队列,数据库或内存缓存的廉价技巧?试图保持轻量化。
答案 0 :(得分:0)
这是预期的行为。这就是原因:
使用cookie来识别会话以存储会话ID,这允许您的浏览器在下次请求时接收相同的会话。
由于您需要使用会话,因此在整个流程执行完成之前,它不会调用 session_write_close(),这意味着在长流程运行时会话仍处于打开状态。
当您使用其他浏览器标签进行连接时,浏览器会尝试使用仍然打开并运行漫长过程的相同会话(使用相同的Cookie)。
如果您使用其他浏览器打开链接,您会看到页面加载正常而不是等待 session_write_close()被调用,这是因为它正在打开一个单独的会话(但是你不会看到你想要的文字,因为它是一个单独的会议)
您可以尝试手动编写和关闭(session_write_close())会话,但这可能不是解决问题的最佳方式。
对于像Gearman这样的东西,绝对值得一看,没有那么多额外的工作,而且它专门为这种异步作业处理而设计。即使将状态写入数据库也会更好,但这仍然不理想。