关于tornado内部实现原理

首先,咱们了解到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()函数开始了服务器的总体运做。 好的,今天就先分析这点内容,给你们,也给本身再次消化的时间。

相关文章
相关标签/搜索