1.什么是长轮询
顾名思义,长轮询就是不停循环请求服务器,获取最新信息。
长轮询分为两类:
1)浏览器以固定时间间隔向服务器发送请求
缺点是轮询频率要足够快,但又不能太频繁,否则当成百上千个客户端不断请求,会使web服务器面临极大压力
2)服务器推送
浏览器和服务器之间保持请求的连接,当服务器数据更新时,向浏览器响应新数据,然后关闭连接,浏览器接收到响应,重新发送请求,服务器保持请求状态,如此循环。
优点是极大减少了web服务器的负载,即时响应,用户体验佳。相对于方法1,客户端制造大量的短而频繁的请求(以及每次处理http头部产生的开销),服务器只有当其接受一个初始请求和再次发送响应时处理连接,大部分时间没有新的数据,连接也不会消耗任何处理器资源。

2.长轮询使用示例
以下示例中,用户可添加P商品(数量为10个)到购物车,当用户添加商品到购物车,或删除购物车的时候,其他用户可以适时看到P商品数量的变化。

1)用户访问主页
显示库存数量,添加/删除购物车操作

class DetailHandler(tornado.web.RequestHandler):
def get(self):
self.post()
def post(self):
#商品条码
session=uuid.uuid1()
#查询现有库存
count=self.application.shoppingCart.getInventoryCount()
#显示
self.render("index.html",session=session,count=count)

界面如下:

2)主页长轮询商品当前库存

class StatusHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
#注册添加/删除购物车后的回调函数
self.application.shoppingCart.register(self.on_message)
def on_message(self,count):
print str(count)
self.write('{"inventorycount":"%s"}'%count)
self.finish()

@tornado.web.asynchronous装饰器表示请求为异步IO类型,服务端没有主动调用finish()方法时,请求连接会一直保持。

register方法注册了在用户添加/删除购物车后,需要调用的回调函数
在用户添加/删除购物车后,服务器会调用所有连接中的请求注册的回调函数,将库存数量响应给所有连接请求,然后关闭每个连接,请求结束。
此时,客户端会循环发起请求,建立连接,当库存变化时,服务器推送新的数据到客户端,结束连接。如此循环

3)添加/删除购物车操作

class CartHandler(tornado.web.RequestHandler):
def get(self):
self.post()
def post(self):
action=self.get_argument('action')
session=self.get_argument('session')
if not session:
self.set_status(400)
return
if action=='add':
#添加到购物车
self.application.shoppingCart.moveItemToCart(session)
elif action=='remove':
#删除购物车
self.application.shoppingCart.removeItemFromCart(session)
else:
self.set_status(400)

4)具体看一看添加和删除操作系统处理流程

class ShoppingCart(object):
totalInventory=10
callbacks=[]
carts={} def register(self,callback):
self.callbacks.append(callback) def moveItemToCart(self,session):
if session in self.carts:
return
self.carts[session]=True
self.notifyCallbacks() def removeItemFromCart(self,session):
if session not in self.carts:
return
del(self.carts[session])
self.notifyCallbacks() def notifyCallbacks(self):
for c in self.callbacks:
print "**********"
self.callbackHelper(c)
self.callbacks=[] def callbackHelper(self,callback):
callback(self.getInventoryCount()) def getInventoryCount(self):
return self.totalInventory-len(self.carts)

moveItemToCart方法,添加操作时,将商品唯一标识码放入json串,然后将新库存作为参数,调用所有请求的回调,响应各个请求,并关闭连接。

removeItemFromCart方法,删除操作时,将商品唯一标识码清除,同样调用各回调,通知客户端。

5)客户端长轮询代码如下

$(document).ready(function() {
document.session = $('#session').val(); setTimeout(requestInventory, 100); $('#add-button').click(function(event) {
jQuery.ajax({
url: 'http://localhost:9999/cart',
type: 'POST',
data: {
session: document.session,
action: 'add'
},
dataType: 'json',
beforeSend: function(xhr, settings) {
$(event.target).attr('disabled', 'disabled');
},
success: function(data, status, xhr) {
$('#add-to-cart').hide();
$('#remove-from-cart').show();
$(event.target).removeAttr('disabled');
}
});
}); $('#remove-button').click(function(event) {
jQuery.ajax({
url: 'http://localhost:9999/cart',
type: 'POST',
data: {
session: document.session,
action: 'remove'
},
dataType: 'json',
beforeSend: function(xhr, settings) {
$(event.target).attr('disabled', 'disabled');
},
success: function(data, status, xhr) {
$('#remove-from-cart').hide();
$('#add-to-cart').show();
$(event.target).removeAttr('disabled');
}
});
});
}); function requestInventory() {
jQuery.getJSON('http://localhost/status', {session: document.session},
function(data, status, xhr) {
$('#count').html(data.inventorycount);
setTimeout(requestInventory, 0);
}
);
}

6)运行结果
打开多个客户端,当做添加/删除操作时,可以观察到库存数量会实时变动。

