标签:
最近要做一个来电的弹屏功能,利用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秒 表示一秒钟判断一下数据状态 } }
Ajax实现的长轮询不阻塞同一时间内页面的其他Ajax请求(同域请求)
标签:
原文地址:http://www.cnblogs.com/timelesszhuang/p/4719368.html