開始Tornado的源碼分析之旅

Tornado 是由 Facebook 開源的一個服務器「套裝」,適合於作 python 的 web 或者使用其自己提供的可擴展的功能,完成了不完整的 wsgi 協議,可用於作快速的 web 開發,封裝了 epoll 性能較好。文章主要以分析 tornado 的網絡部分即異步事件處理與上層的 IOstream 類提供的異步IO,其餘的模塊如 web 的 tornado.web 之後慢慢留做分析。html

下面開始咱們的 Tornado 之旅,看源代碼以前一定須要有一份源碼了,你們能夠去官網下載一份。這裏分析的是 3.1.1。python

Tornado 的源碼組織以下:ios

tornado網絡部分最核心的兩個模塊就是ioloop.py與iostream.py,咱們主要分析的就是這兩個部分。web

ioloop.py 主要的是將底層的epoll或者說是其餘的IO多路複用封裝做異步事件來處理。
iostream.py主要是對於下層的異步事件的進一步封裝,爲其封裝了更上一層的buffer(IO)事件。
咱們先來看看 ioloop(文檔地址:http://www.tornadoweb.org/en/stable/ioloop.html):服務器

We use epoll (Linux) or kqueue (BSD and Mac OS X) if they are available, or else we fall back on select(). If you are implementing a system that needs to handle thousands of simultaneous connections, you should use a system that supports either epoll or kqueue.網絡

Example usage for a simple TCP server:異步

import errno
import functools
import ioloop
import socket

def connection_ready(sock, fd, events):
    while True:
        try:
            connection, address = sock.accept()
        except socket.error, e:
            if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN):
                raise
            return
        connection.setblocking(0)
        handle_connection(connection, address)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setblocking(0)
sock.bind(("", port))
sock.listen(128)

# 建立一個ioloop 實例
io_loop = ioloop.IOLoop.instance()
# connection_ready 的第一個參數爲 sock,即 socket 的返回值
callback = functools.partial(connection_ready, sock)
# 註冊函數,第一個參數是將 sock 轉換爲標準的描述符,第二個爲回調函數,第三個是事件類型
io_loop.add_handler(sock.fileno(), callback, io_loop.READ)
io_loop.start()

能夠看到在註釋前都是使用了傳統的建立服務器的方式,不用多介紹,注意就是把套接口設置爲非阻塞方式。socket

建立ioloop實例,這裏是使用了ioloop.IOLoop中的 instance()靜態方法,以 @classmethod 方式包裝。函數

在後面的add_handler中,程序爲咱們的監聽套接口註冊了一個回調函數和一個事件類型。工做方式是這樣,在註冊了相應的事件類型和回調函數之後,程序開始啓動,若是在相應的套接口上有事件發生(註冊的事件類型)那麼調用相應的回調函數。tornado

當監聽套接口有可讀事件發生,意味着來了一個新鏈接,在回調函數中就能夠對這個套接口accept,並調用相應的處理函數,其實應該是處理函數也設置爲異步的,將相應的鏈接套接口也加入到事件循環並註冊相應的回調函數,只是這裏沒有展現出來。

在使用非阻塞方式的accept時候經常返回EAGAIN,EWOULDBLOCK 錯誤,這裏採起的方式是放棄這個鏈接。

轉自:http://www.cnblogs.com/Bozh/

相關文章
相關標籤/搜索