• Ajax实现的长轮询不阻塞同一时间内页面的其他Ajax请求(同域请求)


    最近要做一个来电的弹屏功能,利用OM 系统的接口,OM系统发送请求到接口程序,分析数据添加到mysql数据库中,然后把最新的数据id 跟今日来电的总的数量存储到memcache 中。弹屏程序根据读取的memcache 中的数据  比对,比较是不是有新的请求到来。中间遇到问题是:前台在轮询等待数据的时候,页面中的其他请求被阻塞,查了好多资料,包括 apache 的mpm 模式,都没有找到原因。后来 在论坛里边查到原因:如下

    实际上是不能并发访问同一个站点使用了session的页面,因为访问A页面时,session被锁住了,B页面要等A页面结束释放锁才能被执行。解决方 法就是不用session,或者session使用后立刻释放(php 使用session_write_close释放session锁)。

    以下是我的具体操作的代码:

    js:

        function load_cdr_data() {
            //获取现在的数据
            var url='__MODULE__/Cdrmanage/get_cdr_info?id=';
            var cdr_count = $('input[name="cdr_count"]').val();
            $.ajax({
                type: "POST",
                dataType: "json",
                async: true,
                url: '__MODULE__/Cdrmanage/get_newcdr',
                timeout: 80000, //ajax请求超时时间80秒
                data: {
                    time: 80,
                    count: cdr_count,
                }, //40秒后无论结果服务器都返回数据      
                success: function (data) {
                    //从服务器得到数据,显示数据并继续查询      
                    if (data.status == "10") {
                        var title='您刚才拨打的电话。';
                        url=url+data.cdr_id;
                        open_no_savebtn_dialog('',url,title);
                        $('input[name="cdr_count"]').val(data.count);
                        new_load_cdr_data();
                    }
                    //未从服务器得到数据,继续查询   超时间了   
                    if (data.status == "20") {
                        new_load_cdr_data();
                    }
                },
                //Ajax请求超时,继续查询      
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    if (textStatus == "timeout") {
                        new_load_cdr_data();
                    }
                }
            });
        }

    php 代码实现

        /**
         * 获取cdr 数据信息  初次加载的时候不返回数据   初次的时候count数据为0
         * @access public
         */
        public function get_newcdr() {
            import('Vendor.phpmemcache.Memcachemanage');
            $precount = I('post.count');
            $time = I('post.time');
            $user_id = session('USER_ID');
            $host = '127.0.0.1';
            $port = '11211';
            $expire = '0';
            $memcache_prefix = '';
            $mem = new Memcachemanage($host, $port, $expire, $memcache_prefix);
            if (empty($time)) {
                set_time_limit(0);
            }
            //无限请求超时时间      永久执行直到程序结束
            //session解锁    这个地方查了好久才看到
            //为了安全考虑(避免单个用户并发请求导致的session数据错乱),
            //PHP采用排它锁来互斥的访问session数据
            //(不管你是用session文件还是memcache存session),
            //也就是说开启了session后,单个用户只能串行的访问这个站点,
            //并发的请求只有一个会被立刻响应,其它都会被阻塞
            session_write_close(); //session被占用导致的   排他锁机制
            $i = 0;
            while (true) {
                $i++;
                //若得到数据则马上返回数据给客服端,并结束本次请求      
                //操作memcache 获取数据
                $cdr_info = $mem->get($user_id);
                $max_id = $cdr_info['max_id'];
                $count = $cdr_info['count'];
                if ($count > $precount) {
                    //可以返回一个url  然后弹出窗体实现 
                    $return = array('status' => '10', 'cdr_id' => $max_id, 'count' => $count);
                    exit(json_encode($return));
                }
                if ($i == $time) {
                    //防止程序一直执行  返回数据到前台  前台关闭之后 停止请求
                    $return = array('status' => "20");
                    exit(json_encode($return));
                }
                usleep(500000); //1秒 表示一秒钟判断一下数据状态
            }
        }
  • 相关阅读:
    正则表达式匹配可以更快更简单 (but is slow in Java, Perl, PHP, Python, Ruby, ...)
    ++i? i++? i+=1? i=i+1? 何必纠结?
    数独题的生成与解决方法
    VIM常用设置
    我的“MIT Challenge”
    NDK开发之javaVM
    十二月寒冬
    Linux epoll 笔记(高并发事件处理机制)
    Linux之我见
    半夜惊醒
  • 原文地址:https://www.cnblogs.com/timelesszhuang/p/4719368.html
Copyright © 2020-2023  润新知