[原]tornado源碼分析系列(一)[tornado簡介]


引言:

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

 

首先說明幾點問題:

(1)文章供大家交流使用,如果有錯誤,發揚開源精神,共同交流

(2)文章不加以說明,均以Linux環境為例

(3)如果有epoll,tornado默認使用epoll,這里就不分析select和KQueue了

(4)請不要再問為什么使用python來作為網絡庫而不是高效的C/C++了,因為對於IO密集型程序來說,上層語言的程序運行差異沒有那么大,而且tornado中使用的epoll部分也是用C來寫的。

 

下面開始我們的tornado之旅,看源代碼之前必定需要有一份源碼了,大家可以去官網下載一份。

一.源碼組織:

  |---__init__.py

   ---auth.py

   ---......

   ---epoll.c

   ---ioloop.py

   ---iostream.py

   ---...

 

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

  ioloop.py 主要的是將底層的epoll或者說是其他的IO多路復用封裝作異步事件來處理

  iostream.py主要是對於下層的異步事件的進一步封裝,為其封裝了更上一層的buffer(IO)事件

 

  很好的一點就是在tornado的源碼中,都提供了一個簡單的Demo,我就以這些Demo為例來講,再多的話也不如看代碼,程序猿最好的交流方式就是看代碼。

  

        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()

可以看到在注釋前都是使用了傳統的創建服務器的方式,不用多介紹,注意就是把套接口設置為非阻塞方式

創建ioloop實例,這里是使用了ioloop.IOLoop中的 instance()靜態方法,以 @classmethod 方式包裝

在后面的add_handler中,程序為我們的監聽套接口注冊了一個回調函數和一個事件類型

工作方式是這樣,在注冊了相應的事件類型和回調函數以后,程序開始啟動,如果在相應的套接口上有事件發生(注冊的事件類型)那么調用相應的回調函數

代碼通俗易懂 

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

在使用非阻塞方式的accept時候常常返回EAGAIN,EWOULDBLOCK 錯誤,這里采取的方式是放棄這個連接。

 

 總結:以這樣的方式開始了源碼分析覺得挺水的,第一篇文章就以短小精干為起點了,廣交志同道合人士。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM