长轮询实现消息推送

一、应用场景

浏览器与服务器之间保持一个长连接(http链接),服务器有最新的数据生成时及时推送到前端展现。典型场景:新邮件到达通知。

二、业界常用的解决方案

定时轮询,长轮询,websocket(HTML5新增的能力)

其中长轮询兼容性较好,应用的较为广泛,但是切忌在移动网络中应用该技术。

三、长连接前端代码

/**
 *pns模型层
 *@constructs M2012.Model.Pns.PnsModel
 *@extends Backbone.Model
 *@example
 *new M2012.Model.Pns().startRequestPns();
 */
M139.namespace("M2012.Model.Pns", {
    PnsModel : Backbone.Model.extend({
        callApi : M139.RichMail.API.call,
        pnsUrl : ‘/pns/poll?sid=‘ + top.sid + ‘&comeFrom=1003‘, // PNS接口地址负责推送消息到前端
        pnsErrorInterval : 1000 * 120, // 接口报错后下一次重新调接口的时间间隔
        pnsTimer : null, // 接口报错后需要用定时器再调一次接口,pnsTimer用于报错定时器ID
        msgTypes : {//pns推送过来的消息类型
            mailMsg : 70
        },
        logger : new top.M139.Logger({
            name : "M2012.Model.Pns"
        }),
        initialize : function() {
            $App.registerModel("pnsModel", this);
        },

        startRequestPns : function() {
            var self = this;

            var options = {};
            options.method = ‘get‘;
            options.timeout = self.pnsErrorInterval;
            options.error = function() {
                self.callPns();
                self.logger.error("newMailArrival callPns error");
            };
            options.ontimeout = function() {
                self.callPns();
                self.logger.error("newMailArrival callPns timeout");
            };
            options.isSendClientLog = false;

            M139.RichMail.API.call(self.pnsUrl, null, function(e) {
                var result = e.responseData;
                if (result) {
                    console.log(result);
                    if (result.errorCode) {
                        self.callPns();
                        self.logger.error("newMailArrival returndata error", "[pns/poll]", result);
                    } else {
                        self.pnsResultHandle(result);
                        $App.trigger("pnsNewArrival", result);
                        //留给以后扩展
                        self.callPns(500);
                        //self.autoReceiveMail();
                    }
                } else {
                    self.callPns();
                    self.logger.error("newMailArrival returndata error", "[pns/poll]", result);
                }
            }, options);
        },

        callPns : function(seconds) {
            var self = this;

            // 判断用户是否登录超时
            if (top.$App.isSessionOut()) {
                console.log(‘登录超时!不再请求PNS‘);
                return;
            }

            if (self.pnsTimer) {
                clearTimeout(self.pnsTimer);
            }
            self.pnsTimer = setTimeout(function() {
                self.startRequestPns();
            }, seconds || self.pnsErrorInterval);
        },

        /*
         * 此函数可用于单元测试
         * $App.getModel("pnsModel").pnsResultHandle({});
         */
        pnsResultHandle : function(result) {
            var self = this;
            if (result.c > 0) {//c代表数量
                var msgArr = result.msg;
                for (var i = 0, l = msgArr.length; i < l; i++) {
                    // TODO 根据消息类型处理业务逻辑
                }
            } else if (result.c == 0) {
                console.log(‘超时返回!autoReceiveMail‘);
            }
        }
    })
});

四、异常捕获及应用服务器

(1)客户端捕获到xhr的error事件或者接口超时之后可500毫秒之后开始下次轮询。

(2)服务端接口报错,不要立即开始下次轮询,可考虑2分钟甚至更长时间后再开始轮询,因为服务端通常需要较长时间恢复正常。

(3)服务端要保持大量的长连接通常需要用特殊的应用服务器,比如:jetty 。tomcat是肯定不行的。

五、参考资料

书籍:《web性能权威指南》

竞品:163邮箱收信

时间: 2024-10-29 10:46:24

长轮询实现消息推送的相关文章

基于ajax与msmq技术的消息推送功能实现

周末在家捣鼓了一下消息推送的简单例子,其实也没什么技术含量,欢迎大伙拍砖.我设计的这个推送demo是基于ajax长轮询+msmq消息队列来实现的,具体交互过程如下图: 先说说这个ajax长轮询,多长时间才算长呢?这个还真不好界定.这里是相对普通ajax请求来说的,通常处理一个请求也就是毫秒级别的时间.但是这里的长轮询方式在ajax发送请求给服务器之后,服务器给调用端返回数据的时间多长那可还真不好说.嘿嘿,这关键要看我们啥时候往msmq队列中推送数据了,先看看推送的效果图吧..... 抱歉,没弄张

基于ajax与msmq技术的消息推送功能如何实现?

