def asynchronous(method):
"""Wrap request handler methods with this if they are asynchronous.
If this decorator is given, the response is not finished when the
method returns. It is up to the request handler to call self.finish()
to finish the HTTP request. Without this decorator, the request is
automatically finished when the get() or post() method returns.
class MyRequestHandler(web.RequestHandler):
@web.asynchronous
def get(self):
http = httpclient.AsyncHTTPClient()
http.fetch("http://friendfeed.com/", self._on_download)
def _on_download(self, response):
self.write("Downloaded!")
self.finish()
"""
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
if self.application._wsgi:
raise Exception("@asynchronous is not supported for WSGI apps")
self._auto_finish = False
return method(self, *args, **kwargs)
return wrapper
web.py
Tornado的web框架核心文件
Application
函数说明
init:
接受一个setting字典参数,里边包括gzip,ui_modules,ui_methods,static_path等一系列参数。并调用_load_ui_modules和_load_ui_methods去加载一些ui资源。此外还会调用self.add_handlers去加载handlers.
add_handlers:
这里的host_pattern为
.*?
.将regex和相应的handler_class封装
URLSpec
对象,将其添加到handlers中.call:
获取请求host的handlers list.
将handler初始化为RequestHandler
RequestHandler调用_execute.
RequestHandler
支持的http方法有"GET", "HEAD", "POST", "DELETE", "PUT"这几种
函数说明
init:
声明self.application和self.request,调用self.clear方法
_execute:
如果请求方法不在定义之内,返回405错误。调用self.prepare()方法,这个方法是在handler之前调用的。
调用handler中复写的http方法,最后调用finish方法。
write
如果传入的是字典,encode为json对象
将需要返回的chunk内容加入到self._write_buffer中。
finish
判断status_code和etag以及其他一些列参数。如果http request中带有connection,将绑定在IOStream上的callback清除即可
调用
self.flush
方法,调用self.request.finish()。flush
将self._write_buffer拼接成字符串
判断reuqest请求方法, 调用requests的write方法:
通过代码分析
流程图
异步模块asynchronous
代码很简短,直接贴上来
这里文档也说的很清楚,如果没有加装饰器,当get或者post方法返回时,
http requests
就直接执行并返回。当加上装饰器后,就需要结合上面的_execute
方法来进行判断了,这里关键就是加上了一行self._auto_finish = False。这里有一个判断,当
self._auto_finish
为False的时候,是不执行self.finish()的,所以这里的这个连接会一直打开,除非我们自己去调用self.finish()这个方法。 这里的finish方法前面没有细写,这里剖析一下。finish方法调用self.request.finish(), 跟进到request里面看,requests调用self._finish_request(), 最后执行这里就是将这个socket的文件描述符重新设置为读事件, 就是初始化到一开始的状态。 用例子说明一下这里支持异步的真正含义。
假设我们要去请求十个url,并将其结果返回给客户端,同步的写法是这样:
如果我们不加这个asynchronous装饰器的话,直接用AsyncHTTPClient去请求的话,代码如下:
这里会报错
assert not self._finished
,如果不加装饰器,使用异步lib的进行write的话,当回调完成后,连接却关闭了,无法继续write。正确的写法应该是:
由于这里的代码是异步的,不会直接返回,所以http method不会阻塞整个ioloop,不影响其他的连接。