首先,咱们了解到tornado自己就是一个高并发的异步框架?那么这个高并发和异步应该从哪里看出来呢?咱们应该怎么用咱们本身的模块实现异步呢?好吧,一切始于源,就从入口函数看起吧。python
tornado.options.parse_command_line()
这个不用说你们都知道封装的是哪一块(从sys 得到输入解析参数)。git
app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
关于这个类的具体内容就有的说了,首先进入Application类看看都是什么内容。github
self.wildcard_router = _ApplicationRouter(self, handlers) self.default_router = _ApplicationRouter(self, [ Rule(AnyMatches(), self.wildcard_router)
最关键的内容就是这块了,他会把你匹配到的规则和对应的handlers联系起来。OK,如今把规则联系起来了怎么运行起来呢?这就是接下来的内容了:web
http_server = tornado.httpserver.HTTPServer(app)
好的,进入HTTPServer类里看看到底发生了什么鬼。首先看这一部分:服务器
class HTTPServer(TCPServer, Configurable, httputil.HTTPServerConnectionDelegate):
记住这个类继承了哪些类之后会用到。而后找到入口函数:并发
def __init__(self, *args, **kwargs): # Ignore args to __init__; real initialization belongs in # initialize since we're Configurable. (there's something # weird in initialization order between this class, # Configurable, and TCPServer so we can't leave __init__ out # completely) pass
怎么什么都没有啊?这是怎么回事呢?先接着往下看:app
def initialize(self, request_callback, no_keep_alive=False, io_loop=None, xheaders=False, ssl_options=None, protocol=None, decompress_request=False, chunk_size=None, max_header_size=None, idle_connection_timeout=None, body_timeout=None, max_body_size=None, max_buffer_size=None, trusted_downstream=None): self.request_callback = request_callback self.no_keep_alive = no_keep_alive self.xheaders = xheaders self.protocol = protocol self.conn_params = HTTP1ConnectionParameters( decompress=decompress_request, chunk_size=chunk_size, max_header_size=max_header_size, header_timeout=idle_connection_timeout or 3600, max_body_size=max_body_size, body_timeout=body_timeout, no_keep_alive=no_keep_alive) TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options, max_buffer_size=max_buffer_size, read_chunk_size=chunk_size) self._connections = set() self.trusted_downstream = trusted_downstream
怎么建立server是在这个里面呢?这就用到了继承类里的Configurable,其余的两个继承类看单词就知道什么意思了,之后再具体分析,今天就先具体分析Configurable这个类,那么进入Configurable以后呢:框架
def __new__(cls, *args, **kwargs): base = cls.configurable_base() init_kwargs = {} if cls is base: impl = cls.configured_class() if base.__impl_kwargs: init_kwargs.update(base.__impl_kwargs) else: impl = cls init_kwargs.update(kwargs) instance = super(Configurable, cls).__new__(impl) # initialize vs __init__ chosen for compatibility with AsyncHTTPClient # singleton magic. If we get rid of that we can switch to __init__ # here too. instance.initialize(*args, **init_kwargs) return instance @classmethod def configurable_base(cls): # type: () -> Any # TODO: This class needs https://github.com/python/typing/issues/107 # to be fully typeable. """Returns the base class of a configurable hierarchy. This will normally return the class in which it is defined. (which is *not* necessarily the same as the cls classmethod parameter). """ raise NotImplementedError() @classmethod def configurable_default(cls): # type: () -> type """Returns the implementation class to be used if none is configured.""" raise NotImplementedError() def initialize(self): # type: () -> None """Initialize a `Configurable` subclass instance. Configurable classes should use `initialize` instead of ``__init__``. .. versionchanged:: 4.2 Now accepts positional arguments in addition to keyword arguments. """ @classmethod def configure(cls, impl, **kwargs): # type: (Any, **Any) -> None """Sets the class to use when the base class is instantiated. Keyword arguments will be saved and added to the arguments passed to the constructor. This can be used to set global defaults for some parameters. """ base = cls.configurable_base() if isinstance(impl, (str, unicode_type)): impl = import_object(impl) if impl is not None and not issubclass(impl, cls): raise ValueError("Invalid subclass of %s" % cls) base.__impl_class = impl base.__impl_kwargs = kwargs
看到这里你有没有豁然开朗的感受?反正我是挺兴奋的。原来在继承Configurable类的时候,已经在建立的时候完成了。接下来是什么?异步
tornado.ioloop.IOLoop.instance().start()
这个IOLoop是什么鬼?他是怎么来的呢?请看下面:函数
class IOLoop(Configurable):
@classmethod def configurable_default(cls): if hasattr(select, "epoll"): from tornado.platform.epoll import EPollIOLoop return EPollIOLoop if hasattr(select, "kqueue"): # Python 2.6+ on BSD or Mac from tornado.platform.kqueue import KQueueIOLoop return KQueueIOLoop from tornado.platform.select import SelectIOLoop return SelectIOLoop
原来如此呀,impl = cls.configured_class() impl 在这里就是 epoll ,它的生成函数是 configured_class(), 而其方法里又有 base.__impl_class = cls.configurable_default() ,调用了 configurable_default() 。而 Configurable 的 configurable_default()被IOLoop继承后重载,终于实现了epoll的并发大法。最后调用了thread的start()函数开始了服务器的总体运做。 好的,今天就先分析这点内容,给你们,也给本身再次消化的时间。