php - 两个ajax请求可能发生冲突?

标签 php ajax zend-framework jquery

我的其中一个站点在加载页面时执行了两个 ajax 请求时遇到问题。我将 jQuery 与基于 zend 框架的 PHP 应用程序结合使用。

相关的 HTML(简化版)如下所示:

<select id="first">
     <option value="1">First Option</option>
     <option value="2">Second Option</option>
</select>
<div class="first_block"></div>

<select id="second">
     <option value="1">First Option</option>
     <option value="2">Second Option</option>
</select>
<div class="second_block"></div>

这是我的 jQuery 的样子:

$(document).ready(function(){

// function to update the first block
var updateFirstBlock = function(){
    var param = $(this).val();
    $.ajax('module/controller/action/param/' + param, {
        'success': function(data){
            $('.first_block').html(data);
        }
    });
};

// bind and trigger the first update function
$('select#first').bind('change', updateFirstBlock );
$('select#first').trigger('change');


// function to update the second block
var updateSecondBlock = function(){
    var param= $(this).val();
    $.ajax('module/controller/another-action/param/' + param, {
        'success': function(data){
            $('.second_block').html(data);
        }
    });
};

// bind and trigger the second update function
$('select#second').bind('change', updateSecondBlock );
$('select#second').trigger('change');

});

PHP 应用程序仅返回一些内容,具体取决于分配的值。

现在加载页面时发生的情况是,在十分之九的情况下,两个请求之一得不到答复。另一个获得 200 OK,失败的一个超时。没有规律,哪个请求失败。

网络服务器 (Apache 2.2) 配置是否有问题,导致两个同时触发的请求相互约束?

编辑

如果我将两个请求都设置为 async: false,它们将始终正确执行。所以我认为一定有碰撞。

编辑 2

此行为的一个可能原因可能是 php 的 session 锁定。我将进一步研究这一点。

最佳答案

看来您的 PHP session 锁绝对正确:

session 锁定(并发)注意事项

默认的 PHP session 模型会锁定 session ,直到页面加载完成。因此,如果您有两个或三个要加载的帧,并且每个帧都使用 session ,它们将一次加载一个。这样一来,在任何时候只有一个 PHP 执行上下文可以写入 session 。

有些人通过在将任何数据写入 $_SESSION 后立即调用 session_write_close() 来解决这个问题 - 他们甚至可以在之后继续读取数据他们称之为。 session_write_close() 的缺点是您的代码仍然会锁定在任何 session 页面上对 session_start() 的第一次调用,并且你必须尽快在你使用 session 的任何地方使用 session_write_close()。这仍然是一个非常好的方法,但是如果您的 Session 访问遵循某些特定的模式,您可能有另一种方法需要对代码进行较少的修改。

想法是,如果您的 session 代码主要从 session 中读取,很少写入,那么您可以允许并发访问。为了防止 session 数据完全损坏,我们将在写入时锁定 session 的后备存储(通常是 tmp 文件)。这意味着 session 仅在我们写入后备存储的短暂瞬间被锁定。但是,这意味着如果您同时加载两个页面,并且都修改 session ,则最后一个获胜。无论哪个先加载,其数据都会被第二个加载的数据覆盖。如果您不介意,您可以继续 - 否则,请使用上面的 session_write_close 方法。

如果您有一些复杂的代码,这些代码依赖于 session 中的某些状态,以及数据库或文本文件中的某些状态,或者其他东西 - 同样,您可能不想使用此方法。当你有两个同时运行的页面时,你可能会发现一个页面运行到一半,修改你的文本文件,然后第二个页面运行到一半,进一步修改你的文本文件,然后第一个完成 - 你的数据可能是损坏或完全丢失。

因此,如果您准备好调试可能非常、非常讨厌的竞争条件,并且您的 session 访问模式是读为主而写很少(而不是写得很频繁),那么您可以尝试以下系统。

将 session_set_save_handler() 中的示例复制到您的包含文件中,在您开始 session 的位置上方。修改session的write()方法:

function write($id, $sess_data)
{
  global $sess_save_path, $sess_session_name;

  $sess_file = "$sess_save_path/sess_$id";
  if ($fp = @fopen($sess_file, "w")) {
   flock($fp,LOCK_EX);
   $results=fwrite($fp, $sess_data);
   flock($fp,LOCK_UN);
   return($results);
  } else {
   return(false);
  }

}

您可能还想为 session 添加 GC(垃圾收集)方法。

当然,请对这个建议持保留态度——我们目前在我们的测试服务器上运行它,它似乎在那里工作正常,但人们报告说共享内存 session 处理程序和此方法存在严重问题可能和那样不安全。

您还可以考虑为代码中可怕的并发敏感位实现自己的锁。

引用:http://ch2.php.net/manual/en/ref.session.php#64525


实现数据库 session 处理程序可能是值得的。如果使用良好的数据库结构,使用数据库可以消除这个问题,实际上可以略微提高性能。

关于php - 两个ajax请求可能发生冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6262087/

相关文章:

php - 我应该将什么传递给 symfony 的 handleRequest 类?

javascript - 使用 Ajax 在 PHP 中发表评论

zend-framework - 从一个 PHP 框架迁移到另一个

php - 布局和 View 有什么区别?以 Zend_Layout 和 Zend_View 为例

php - 如何禁用/只读 MultiCheckbox 中的某些复选框?

php - 在 Laravel 中自动发送电子邮件

javascript - PHP 搜索文件中不匹配的行

javascript - 如何从打开 UPS 页面返回 UPS 运输报价

javascript - 如何从异步调用返回响应?

javascript - 检查 jQuery.validate() 上的元素上是否已有 "active"类