Reactor pattern in Tornado

2017-12-18  本文已影响0人  庞贝船长

前言: 在看 tornado v1.0 的服务器部分的源码时,当时傻乎乎的还不懂啥是 reactor 设计模式,看得真心是头痛!那时,只知道一个叫 单例模式的。看来,软件的设计架构还是真心有用的。(这是个套路...)

接下来就简单的分析一下 tornado 中的 reactor pattern, 由于才疏学浅,难免有错,还请指教!
预备知识:知道 socket, epoll 的原理及使用,当然,最好也是看了 tornado 中的服务器部分的源码以及这篇 Reactor: An Object Behavioral Pattern for
Demultiplexing and Dispatching Handles for Synchronous Events

What's Reactor

来自 wikipedia 的简明版:

The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.

一个 Reactor 中通常有几个元素:

来自这篇 Reactor 文章的详细版

The Reactor design pattern handles service requests that are
delivered concurrently to an application by one or more
clients. Each service in an application may consist of
serveral methods and is represented by a separate event handler
that is responsible for dispatching service-specific requests.
Dispatching of event handlers is performed by an initiation
dispatcher, which manages the registered event handlers.
Demultiplexing of service requests is performed by a
synchronous event demultiplexer.

reactor_structure

Reactor structure in Tornado

由上面对 reactor structure 的理解,进一步推理到 Tornado 中:

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

General Collaborations

各模块之间的协作,如下图所示.

reactor_work

请注意上图最左边纵向的字为: INITIALIZATION MODE, EVENT HANDLING MODE. 这意味着可以将这个模式的工作方式分解成这2个小模块来分析.

Initialization Mode

Event Handling Mode

Initialization Mode in Tornado

如下为 tornado v1.0.0 代码

class IOLoop(object):
    ...
    def add_handler(self, fd, handler, events):
        """Registers the given handler to receive the given events for fd."""
        self._handlers[fd] = handler
        self._impl.register(fd, events | self.ERROR)
class IOLoop(object):
    ...
    def start(self):
        """Starts the I/O loop.
        The loop will run until one of the I/O handlers calls stop(), which
        will make the loop stop after the current event iteration completes.
        """
        ...
        while True:
            # Never use an infinite timeout here - it can stall epoll
            poll_timeout = 0.2
            ...
            event_pairs = self._impl.poll(poll_timeout)
            ...
            self._events.update(event_pairs)
            while self._events:
                fd, events = self._events.popitem()
                ...
                    self._handlers[fd](fd, events)
                ...

Event Handling Mode in Tornado

Others

Define the Event Handling Interface

对应 tornado 中 RequestHandler 类的接口实现,有两种方法: 一种是 A single-method interface, 另一种是 A multi-method interface; 而 Tornado 中 RequestHandler 采用的是后种即 A multi-method Interface 的设计方法,因为HTTP/1.1 总共就8种方法: GET HEAD POST OPTIONS PUT DELETE TRACE CONNECT;

class RequestHandler(object):
   ...
   def head(self, *args, **kwargs):
       raise HTTPError(405)

   def get(self, *args, **kwargs):
       raise HTTPError(405)
   ...

Determine the Number of Initiation Dispatchers in an Application

"Many applications can be structured using just one instance of the Reactor pattern. In this case, the Initiation Dispatcher can be implemented as a Singleton".

而 Tornado 中的 IOLoop 就是采用 Singleton 模式的实现;

Reference

See also

上一篇下一篇

猜你喜欢

热点阅读