最近打算清理掉之前的博客。寫一些關於twisted的框架的文章,twisted是python優秀,成熟,廣泛使用的非同步網路框架;打算從網路基礎開始寫起,到例子,到源碼分析,爭取對twisted有個比較清晰的認識,自己也能再次從中有所收穫。最近比較忙,有空就更新。這是第一篇,想到哪裡寫哪裡,最後再整理
最近打算清理掉之前的博客。寫一些關於twisted的框架的文章,twisted是python優秀,成熟,廣泛使用的非同步網路框架;打算從網路基礎開始寫起,到例子,到源碼分析,爭取對twisted有個比較清晰的認識,自己也能再次從中有所收穫。最近比較忙,有空就更新。這是第一篇,想到哪裡寫哪裡,最後再整理。
官網:https://twistedmatrix.com/trac/
What is Twisted?
Twisted is an event-driven networking engine written in Python and licensed under the open source MIT license. Twisted runs on Python 2 and an ever growing subset also works with Python 3.
twisted是python實現的基於事件驅動的非同步網路通信構架。可以在官網上線上瀏覽twisted的源碼,也有svn可以自行下載,源碼還是比較清晰易懂的。接下來的代碼或者例子,文檔很多都來源於官網介紹。
第一個問題是為什麼項目叫twisted? 我的理解是由於構成twisted的主要構件deferred list, 有兩個回調鏈,如圖所示,回調鏈每一項包含一個(callback,errback)對。twisted按照回調鏈從第一個callback開始執行,如果出錯執行下一個回調函數對應的errback,如果執行成功,再回到下下個callback繼續執行。是不是很twisted?
第二個問題是什麼是基於事件驅動的非同步網路框架?
我們寫過網路通信程式的都熟悉socket, 都知道select/poll/epoll這些網路多路復用程式,都對應著讀或者寫操作,twisted的構成中包含一個reacotor的東東,就是很多非同步事件框架都有的概念反應堆模式,這是個單例模式,同一時間內只有一個reactor在運行。reactor.run(), 我們說的基於事件就是這樣的一個事件迴圈,twisted等待事件就緒,然後調用回調函數,返回結果。當然它是基於select/poll/epoll的輸入輸出(讀、寫)事件。
關於反應堆模式: 請移步這裡,這個大牛的翻譯:http://www.cnblogs.com/pugang/p/4621373.html
那麼什麼又是非同步? 同樣的,我們知道網路通信有幾個模式,在各種面試中也或有問到,關於同步,非同步,阻塞,非阻塞的區別。
關於這個解釋的文章很多,權威的請參考《unix網路編程》中關於unix網路i/o模式的描述。說說我自己的理解,在Linux中所有都是文件,socket當然也是,網路i/o是i/o的一種嘛。我們的應用程式也要包含兩部分的內容,一個是用戶態一個是內核態的內核調用。網路i/o包含了兩部分的內容:
1. 應用程式陷入內核態等待數據就緒
2. 將數據從內核空間複製到用戶空間。
阻塞就是在這兩個階段都在等待,都被block了,一直等待內核的返回。
非阻塞就是我們熟悉的socket.setblocking(0),或者fnctl設置的非阻塞flag;它只是在第二個階段阻塞了,在一個階段,應用程式知道數據未準備好後,立刻返回錯誤碼EAGAIN/EWOULDBLOCK,知道數據準備結束,複製完畢後返回。
同步指的是等待I/O操作的完成。
非同步指的是不必等待I/O操作完成,直接返回,等到第二階段完成後,內核主動通知進程結束。
所以你說區別,我覺得就是阻塞/非阻塞對應的是一個當前的一個狀態,同步/非同步著眼於整個大局或操作。
我們今天是要說事件驅動的,前面說了我們依賴於select/poll/epoll,他們都是網路多路復用i/o,用了它們不需要再建多線程,線程池這些東西就能同時監控多個fd。有人叫它們非同步(同步)非阻塞I/0, 但是從實際上來說,他們也是同步阻塞的,select/poll/epoll阻塞在select(), epoll.wait()這些函數中,等到數據就緒,然後開始第一個階段,然後第二個階段,在第二個階段中也是I/O阻塞的嘛,所以說它們阻塞在了兩個地方,而且需要等待I/O操作的完成。那到底有沒有非同步I/O,非同步I/O需要操作系統底層的支持,目前好像還沒有滿意的非同步I/O,有一些實現也是基於線程/線程池模擬實現。
那twisted既然用到了select/poll/epoll,它為什麼叫基於事件的非同步框架。因為它模式了非同步I/O,它使用reactor模式處理事件迴圈,使用deferred處理回調函數,用戶可以自己寫一個回調函數,然後放到deferred list中,twsited會在事件通知就緒後調用這些回調函數,執行完畢,返回結果。看,是不是非同步I/O。其它的一些基於事件的非同步框架,像java的netty也是這樣模擬的。
今天寫到這裡,下一篇準備分析select/epoll這些多路復用I/O,再從socket/epoll的例子入手,開始twisted的講解。有錯誤之處,敬請指正,共同學習。