我有几个耗时的数据库查询要运行。每个都被构建为从网页上选择的选项触发。我认为我通过几个AJAX请求来完成工作是相当狡猾的。
我假定多个请求将被分配到多个进程/线程中,这意味着工作将相对较快地为用户完成。
然而,请求似乎是串行处理的,这意味着用户感觉不到速度优势。
更糟糕的是,更新页面的AJAX请求也排队等待,这意味着它们在之前的请求全部完成之前无法响应。
我了解到这可能是由于PHP会话被锁定引起的。
通常处理这种问题的方法是什么?
- 是否有一种方法可以强制AJAX请求异步工作?
- 我可以阻止PHP锁定会话吗?
- 我应该通过cron使用一个单独的进程来触发后台工作吗?
谢谢!
注意:这个项目是使用symfony框架构建的。
AJAX使用jQuery
// Get the content
$.get('/ajax/itemInformation/slug/'+slug, function(data) {
$('#modal-more-information').html(data);
});
如果在任何给定的AJAX请求期间使用会话,则它们将有效地按请求顺序串行执行。这是由于会话数据文件在操作系统级别被锁定。使这些请求异步的关键是尽可能快地关闭(或永远不启动)会话。
您可以使用session_write_close
(docs)尽快关闭会话。为此,我喜欢使用几个辅助函数,下面的set_session_var
函数将打开会话,写入var,然后关闭会话-尽可能快地进出。当页面加载时,您可以调用session_start
来填充$_SESSION
变量,然后立即调用session_write_close
。从此以后,只使用下面的set函数来写。
get函数是完全可选的,因为您可以简单地引用$_SESSION
全局变量,但我喜欢使用它,因为它提供了一个默认值,并且我可以在代码主体中少一个三进制。
function get_session_var($key=false, $default=null) {
if ($key == false || strlen($key) < 0)
return false;
if (isset($_SESSION[$key]))
$ret = $_SESSION[$key];
else
$ret = $default;
return $ret;
}
function set_session_var($key=false, $value=null) {
if ($key == false || strlen($key) < 0)
return false;
session_start();
if ($value === null)
unset($_SESSION[$key]);
else
$_SESSION[$key] = $value;
session_write_close();
}
请注意,一旦AJAX请求是真正异步的,就会有一整套新的考虑事项。现在您必须注意竞争条件(您必须警惕一个请求设置了一个可能影响另一个请求的变量)—因为您可以看到,当会话关闭时,一个请求对$_SESSION
的更改对于另一个请求将不可见,直到它重新构建值。您可以通过在关键使用之前立即"重建"$_SESSION
变量来帮助避免这种情况:
function rebuild_session() {
session_start();
session_write_close();
}
…但是这仍然容易受到竞争条件的影响。