PHP / AJAX 并发会话仅在 Chrome 中行为不端

Posted

技术标签:

【中文标题】PHP / AJAX 并发会话仅在 Chrome 中行为不端【英文标题】:PHP / AJAX Concurrent Session Misbehaving only in Chrome 【发布时间】:2013-02-25 09:39:07 【问题描述】:

TL;博士。无需先涉足 JS 的有趣部分:我正在递增会话计数器,但不同的请求看到相同的值。这只是 Chrome 中的一个问题。在 Firefox 和 Internet Explorer 中,每个请求都有一个唯一值。

我尝试多次访问网页(处理数据),直到获得 204 HTTP 代码。我可以一次执行一个 ajax 调用,方法是让 ajax 在成功时调用自身,然后在 204 处停止。

因为我想更快地完成它们,所以我在 js 中有多个“线程”都在这样做。我的意思是创建了多个相同的 ajax 调用,并且它们在完成时都会启动另一个调用,并在 204 代码处停止。

我的相关js如下所示:

$(function() 
    // "thread" id
    var counter = 1;

    // run 3 "threads"
    generateThreads(3);

    function generateThreads(num) 
        if (num <= 0)
            return;

        doNextItem(counter++);

        // Pause before starting the next thread
        setTimeout(function() 
                generateThreads(num-1);
            ,
            50);
    

    function doNextItem(thread) 
        $.ajax(
            url: URL,
            statusCode: 
                200: function(data) 
                    logItem(data, thread);
                    doNextItem(thread); // call itself on the same thread

                ,
                204: function(data) 
                    finished(); // done, don't recurse, end the thread
                
            
        );
    
);

然后在 php 中,我增加一个存储在 Session 中的整数,并在超过截止值时返回 204。

if (!isset($_SESSION["nums"]))

    $_SESSION["nums"] = 0;

else if ($_SESSION["nums"] > 10) 
    http_response_code(204);
    die();

echo json_encode(array("num" => $_SESSION["nums"]++));

然后当我运行它时,奇怪的部分就来了。 javascript 中的 logItem() 只是将线程 ID 打印到控制台,然后是 php 中的数字。

铬:

1: 0 
2: 0 
2: 1 
1: 1 
3: 1 
2: 2 
1: 2 
3: 2 
1: 3 
2: 3 
3: 3 
3: 4 
1: 4 
2: 4 
3: 5 
2: 5 
1: 5 
2: 6 
3: 6 
1: 6 
1: 7 
2: 7 
3: 7 
1: 8 
3: 8 
2: 8 
1: 9 
2: 9 
3: 9 
2: 10
1: 10
3: 10

火狐/IE

1: 0
2: 1
3: 2
1: 3
2: 4
3: 5
1: 6
2: 7
3: 8
1: 9
2: 10
3: 11
1: 12
2: 13
3: 14
1: 15
2: 16 
3: 17 
1: 18  
2: 19 
3: 20

为什么 chrome 会给我重复的值?

更新

真正可疑的是,每个数字的重复次数完全等于同时进行的 ajax 调用的数量。永远不会更少,永远不会更多,但正是如此。如果我同时运行 6 个 ajax 调用,它们都会得到相同的数量。如果这是一个时间问题,它就不会那么一致,特别是因为我抵消了彼此不同的 ajax 调用。这对我来说意味着这是一个 javascript 问题,不一定只是之前出现的 php 问题。

更新的巨大游戏改变 这只是 Chrome 中的一个问题。在 Firefox 或 Internet Explorer 中不会发生。在 Firefox 和 IE 中,每个请求都会获得一个新的计数器值。显然这是一个客户端问题。对这些信息进行更多研究会发现很多关于无效请求执行重定向会终止会话的事情。特别是 favicon.ico 的常见场景。我所有的请求都成功了,我的 favicon.ico 也成功加载了。

【问题讨论】:

在您发送会话时尚未设置或修改,因为上一个执行线程的结束要等到所有 3 个线程都完成后才会发生。换句话说,你只是异步地做同样的事情 3 次。变量没有改变。在 setTimeout() 中尝试更大的时间间隔 我只是猜测你的 ajax 调用太快了。每一个都可能在服务器更新 $_SESSION 之前访问 php 页面。此外,javascript 是单线程的,因此您的线程概念似乎是人为的;目前,您的“线程”永远不会同时执行,除非您计划在某个时候将它们与网络工作者交换developer.mozilla.org/en-US/docs/DOM/Using_web_workers 此外,您的代码示例是一个奇怪的问题混合:为什么即使在您可以轻松跟踪的情况下让 PHP 存储一个值Javascript 中的值? @zgr024:网络上的所有其他链接都表明 session_start() 锁定了对会话文件的访问,因此不会同时发生具有该会话 ID 的其他会话请求。 @MarkFox:显然我不会只增加 php.ini 中的计数器。这是一个愚蠢的例子,我正在做一些更复杂的事情,这只是一个说明问题的例子。 另外,我的“线程”只是 ajax 调用。所以我同时进行了 3 个 ajax 调用,它们在完成后立即重新启动,直到返回 204。这在 javascript 中完全没问题,与线程的定义类似。 【参考方案1】:

Chrome 正在缓存响应,因为您在短时间内多次发送相同的请求。强制 ajax 调用不缓存响应应该可以解决您的问题。试试这个:

$.ajax(
    url: URL,
    cache: false,
    statusCode: 
...

【讨论】:

我在使用 php 时遇到问题。问题是会话返回其他用户的不同值。这个答案给了我一个解决的想法。但我不使用此代码,我宁愿按照此处的说明进行操作 spacebug.com/solving_browser_caching_problem_of_ajax-html。但是你的回答还是很有帮助的

以上是关于PHP / AJAX 并发会话仅在 Chrome 中行为不端的主要内容,如果未能解决你的问题,请参考以下文章

并发会话和 AJAX 的 PHP 问题

PHP会话问题*仅在IE中*

具有并发会话的 grails 3

ASP.NET Web API 在来自 Chrome 扩展的并发 AJAX 调用上崩溃

使用 AJAX 检查 PHP 会话是不是存在或过期

如何使用子域和 AJAX 使 PHP 会话工作?