继续笔记下关于tornado async一些学习知识:
Tornado支持long-polling,在其提供的demo中推荐参考的例子就是那个chat demo,我这里参考chat demo,提供一个简单的long-polling测试应用“用于统计当前在线人数,并保持最新数据至各个客户端的同步更新”。
1. 通过URL加一个参数name来模拟在线用户。
2. Ajax long polling 不只是server端的轮询,client端也需要保持一种请求轮询状态,因为当前的大多数web server都不支持基于单向的HTTP链接的双向通信,我们可以通过websockets,但是这个将HTTP转换成其他形式的协议的操作,目前大多数的浏览器并没有广泛支持,我们可以联想到HTML5 Websockets。我们可以用一种long-lived 链接方式(tornado支持的),用于server和client端之间的数据传输, 类似push-pull的方式,我觉得。
3. 这次的测试,暂没有提供基于重写on_connection_close来处理offline的用户(直接关闭浏览器),所以用户统计的数量只会随着访问数量的增加而增加
Comet
我的测试代码,目前使用的是tornado 1.2.1
Server端:
import os
import string
import time
import logging
from datetime import datetime
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
from tornado.options import define, options
define("port", default=8888, help="run on the given port", type=int)
online = []
count = 0
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.user = self.get_argument("name", None)
self.render("templates/stack_p312a.html", title="Online number testing", c_time=datetime.now(), user=self.user)
class LongPollingHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
global online, count
self.user = self.get_argument("name", None)
if self.user not in online:
logging.info("user : " + self.user)
online.append(self.user)
http = tornado.httpclient.AsyncHTTPClient()
appURL = self.request.protocol + "://" + self.request.host
http.fetch(appURL + "/internal-polling", self._on_finish)
'''push to the client'''
def _on_finish(self, response):
if self.request.connection.stream.closed():
return
self.write("welcome %s, current online number(s) %s" % (self.user, response.body))
self.finish()
'''
def on_connection_close(self):
TODO, testing
'''
class InternalPollingHandler(tornado.web.RequestHandler):
'''
The internal polling for the new online member which will be counted into
the global online list, and then asynchronously push the latest data to the connected client,keep in a long-polling status.
'''
def get(self):
global online, count
logging.info("count : " + str(count))
logging.info("online : " + str(len(online)))
if count != len(online):
count += 1
self.get()
else:
self.write(str(count))
def main():
tornado.options.parse_command_line()
settings = {
"static_path": os.path.join(os.path.dirname(__file__), "static"),
}
application = tornado.web.Application([
(r"/", MainHandler),
(r"/long-polling", LongPollingHandler),
(r"/internal-polling", InternalPollingHandler),
], **settings
)
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
Client端(stack_p312a.html):
<html>
<head>
<title>{{ title }}</title>
<script type="text/javascript" language="JavaScript" src="{{ static_url("jquery-1.5.1.min.js")}}"></script>
<script type='text/javascript' language='JavaScript'>
function test(){
window.setTimeout(function(){
$.ajax({
url : '/long-polling?name={{ user }}',
success : function(data){
$("#num").text(data);
}
});
test();
}, 5000);
}
</script>
</head>
<body>
Current time is {{c_time}}
<br>
<input type="button" value="Test" onclick="test();"/>
<div id="num"></div>
</body>
</html>
简单说明:
1.
通过简单的提供
global online = []
global count = 0
用于用户在线用户的统计
2.
http://localhost:8888/?name=a
http://localhost:8888/?name=b
通过不同的name来模拟各个用户
-----------------------------------------------
对于on_connection_close,the select()-base implements of IOLoop (non-Linux systems) 相关的实现是在tornado 1.2下有修补一些问题,详细可以参考
changelist :
https://github.com/facebook/tornado/commit/1221865747ecfde69a0463b9a0d77b3c5b87f320
但是根据Ben Darnell的建议,并没有在windows下测试过,目前还在学习、讨论中。
-----------------------------------------------
在使用tornado async时一些体验:
1. self.render(), self.redirect()其中已经包含了self.finish()操作,我们在写相关的async callback时候,需要注意这个,不应重复使用self.finish()
2. RequestHandler.async_callback 这个方法从1.1版本开始已经废除,类似代码(下面)应该不再使用,可以通过AsyncHTTPClient来实现异步请求
@tornado.web.asynchronous
def get(self):
...
self.check_for_last_numbers(callback=self.async_callback(self.on_finish))
...
def check_for_last_numbers(self, callback):
...
3. self.finish(),self.flush() 可以“简单的理解”为一种server端的push操作,但是实际实现中,建议使用self.finish(),tornado可以基于之前的cursor、session(secure cookie)来重用之前的connection。
笔记先分享到这里,欢迎大家讨论,共同学习
分享到:
相关推荐
NULL 博文链接:https://jxee.iteye.com/blog/1608820
跨平台 Python 异步聊天机器人框架 - Asynchronous multi-platf-nonebot2
A-Designer-s-Guide-to-Asynchronous-VLSI
xapp523-lvds-4x-asynchronous-oversampling
徐聪-Asynchronous Federated Optimization1
swift开发、iOS、macOS、iphone、后台、第2版本
异步时钟设计,解决亚稳态,异步FIFO读写等。
基于Verilog设计的异步FIFO,有效防止速率不匹配造成的数据丢失,文件中包含源码以及testbench,且有注释,可读性强
可实现异步调用子程序,跨线程访问控件,实现同步调用
The Task-based Asynchronous Pattern (TAP) is a new pattern for asynchrony in the .NET Framework. It is based on the Task and Task<TResult> types in the System.Threading.Tasks namespace, which are used...
TA-JS-asynchronous-js-TJaaao
将异步电机等效为直流电机,即将定转子解耦的同步旋转模型
026-asynchronous-native-java-calls-spring
[TakeLionOS汇编与C语言自学笔记-第五课] 版权所有 2021年 江志剑 按照《21天学通C语言》(第七版),有如下二个例子。 一个例子输出一段话,另一个例子计算年份: //1、files:hello1.c hello1no.s hello1.exe #...
按照《21天学通C语言》(第七版),有如下二个例子。其中一个改为输出红心符号,是练习题6修改一下的: //1、files:hello.c hello.i hello.s hellono.s hello.exe #include int main(void) { printf("Hello, ...
[TakeLionOS汇编与C语言自学笔记-第三课] 版权所有 2021年 江志剑 按照《21天学通C语言》(第七版),有如下二个修改版的例子。其中一个改为输出黑桃符号,其中一个改为输出红心符号,是练习题6修改一下的: //1、...
[TakeLionOS汇编与C语言自学笔记-第四课] 版权所有 2021年 江志剑 按照《21天学通C语言》(第七版),有如下二个例子。其中一个改为输出黑桃符号,是练习题3修改一下的: //1、files:helloxy.c helloxy.i ...
[TakeLionOS汇编与C语言自学笔记-第六课] 版权所有 2021年 江志剑 按照《21天学通C语言》(第七版),有如下一个例子P17。 将整个程序的代码,包括行号显示出来: //1、files:hellolistit.c hellolistitno.s ...
Pika是AMQP 0-9-1协议的纯Python实现,包括RabbitMQ的扩展。新增功能接受用于处理消息的回调。 原始邮件将消息写入日志文件。 处理并记录连接到发布者时的错误。 记录读取的消息数和处理失败的消息数。 添加班级...
The Task-based Asynchronous Pattern