3.长轮询的缺陷
上面有提到过长轮询的优势,经过上面的示例,我们可以明白长轮询存在的一些缺陷。
1)所有客户端请求同时关闭,同时打开,在库存变化的时候,服务器会受到猛烈的攻击
2)长轮询保持了连接请求,很多浏览器限制了对于服务器的并发请求数量,所以一直占用连接,会导致其他的请求如下载受到限制。
3)浏览器请求超时是由浏览器控制的。

参考资料:http://docs.pythontab.com/tornado/introduction-to-tornado/ch5.html

tornado长轮询的更多相关文章

  1. Tornado长轮询和WebSocket

    Http协议是一种请求响应式协议, 不允许服务端主动向客户端发送信息. 短轮询是一种简单的实现服务端推送消息的解决方案, 客户端以一定间隔自动向服务端发送刷新请求, 服务端返回要推送的消息作为响应. ...

  2. tornado 10 长轮询和 websocket

    tornado 10 长轮询和 websocket 一.长轮询 #在网页,我们经常扫码登录,那么问题来了,前端是如何知道用户在手机上扫码登录的呢 这里就需要用到长轮询 #长轮询 #客户端能够不断地向服 ...

  3. http长轮询&短轮询

    http 协议介绍: http 协议是请求/响应范式的, 每一个 http 响应都是由一个对应的 http 请求产生的; http 协议是无状态的, 多个 http 请求之间是没有关系的. http ...

  4. 三周,用长轮询实现Chat并迁移到Azure测试

    公司的OA从零开始进行开发,继简单的单点登陆.角色与权限.消息中间件之后,轮到在线即时通信的模块需要我独立去完成.这三周除了逛网店见爱*看动漫接兼职,基本上都花在这上面了.简单地说就是用MVC4基于长 ...

  5. 用.NET MVC实现长轮询,与jQuery.AJAX即时双向通信

    两周前用长轮询做了一个Chat,并移植到了Azure,还写了篇博客http://www.cnblogs.com/indream/p/3187540.html,让大家帮忙测试. 首先感谢300位注册用户 ...

  6. 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室

    实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...

  7. 网页实时聊天之js和jQuery实现ajax长轮询

    众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息. 一直以来的方式 ...

  8. 误人子弟的网络,谈谈HTTP协议中的短轮询、长轮询、长连接和短连接

    引言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码.在研究一个项目的时候,源码里面用到了HTTP的长轮询.由于之前没太接触过,因此LZ便趁着这个机会,好好了解了一下HT ...

  9. Comet 反Ajax: jQuery与PHP实现Ajax长轮询

    原文地址(http://justcode.ikeepstudying.com/2016/08/comet-%E5%8F%8Dajax-%E5%9F%BA%E4%BA%8Ejquery%E4%B8%8E ...

随机推荐

  1. MySQL中SYSDATE()和NOW()函数的区别和联系

    MySQL中有5个函数需要计算当前时间的值: NOW.返回时间,格式如:2012-09-23 06:48:28 CURDATE,返回时间的日期,格式如:2012-09-23 CURTIME,返回时间, ...

  2. easyui 隔行渐变色属性设置

    1.部分JS文件 function getAgencyDealTable(begin,end,regionFlag,agencyId){ $('#reportList').datagrid({ idF ...

  3. 突破技术管理,IT人中年危机变契机

    突破技术管理,IT人中年危机变契机 中生代技术 Yesterday 作为一个老技术人,今天不聊技术,就聊点技术人员职业发展的事情:对技术管理岗位的认知,比如技术总监. 先贴一张技术人员职业发展路线图, ...

  4. iOS开源项目:DYNavigationController

    DYNavigationController是一个实现了左右滑动导航的项目. https://github.com/dyang/DYNavigationController 首先用之前的跟视图初始化D ...

  5. iOS:网络编程的第三方框架:AFNetworking、SDWebImage

    网络编程第三方框架:AFNetworking.SDWebImage 介绍:这些框架是开源的,经过前人的封装.改进,成为使用次数很多的一个性能好的源代码框架,只需要将它导入项目中,就可以使用.因此,在做 ...

  6. UVA 11107(Life Forms-后缀数组+二分)

    Problem C: Life Forms You may have wondered why most extraterrestrial life forms resemble humans, di ...

  7. dedecms织梦 v5.6 两处跨站漏洞

    漏洞版本: dedecms织梦 v5.6 漏洞描述: DedeCMS内容管理系统软件采用XML名字空间风格核心模板:模板全部使用文件形式保存,对用户设计模板.网站升级转移均提供很大的便利,健壮的模板标 ...

  8. 智能化的命令行工具-betty

    本文首先公布在 CSDN的文章编辑器实在太烂了,建议大家用Cmd Markdown.它不但支持markdown.还支持VIM模式. 智能化的命令行工具-betty betty tool command ...

  9. (C++)函数参数传递中的一级指针和二级指针

    主要内容: 1.一级指针和二级指针 2.函数指针传递的例子 3.什么时候需要传递二级指针? 4.二级指针在链表中的使用 1.一级指针和二级指针 一级指针:即我们一般说的指针,就是内存地址: 二级指针: ...

  10. C++ 11 - STL - 函数对象(Function Object) (上)

    1. 定义 在STL中,可以把函数传递给算法,也可以把函数对象传递给算法. 那么,什么是函数对象呢? 我们来看下它的声明: class X { public: // define function c ...