如何理解 tornado 教程

如何理解 Tornado_百度作业帮
如何理解 Tornado
如何理解 Tornado
Tornado就是我们在 FriendFeed 的 Web 服务器及其常用工具的开源版本。Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对epoll的运用,Tornado 每秒可以处理数以千计的连接,因此 Tornado 是实时 Web 服务的一个 理想框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题,请参阅The C10K problem)深入理解yield(三):yield与基于Tornado的异步回调 - 网名还没想好 - 博客园
posts - 254, comments - 29, trackbacks - 0, articles - 2
在&和已经对yield原理及在python中的运用了解了很多,那么接下来就要结合Tornado,进行python异步的分析。
一.异步的实现
异步的实现离不开回调函数,接下来介绍回调函数的概念以及在python中的使用。
软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础,
可以参阅加深理解。
图片来源:/developerworks/cn/linux/l-callback/
有时候对回调这个概念比较模糊,在知乎上,举了一个很好的例子:
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。
下面举一个Python的回调例子
# coding=utf-8
__author__ = 'fang'
def call_back(value):
print 'call back value:', value
def caller(func, arg):
print 'caller'
caller(call_back, 'hello,world')
Tornado异步
tornado提供了一套异步机制,asynchronous装饰器能够使其异步,tornado默认在get()或者post()返回后自动结束HTTP请求(默认在函数处理返回时关闭客户端的连接),当装饰器给定,在函数返回时response不会结束,self.finish()去结束HTTP请求,它的主要工作就是将 RequestHandler 的 _auto_finish 属性置为 false。
如下例子:
#同步阻塞版本
def MainHandler(tornado.web.RequestHandler):
def get(self):
client = tornado.httpclient.HttpClient()
response = client.fetch("/")
self.write('Hello World')
这个例子就不在啰嗦了,整体性能就在于访问google的时间.下面展示异步非阻塞的例子:
def MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
client = tornado.httpclient.AsyncHTTPClient()
def callback(response):
self.write("Hello World")
self.finish()
client.fetch("/", callback)
fetch的时候提供callback函数,这样当fetch http请求完成的时候才会去调用callback,而不会阻塞。callback调用完成之后通过finish结束与client的连接。
这种异步回调的缺点就是:拆分代码逻辑,多重回调的繁琐,能不能有一套方案像正常执行逻辑一样使异步能够顺序化去执行呢?在上面的两节yield的学习中可知:因为yield很方便的提供了一套函数挂起,运行的机制,所以我们能够通过yield来将原本是异步的流程变成同步的。,在tornado中具体表现为tornado.gen.
def MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
client = tornado.httpclient.AsyncHTTPClient()
response = yield tornado.gen.Task(client.fetch, "/")
self.write("Hello World")
self.finish()
使用gen.engine的decorator,该函数主要就是用来管理generator的流程控制。 使用了gen.Task,在gen.Task内部,会生成一个callback函数,传给async fetch,并执行fetch,因为fetch是一个异步操作,所以会很快返回。 在gen.Task返回之后使用yield,挂起 当fetch的callback执行之后,唤醒挂起的流程继续执行.
那么接下来分析gen源码:
def engine(func):
"""Decorator for asynchronous generators.
异步generators装饰器
任何从这个module生产的生成器必须被这个装饰器所装饰。这个装饰器只用于已经是异步的函数
@tornado.web.asynchronous
@tornado.gen.engine
def get(RequestHandler):
#http method.
源码分析:http://blog.xiaogaozi.org//understanding-tornado-dot-gen/
Any generator that yields objects from this module must be wrapped in this decorator.
The decorator only works on functions that are already asynchronous.
For `~tornado.web.RequestHandler```get``/``post``/etc methods, this means that both the `tornado.web.asynchronous` and `tornado.gen.engine` decorators must be used (for proper exception handling, ``asynchronous` should come before ``gen.engine``).
In most other cases, it means that it doesn't make sense to use ``gen.engine`` on functions that
don't already take a callback argument.
@functools.wraps(func)
def wrapper(*args, **kwargs):
runner = None
def handle_exception(typ, value, tb):
# if the function throws an exception before its first "yield"
# (or is not a generator at all), the Runner won't exist yet.
# However, in that case we haven't reached anything asynchronous
# yet, so we can just let the exception propagate.
if runner is not None:
return runner.handle_exception(typ, value, tb)
return False
with ExceptionStackContext(handle_exception) as deactivate:
# 代表被装饰的http method(如get), 因为在之前所装饰的method 包含yield关键字,所以gen = func()是generator
gen = func(*args, **kwargs)
# 检查是否是generator对象
if isinstance(gen, types.GeneratorType):
# 虽然调用了包含yield的http method,但函数并没有立即执行,只是赋值给了gen
# 可想而知Runner()是来启动生成器函数的,包含next(),send(),throw(),close()等方法
runner = Runner(gen, deactivate)
runner.run()
assert gen is None, gen
deactivate()
# no yield, so we're done
return wrapper
了解了gen,接下来我们自己实现一个:
# coding=utf-8
__author__ = 'fang'
import tornado.ioloop
from tornado.httpclient import AsyncHTTPClient
import functools
def task(fun, url):
return functools.partial(fun, url)
def callback(gen, response):
print 'callback:', response
gen.send(response)
except StopIteration:
def sync(func):
def wrapper():
gen = func()
f = gen.next()
print 'aa', f, gen
f(functools.partial(callback, gen))
return wrapper
def fetch():
response = yield task(AsyncHTTPClient().fetch, '')
print response
tornado.ioloop.IOLoop.instance().start()
aa &functools.partial object at 0x10a992fc8& &generator object fetch at 0x10a6e6460&
HTTPResponse(code=200,request_time=0.8711,buffer=&_io.BytesIO object at 0x10a9b9110&......)
HTTPResponse(code=200,request_time=0.8711,buffer=&_io.BytesIO object at 0x10a9b9110&......)tornado 到底是个什么东西呢? 如果它是个webserver ,那么后端如何搭配Django使用 ,又能否搭配Node.js 或 PHP?如果作为web框架,nginx对于她来说意义在哪里? 在实际使用中是否会影响Tornado本身的异步IO设计?Tornado与node.js 的实现的目的 ,和设计方式上的不同之处在哪里 ( 不谈语言 )?----------------------------- 补充:以下是看官方说明和 Google 了一番后的理解:它可以作为一个裸 webserver 来使用 ,就是说它的后端可以运行 Django、web.py。它是一个简单 Python 框架,url 基于正则,有自己的模板实现,但是没有 orm。这部分看起来类似于 web.py。非阻塞异步 IO,类似于 node.js。它的前端可以放 Nginx
,感觉类似于 Nginx、Apache 之于 Tomcat。就是说它作为 web 框架比 Django 简单,又支援异步 IO,且更不需要前端的 webserver ?我已经混乱了, Tornado是 Nginx、Django、Node.js 的结合体?又或是 Nginx * 20% + Django * 40% + Node.js * 40% ?
Tornado 是一个web服务器。django是一个快速web程序编写框架。node.js是一种编程环境。你直接用Tornado 写网站也可以,但是它只有最基本的功能,你写个网站工作量不小,而DJANGO则可以帮助你快速的编写网站程序,而后部署在Tornado 或者其他web服务器上。node.js则是类似PYTHON的一种编程环境,它可以实现很多东西。我认为你要做个网站,真正现实的就是PHP、rails、django,真正重要的快速实现你的想法,性能之类的东西开始并不重要。
Tornado既是一个web server,也是web framework。而它作为web server 采用的是asynchronous IO的网络模型,这是一种很高效的模型。&br&&br&web framework的定义(&a href=&http://wiki.python.org/moin/WebFrameworks& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&wiki.python.org/moin/We&/span&&span class=&invisible&&bFrameworks&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&)&blockquote&A Web framework is a collection of packages or modules which allow developers to write Web applications or services without having to handle such low-level details as protocols, sockets or process/thread management.&/blockquote& Tornado作为web server,提供了web framework的api,可以来直接构建自己的web程序。同时,Tornado支持WSGI ( &a href=&http://www.python.org/dev/peps/pep-0333/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&python.org/dev/peps/pep&/span&&span class=&invisible&&-0333/&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& ),也就是说它可以有能力其它的一些python的框架一起使用,比如django, bottle, flask等。不妨看下bottle在不同server下的性能评测,其中就有tornado( &a href=&http://bottlepy.org/page/_Comparing_HelloWorld_Performance& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&bottlepy.org/page/2009-&/span&&span class=&invisible&&12-19_Comparing_HelloWorld_Performance&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& )。额外说的是,WSGI的框架是不支持异步的,所以如果有异步调用的逻辑的web程序,Tornado也是选择之一。&br&&br&没有使用过Node.js,但官网说:&blockquote&Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. &/blockquote&可以把Node.js理解成基于V8的javascript运行环境或工具包,它属于偏底层的抽象,扩展了javascript写服务端程序的能力。所以基于它也会有不同的web framework。从这个角度来看,Node.js和Tornado其实不在一个层次上。&br&不过相同的是 Node.js 和 Tornado都采用的的单进程单线程异步IO的网络模型。它们都可以写异步非阻塞的程序,不过我觉得因为javascript的语言特性,Node.js对异步回调非阻塞的风格坚持比Tornado更彻底一点。不过通常多进程时,一个进程的短时间阻塞也是可以接受的。&br&&br&使用Nginx是因为一些单进程服务无法利用多核CPU,同时也会有单机的限制,所以通常会在多个服务器启动多个进程实例,使用Nginx在前端作为反向代理服务器来分发web请求,同时负载均衡。Nginx是C写的,有更好的并发性,可配置性,对静态文件也有更好的支持。当然这是Nginx的常用情景,其实也可以直接使用Nginx来构建web应用,可以参考OpenResty项目( &a href=&http://openresty.org/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&openresty.org/&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& )。&br&&br&其实网络模型、web server、web framework是三个不同层次,它们之间并不冲突,是选择的关系。理解前,不妨先理清概念:)
Tornado既是一个web server,也是web framework。而它作为web server 采用的是asynchronous IO的网络模型,这是一种很高效的模型。web framework的定义()A Web framework is a collection of packages or modules which allow develo…
建议楼主阅读一下这篇论文 C10K problem,虽然有点老了&a href=&/c10k.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&/c10k.html&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a& &br&&br&其实,你也可以说nginx是一个framework,不过是针对C的。&br&&br&裸WebServer表示他支持HTTP协议,既然支持HTTP协议,你前面放啥反向都无所谓,nginx apache squid varnish。或者也可以用wsgi模块,只是采用了特殊的通讯协议。&br&&br&为什么要在tornado前面放nginx,原因在于,Python虽然有多线程,但是Python的解释器有GIL
&a href=&http://en.wikipedia.org/wiki/Global_Interpreter_Lock& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&en.wikipedia.org/wiki/G&/span&&span class=&invisible&&lobal_Interpreter_Lock&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& 这点非常影响了Python和Tornado利用多核的能力,所以只能通过多进程来利用多核。既然多进程,一般就需要在前端放置nginx haproxy做为负载均衡的反向代理,或是使用这些应用服务器的wsgi模块来管理进程的生命周期等等。另外对于静态文件的服务,也是nginx之类的更具有优势。(他们直接把请求转发到tornado的进程中,你根本不用管请求怎么来的,专心写你的程序。)&br&&br&其他很多脚本语言的框架都有类似问题,比如ruby,而Nodejs更加是连线程都没有了。&br&&br&Nodejs的核心在于,他使用了JavaScript天生擅长的事件/回调机制来实现异步。&br&Python对于匿名函数和闭包支持不够好,所以Tornado通过了类来和回调方法来实现异步,这里没有事件的概念。(没深入研究过Tornado,大致是这么了解的)&br&另外Tornado封装了很多常用的诸如静态文件处理、Router、模板等等,而Nodejs基本上是一个纯粹的协议框架,这些功能都需要自己去写。Nodejs+Express差不多就可以等于Tornado的功能了。&br&&br&而如果是要做一个中间件或中间层,做一些高级点的协议处理,可能nodejs更加能胜任。&br&在tornado里面去调用用php或者nodejs所开发的服务,这是没问题的,主要要看架构上如何设计。
建议楼主阅读一下这篇论文 C10K problem,虽然有点老了 其实,你也可以说nginx是一个framework,不过是针对C的。裸WebServer表示他支持HTTP协议,既然支持HTTP协议,你前面放啥反向都无所谓,nginx apache squid varnish。或者也可以用w…
《脑神迹背单词PRO》V2.1发布!/Vbesg如何理解Python的web框架tornado文档里面的用户认证的self.current_user?
tornado用户认证:还有:tornado.escape.xhtml_escape和cookie_secret="61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo="
感觉有点难以理解,阅读码源又不知道如何下手…… 求指点哇
按投票排序
1. self.current_user是用来活取get_currrent_user返回的值在tornado的源码中def get_current_user(self):
"""Override to determine the current user from, e.g., a cookie."""
return None
get_current_user一直返回None,如果没有重写它来获得你想要的数据,那么在服务器端的self.current_user就一直是None。例如我们可以在get_current_user中返回cookie来代表用户已经登录过并在浏览器保存了cookie,例如:class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
return self.get_cookie(cookie_name)
class SignInHandler(BaseHandler):
def get(self):
#如果拿到的cookie不为None,表示用户已经登录过
if self.current_user:
self.redirect(your_main_page)
self.render(your_sign_in_page)
2. tornado.escape.xhtml_escape是用来转义一些字符的。Escapes a string so it is valid within HTML or XML.Escapes the characters &, &, ", ', and &. When used in attribute values the escaped strings must be enclosed in quotes.Changed in version 3.2: Added the single quote to the list of escaped characters.在tornado的源码中是用python正则表达式按_XHTML_ESCAPE_DICT = {'&': '&', '&': '&', '&': '&', '"': '&',
'\'': '''}
去替换字符来达到转义效果。3. cookie_secret是当你使用set_secure_cookie或get_secure_cookie时才会用到的,这是官方解释:Cookies are not secure and can easily be modified by clients. If you need to set cookies to, e.g., identify the currently logged in user, you need to sign your cookies to prevent forgery. Tornado supports signed cookies with the
methods. To use these methods, you need to specify a secret key named cookie_secret when you create your application. 我个人的理解cookie_secret会在cookie生成的时候被使用(用于cookie编码),然后cookie_secret就相当于一把钥匙,只有拥有这把钥匙才能得到cookie里面的数据。
你的 RequestHandler 里写一个方法def get_current_user(self):
return "Someone"
只要这里返回的不是 None,@authenticated decorator 就会认为是经过认证的,否则会跳转到 self.settings['login_url'] 去。所以需要做的事情完整起来是三件:实现 login_url 登录流程,将用户名存在 session 中——常见办法是用 set_secure_cookie 把用户名放在 cookie 中。这里你跑不了要做登录验证啊身份管理啊等等等等。在 get_current_user 中,去提取 login_url 保存的这个用户名。如何理解 Tornado_百度知道
如何理解 Tornado
提问者采纳
保护用户在开发和培训方面的投资。已有部分应用程序接口可以利用并附带参考书目。Tornado 结构的专门设计为开发人员和第三方工具厂商提供了一个开放环境, 一套位于主机或目标机上强大的交互式开发工具和使用程序,在68K处理器上上下文切换仅需要3,任务抢占式调度和循环调度。微内核支持实时系统的一系列特征包括多任务,例如系统内容 TornadoTornado代表嵌入实时应用中最新一代的开发和执行环境: (1)Tornado系列工具,所有工具能很方便地同时运行;IP网络协议,很容易增加和交互式开发。VxWorks支持广泛的工业标准如POSIX 1003; (2)VxWorks 系统。 Tornado 包含三个完整的部分,目标和工具管理。VxWorks具备一个高效的微内核.8微秒,开发人员可任意选择多达80种不同的配置,提升了可移植性,完整集的Tornado工具可以使开发人员完全不用考虑与目标连接的策略或目标存储区大小。微内核设计使VxWorks缩减了系统开销并加速了对外部事件的反应, 目标板上高性能可扩展的实时操作系统,系统目标跟踪。Tornado的独特之处在于其所有开发工具能够使用在应用开发的任意阶段以及任何档次的硬件资源上,中断支持. 另外.1b实时扩展。从需要几K字节存储区的嵌入设计到需求更多的操作系统功能的复杂的高端实时应用、串行线,内容从开发环境接口到连接实现。Tornado包括强大的开发和调试工具。中断等待时间少于3微秒。VxWorks 具有可伸缩性,开发人员能按照应用需求分配所需的资源,尤其适用于面对大量问题的嵌入式开发人员; (3)可选用的连接主机和目标机的通讯软件包 如以太网、在线仿真器或ROM仿真器. 这些标准促进多种不同产品间的互用性,而不是为操作系统分配资源。内核的运行非常快速和确定,ANSI C (浮点支持) and TCP&#47,内存使用分析和自动配置。这些工具包括C和C++源码级别的调试器。而且
来自团队:
其他类似问题
为您推荐:
tornado的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁}

我要回帖

更多关于 tornado 异步 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信