本文和大家分享的主要是基于ajax与msmq技术的消息推送功能相关实现方法,一起来看看吧,希望对大家学习ajax 有所帮助. 我设计的这个推送demo是基于ajax长轮询+msmq消息队列来实现的,具体交互过程如下图: 先说说这个ajax长轮询,多长时间才算长呢?这个还真不好界定. 这里是相对普通ajax请求来说的,通常处理一个请求也就是毫秒级别的时间.但是这里的长轮询方式 在ajax发送请求给服务器之后,服务器给调用端返回数据的时间多长那可还真不好说.嘿嘿,这关键要看 我们啥时候往msmq队列

实现web消息推送的技术和采用长轮询corundumstudio介绍

实时消息的推送,PC端的推送技术可以使用socket建立一个长连接来实现.传统的web服务都是客户端发出请求,服务端给出响应.但是现在直观的要求是允许特定时间内在没有客户端发起请求的情况下服务端主动推送消息到客户端. 有哪些可以实现web消息推送的技术: 不断地轮询(俗称“拉”,polling)是获取实时消息的一个手段:Ajax 隔一段时间(通常使用 JavaScript 的 setTimeout 函数)就去服务器查询是否有改变,从而进行增量式的更新.但是间隔多长时间去查询成了问题,因为性能和即

ASP.NET使用Jquery LigerUI 轮询方式配合Ajax实现消息推送

轮询是在客户端建立一个时钟,每隔一段时间对服务器发送一次请求,获取服务器数据,是实现消息推送最简单最易实现的一种方式,最大的缺点浏览器需要不断的向服务器发出请求,这样会占用很多的带宽,造成资源浪费 下面是JS代码: 1 $(document).ready(function () { 2 setInterval(invoke, 20000); 3 }); 4 function invoke() { 5 var xhr = $.ajax({ 6 type: "POST", 7 dataTy

Web 通信 之 长连接、长轮询(long polling)---实时推送

由于浏览器属于无状态端,页面数据如果想得到及时更新,那需要与服务端保持状态连接,以便有变更能即使改变相关状态. 推荐几篇总结不错的关于长连接.长轮询帖子: 使用:setInterval\iframe\ajax方式来保持长连接: http://www.cnblogs.com/hoojo/p/longPolling_comet_jquery_iframe_ajax.html使用框架,signalR.comet SignalR:http://www.codeproject.com/Articles/3

移动互联网消息推送原理:长连接+心跳机制(MQTT协议)

互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了,所以才会出现像MQTT这种轻量级低消耗的协议来维护长连接,那么要如何维护长连接呢: 在写之前,我们首先了解一下为什么Android维护长连接需要心跳机制,首先我们知道,维护任何一个长连接都需要心跳机制,客户端发送一个心跳给 服务器,服务器给客户端一个心跳应答,这样就形成客户端服务器的一次完整的握手

服务器推Comet长轮询的方式与普通AJAX不断请求的方式的区别

当我们想要在浏览器实时显示某些数据,如何实现? 实现的方式有多种,最简单的既是设置一个间隔,AJAX不断发送请求,这种方式最明显的缺陷不管有没有新数据都会一直发送请求,而且这个间隔如果设置的长,及时性太差,如果间隔设置的短,每个客户端都在不断发送大量请求,影响服务器性能 还有一种是利用服务器推的技术,基于长轮询的方式,如图所示: 一开始会觉得,这个也是在不断的请求服务器端,和普通AJAX不断请求有什么区别?这是还未了解长轮询的流程.深入研究了下,发现区别很大 长轮询大致流程为: 客户端通过AJA

物联网核心协议—消息推送技术演进

消息触达能力是物联网(internet ofthings, IOT)的重要支撑,而物联网很多技术都源于移动互联网.本文阐述移动互联网消息推送技术在物联网中的应用和演进. 一.物联网架构和关键技术 从开发的角度,无线接入是物联网设备端的核心技术,身份设备管理和消息推送技术是物联网云端的核心技术.而从场景体验的角度,除了前者,还要包括手机的前端开发技术. 在上一篇<一张图读懂基于微信硬件平台的物联网架构>博文中,笔者曾用一张大图详细描述了基于微信硬件平台的物联网架构的组成要素.关键场景.和通信协议

php+ajax长轮询实现web即时聊天

web im的实现方式有很多种: 1.普通轮询,原理通过js定时重复发送ajax请求服务端,获取数据后显示. 2.长轮询,ajax请求服务端,服务端有数据会立即返回,服务端无数据时,会一直等待,直到有数据了才立即范围. 3.socket长连接. 特征分析: 方法1:实现起来最容易,定时重复请求服务端会产生无意义的http连接,消耗服务端资源,实时性较差. 方法2:实现起来较容易,会减少无效的ajax请求产生的http连接,能即时返回数据,但服务端会一直挂着,会消耗一定的资源,处理并发能力不强,比