1

我有一个有两个动作的控制器。一个执行非常长的计算,并在几个步骤中将状态存储在会话容器中:

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)停止 /module/long 就完成了!

提出这一点,一些 ZFers 认为这是对竞争条件的有效保护。但我不能是唯一一个真正不关心后者的用例。

有什么便宜的技巧可以避免使用队列、数据库或内存缓存?试图保持轻量级。

4

1 回答 1

0

这是预期的行为。这就是为什么:

使用 cookie 来识别会话以存储会话 ID,这允许您的浏览器在下一次请求时获取相同的会话。

由于您的长进程正在使用会话,因此在整个进程执行完成之前它不会调用session_write_close(),这意味着在长进程运行时会话仍然打开。

当您使用另一个浏览器选项卡连接时,浏览器将尝试获取相同的会话(使用相同的 cookie),该会话仍处于打开状态并运行漫长的过程。

如果您使用不同的浏览器打开链接,您会看到页面加载正常,而不是等待session_write_close()被调用,这是因为它正在打开一个单独的会话(但是您不会看到您想要的文本,因为它是单独的会话)

您可以尝试手动编写和关闭 (session_write_close()) 会话,但这可能不是最好的处理方式。

绝对值得看看像 Gearman 这样的东西,没有太多额外的工作,而且它是专门为这种异步作业处理而设计的。即使将状态写入数据库也会更好,但这仍然不理想。

于 2013-01-28T13:25:44.597 回答