COMET探索系列二【Ajax轮询复用模型】

COMET探索系列二【Ajax轮询复用模型】

写在前面:Ajax轮询相信大家都信手拈来在用,可是有这么一个问题,如果一个网站中同时有好多个地方需要用到这种轮询呢?就拿我们网站来说,有一个未读消息数提醒、还有一个时实时加载最新说说、昨天又加了一个全网喊话,以后还会要有类似功能添加是肯定的,难道要为每个功能都创建一个独立的轮询?要知道轮询请求中有大半是无用,会对服务器资源和宽带造成巨大的浪费。因此在页面中每增加一个轮询点,对服务器的压力及宽带浪费都将成倍的增长。再考虑一个情况,如果当前网页中需要的不仅是简单的Ajax轮询,而是Ajax长轮询呢?比如在一个 WebIM 应用中同时与两个好友聊天,是不是要为每个好友都建立一个长轮询呢?这不科学,这也不现实,HTTP1.1 协议中规定,同一客户端同一时间最多只能与服务器保持两个连接,问题就变得很棘手了。于是想,所有的轮询无非都是定时向服务器取消息,那么我们是不是只建立一个轮询点定时向服务器取消息,而服务器则将客户端所有需要的消息整理打包后一次性发送给该轮询点,再由该轮询点对返回的消息进行逐点分配处理,心动不如行动,程序员用代码说话。

<!--客户端代码-->

var rtmsg = {

    //请求地址

    uri: U("public/RtMsg/rtmsg"),

    //要获取的消息,可以根据需要动态增减,如从模板变量进行分配,这样可以减少不必要的数据浪费宽带

    items:‘UnreadCount,Allnet,newfeed‘,

    //建立连接

    connect: function () {

        $.ajax({

            url: rtmsg.uri,

            data:{‘items‘:rtmsg.items},

            type: ‘post‘,

            dataType: ‘json‘,

            success: function (res) {

                //请求成功后通过HadnleRes对返回的结果进行分配处理

                rtmsg.HandleRes(res.data);

            }

        })

    },

    //将取回的结果分配给对应的处理程序

    HandleRes: function (res) {

        for (x in res) {

            eval(‘rtmsg.Handle‘ + x + ‘(res[x])‘);

        }

    },

    //处理未读消息数提醒

    HandleUnreadCount: function (res) {

        /*…………*/

    },

    //处理全网喊话

    HandleAllnet: function (allnet) {

        /*…………*/

    },

    //最新说说处理

    HandleNewfeed: function (newfeed) {

        /*…………*/

    }

    /*我还想要*/

    /*我还可以再加*/

};

$(function () {

    //每隔10秒再来一次

    setInterval(rtmsg.connect, 10000);

    //页面加载完毕先来一次

    rtmsg.connect();

})

<!--服务器端程序,注:我这里使用的是ThinkPHP框架-->
<?php
/**
 * 实时消息推送模块
 */
class RtMsgAction extends Action
{
    /**
     * 模块初始化
     */
    function _initialize()
    {
        //关闭session,连接占用session导至页面等待
        session_write_close();
        //不限请求超时
        set_time_limit(0);
    }

