tornado长轮询
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长轮询的更多相关文章
- Tornado长轮询和WebSocket
Http协议是一种请求响应式协议, 不允许服务端主动向客户端发送信息. 短轮询是一种简单的实现服务端推送消息的解决方案, 客户端以一定间隔自动向服务端发送刷新请求, 服务端返回要推送的消息作为响应. ...
- tornado 10 长轮询和 websocket
tornado 10 长轮询和 websocket 一.长轮询 #在网页,我们经常扫码登录,那么问题来了,前端是如何知道用户在手机上扫码登录的呢 这里就需要用到长轮询 #长轮询 #客户端能够不断地向服 ...
- http长轮询&短轮询
http 协议介绍: http 协议是请求/响应范式的, 每一个 http 响应都是由一个对应的 http 请求产生的; http 协议是无状态的, 多个 http 请求之间是没有关系的. http ...
- 三周,用长轮询实现Chat并迁移到Azure测试
公司的OA从零开始进行开发,继简单的单点登陆.角色与权限.消息中间件之后,轮到在线即时通信的模块需要我独立去完成.这三周除了逛网店见爱*看动漫接兼职,基本上都花在这上面了.简单地说就是用MVC4基于长 ...
- 用.NET MVC实现长轮询,与jQuery.AJAX即时双向通信
两周前用长轮询做了一个Chat,并移植到了Azure,还写了篇博客http://www.cnblogs.com/indream/p/3187540.html,让大家帮忙测试. 首先感谢300位注册用户 ...
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...
- 网页实时聊天之js和jQuery实现ajax长轮询
众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息. 一直以来的方式 ...
- 误人子弟的网络,谈谈HTTP协议中的短轮询、长轮询、长连接和短连接
引言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码.在研究一个项目的时候,源码里面用到了HTTP的长轮询.由于之前没太接触过,因此LZ便趁着这个机会,好好了解了一下HT ...
- Comet 反Ajax: jQuery与PHP实现Ajax长轮询
原文地址(http://justcode.ikeepstudying.com/2016/08/comet-%E5%8F%8Dajax-%E5%9F%BA%E4%BA%8Ejquery%E4%B8%8E ...
随机推荐
- WCF 自承载 提供源码
一.WCF 简单介绍 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,是一套通讯接口.现在比较流行的SOA就可以通过WCF实现. ...
- OpenRISC自定义指令GCC修改
This short tutorial shows how to use the custom instructions defined by OpenRISC architecture. The O ...
- C/C++调用java---JNI常用函数
DefineClass jclass DefineClass(JNIEnv *env, jobject loader, const jbyte *buf, jsize bufLen ...
- http://blog.csdn.net/steveguoshao/article/details/38414145
http://blog.csdn.net/steveguoshao/article/details/38414145
- -bash: ./xxx.sh: /bin/bash^M: bad interpreter: No such file or directory
问题的原因是在windows下编辑然后上传到linux系统里执行的..sh文件的格式为dos格式.而linux只能执行格式为unix格式的脚本. 不要使用记事本编辑,使用代码编辑器可以正常执行
- python爬虫模拟登陆
python爬虫模拟登陆 学习了:https://www.cnblogs.com/chenxiaohan/p/7654667.html 用的这个 学习了:https://www.cnblogs.co ...
- 彻底领悟javascript中的exec与match方法
exec是正则表达式的方法,而不是字符串的方法,它的参数才是字符串,如下所示: var re=new RegExp(/\d/); re.exec( "abc4def" ); //或 ...
- sar详解(linux/unix通用)
转载:http://www.toxingwang.com/linux-unix/2027.html sar是linux和unix通用的性能报告工具,常用命令组合如下: sar 命令行的常用格式: sa ...
- gedit如何使用代码片段
gedit的片段插件 1 打开这个插件 2 以HTML为例,我们看到触发器是doctype 3则我在编辑一个HTML文档的时候,先输入doctype,再按Tab键,将会自动提示,我选择即可插入 ...
- poj 3237(树链剖分+线段树)
题意:给一棵树,三种操作.将第i条边的权值改为v,将a到b的路径上的边的权值全部取反,求a到b路径上边的权值的最大值. 思路:明显的树链剖分,加上线段树的操作.因为有取反的操作所以每个区间要记录最大值 ...