    public function rtmsg()
    {
        //接收要获取的消息项
        $items = $_REQUEST[‘items‘];
        //收集消息
        $rt = $this->collect(explode(‘,‘, $items));
        //返回的消息格式大至如下
        $rt = array(
            ‘UnreadCount‘=>array(‘status‘=>1,‘data‘=>array(‘total‘=>5,‘system‘=>2,‘message‘=>3)),
            ‘Allnet‘=>array(‘status‘=>1,‘data‘=>array(‘消息一‘,‘消息二‘,‘消息三‘,‘data格式自定,方便客户端处理为好‘),
            ‘Newfeed‘=>array(‘status‘=>0,‘data‘=>false)
        )
        //返回json格式消息
        echo json_encode($rt);
    }

    /**
     * 收集需要返回给客户端的信息
     */
    public function collect($items)
    {
        //设置未传items时默认获取哪些消息
        $items = $items?$items:array(‘UnreadCount‘, ‘Allnet‘, ‘Newfeed‘);
        $rt = array();
        //逐项获取消息
        foreach ($items as $v) {
            $rt[$v] = call_user_func(array(&$this, ‘get‘ . $v));
        }

        return $rt;
    }

    /**
     * 获取用户的通知统计数目
     */
    public function getUnreadCount()
    {
        /*获取消息过程省略,返回信息格式如下*/
        $data[‘status‘] = ‘获取信息状态‘;
        $data[‘data‘] = ‘信息详情‘;
        return $data;
    }

    /**
     * 获取全网喊话
     */
    public function getAllnet()
    {
        /*获取消息过程省略,返回信息格式如下*/
        $data[‘status‘] = ‘获取信息状态‘;
        $data[‘data‘] = ‘信息详情‘;
        return $data;
    }

    /**
     * 获取最新说说
     */
    public function getNewfeed()
    {
        /*获取消息过程省略,返回信息格式如下*/
        $data[‘status‘] = ‘获取信息状态‘;
        $data[‘data‘] = ‘信息详情‘;
        return $data;
    }

}

基实本模型的关键在于各消息的分类收集,及返回消息之后的分配处理,即代码中以下两个部分

//客户端:将取回的结果分配给对应的处理程序

HandleRes: function (res) {

    for (x in res) {

        eval(‘rtmsg.Handle‘ + x + ‘(res[x])‘);

    }

}

//服务器端:逐项收集信息

foreach ($items as $v) {

    $rt[$v] = call_user_func(array(&$this, ‘get‘ . $v));

}

至此Ajax轮询复用模型就建好了,技术没什么技术,关键是巧合,最后总结一下这种模型的优缺点。

优点:避免了客户端多个轮询点造成的服务器资源及宽带浪费,可以动态更改需要获取的消息项,便于管理。

缺点:没有办法为每个需要轮询的点分配独立的请求频率,一般情况下无所谓啦,如果是在长轮询中使用该缺点不复存在。

时间: 2024-10-14 06:55:51

COMET探索系列二【Ajax轮询复用模型】的相关文章

COMET探索系列一【COMET实践笔记】

转:http://www.cnblogs.com/hackboy/p/3687627.html COMET探索系列一[COMET实践笔记] 这几天在给公司的一个点对点聊天系统升级,之前只是使用简单的ajax轮询方式实现,每5秒钟取一次数据,延时太长,用户体验不是很好,因此打算采用服务器推送技术,故此整理了以下文档,将自己找到的一些资料及心得与大家在此分享.本文主要综述了Comet相关的概念.应用场景.常用的两种实现模型.及PHP实现代码. 概    念:Comet,基于 HTTP 长连接的“服务

ajax轮询请求实现源码分享

ajax轮询请求状态是ajax学习中非常重要的也是必须掌握的知识点,今天就和大家一起来分享一下这部分内容,一起来看看吧.      这里要实现的功能是:通过扫码微信公众号带参数的二维码,来登录网站.      但很明显,如果ajax不间断的请求服务器,这样会加重服务器的负荷,所以本例采用的是js的setInterval来周期性调用执行一个ajax函数来来向服务器请求数据,但请求成功或者请求一定次数后还未成功时用clearinterval函数清空计时器. 代码和注释如下:(后端采用thinkPHP

long poll、ajax轮询和WebSocket

websocket 的认识深刻有木有.所以转到我博客里,分享一下.比较喜欢看这种博客,读起来很轻松,不枯燥,没有布道师的阵仗,纯粹为分享.废话这么多了,最后再赞一个~ WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算) 1.1 和 keep-alive ,把多个HTTP请求合并为一个,但是 Websocket 其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说

Android学习系列(7)--App轮询服务器消息

这篇文章是android开发人员的必备知识. 1.轮询服务器     一般的应用,定时通知消息可以采用轮询的方法从服务器拿取消息,当然实时消息通知的话,建议采用推送服务.    其中需要注意轮询的频率设置,要在需求和性能中平衡. 2.独立进程     无论程序是否正在运行,我们都要能通知到客户,我们需要一个独立进程的后台服务.     我们需要一个独立进程的后台服务.     在AndroidManifest.xml中注册Service时,有一个android:process属性,如果这个属性以

【Javascript】解决Ajax轮询造成的线程阻塞问题(过渡方案)

一.背景 开发Web平台时,经常会需要定时向服务器轮询获取数据状态,并且通常不仅只开一个轮询,而是根据业务需要会产生数个轮询.这种情况下,性能低下的Ajax长轮询已经不能满足需求,频繁的访问还会造成线程阻塞.最优的解决方案当然是用Websocket,采用服务器推送的方式来减少频繁开关连接造成的开销.但是Websocket对于我来说还只是个新事物,在未完成论证的情况下不能直接开发完就上,因此只好采用过渡方案,使用队列的方式,暂时优化多AJax长轮询的情况下造成的线程阻塞问题. 我所用的Web平台框

ajax轮询与长轮询

  刚刚网了关于轮询的知识,必须拿到自己这里来做个备份了! 其实以前用ajax轮询做个及时数据更新的,只是当时做了不知道那个就是轮询. 首先我们什么时候会想到用轮询技术呢? 一般而言,最多的是及时信息更新,比如一个商城活动,参与人数的实时更新等,也还有人用来做过聊天室的,但是哈,轮询技术问题还是很多的,频繁的请求的服务器,服务器会把IP给你列入非白名单里,让你无法请求服务器.所以做及时的我还是建议用websocket 建立长连接. 其次小杨用一位老师的原话来讲解一下ajax轮询技术: 一.Aja

Ajax轮询——“定时的通过Ajax查询服务端”

Ajax轮询——"定时的通过Ajax查询服务端". 概念: 轮询(polling):客户端按规定时间定时像服务端发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接. 百闻不如一见,来段代码相信你一看就明白 //为了让同学们都明白,我用了最简单的实现方法,同学们懂了原理后可以自行衍生: Reception.html //前端代码 <html> <head> <title></title> <script src="

闲话ajax,例ajax轮询,ajax上传文件

引语:ajax这门技术早已见怪不怪了,我本人也只是就自己真实的经验去总结一些不足道的话.供不是特别了解的朋友参考参考! 本来早就想写一篇关于ajax的文章的,但是前段时间一直很忙,就搁置了,趁着元旦放假,赶紧补上吧! ajax的出现,可以出给用户带来了很好的体验,证据如下: 1.感觉:以前要给用户呈现新的内容,就必须要刷新当前页面,结果往往是这样:用户看着看着,唰...,然后又重头看起,我那个去,这谁受得了; 自从有了ajax后,就是这样的,用户关注哪一块,变化哪一块,我们就更新那一块,完全看不

ajax轮询session阻塞问题

近来读了几篇关于ASP.NET下Session机制的文章,结合自己的实际应用,有点感想: 在ASP.NET的Session的默认机制下,对同一个SessionID下的用户请求ASP.NET的Session数据的操作会引起排他锁,假设在同一个SessionID下有多个用户同时请求Session数据的话,就会出现很大的延迟现象.把Session的信息设置为ReadOnly,将不会在导致排他锁的出现.但是,只读Session'数据的操作还是要等待对Session的读写操作引起的排他锁的释放. 因此在不