(轉)Twisted :第一部分:初步認識Twisted

前言:程序員

    最近有人在Twisted郵件列表中提出諸如」爲任務緊急的人提供一份Twisted介紹」的的需求。值得提早透露的是,這個序列並不會如他們所願.尤爲是介紹Twisted框架和基於Python 的異步編程而言,可能短期沒法講清楚。所以,若是你時間緊急,這恐怕不是你想找的資料。編程

 

    我相信若是對異步編程模型一無所知,快速的介紹一樣沒法讓你對其有所理解,至少你得稍微懂點基礎知識吧。我已經用Twisted框架幾年了,所以思考過我當初是怎麼學習它(學得很慢)並發現學習它的最大難度並不在Twisted自己,而在於對其模型的理解,只有理解了這個模型,你才能更好去寫和理解異步程序的代碼。大部分Twisted的代碼寫得很清晰,其在線文檔也很是棒(至少在開源軟件這個層次上能夠這麼說)。但若是不理解這個模型,不論是讀Twisted源碼仍是使用Twisted的代碼更或者是相關文檔,你都會感到很是的傷腦筋。服務器

 

    所以,我會用前面幾個部分來介紹這個模型以讓你掌握它的機制,稍後會介紹一下Twisted的特色。實際上,一開始,咱們並不會使用Twisted,相反,會使用簡單的Python來講明一個異步模型是如何工做的。咱們在初次學習Twisted的時,會從你日常都不會直接使用的底層的實現講起。Twisted是一個高度抽象的體系,所以在使用它時,你會體會到其多層次性。但當你去學習尤爲是嘗試着理解它是如何工做時,這種爲抽像而帶來的多層次性會給你帶來極大的理解難度。因此,咱們準備來個從內到外,從低層開始學習它。網絡

 

模型:多線程

    爲了更好的理解異步編程模型的特色,咱們來回顧一下兩個你們都熟悉的模型。在闡述過程當中,咱們假設一個包含三個相互獨立任務的程序。在此,除了規定這些任務都要完成本身工做外,咱們先不做具體的解釋,後面咱們會慢慢具體瞭解它們。請注意:在此我用「任務」這個詞,這意味着它須要完成一些事情。併發

 

第一個模型是單線程的同步模型,如圖1所示:框架

圖1 同步模型異步

 

    這是最簡單的編程方式。在一個時刻,只能有一個任務在執行,而且前一個任務結束後一個任務才能開始。若是任務都能按照事先規定好的順序執行,最後一個任務的完成意味着前面全部的任務都已無任何差錯地完成並輸出其可用的結果—這是多麼簡單的邏輯。異步編程

下面咱們來呈現第二個模型,如圖2所示:性能

 

圖2 線程模型

    在這個模型中,每一個任務都在單獨的線程中完成。這些線程都是由操做系統來管理,若在多處理機、多核處理機的系統中可能會相互獨立的運行,若在單處理機上,則會交錯運行。關鍵點在於,在線程模式中,具體哪一個任務執行由操做系統來處理。但編程人員則只需簡單地認爲:它們的指令流是相互獨立且能夠並行執行。雖然,從圖示看起來很簡單,實際上多線程編程是很麻煩的,你想啊,任務之間的要通訊就要是線程之間的通訊。線程間的通訊那不是通常的複雜。什麼郵箱、通道、共享內存! 唉: 一些程序用多處理機而不是多線程來實現並行運算。雖然具體的編程細節是不一樣的,但對於咱們要研究的模型來講是同樣的。

 

下面咱們來介紹一下異步編程模型,如圖3所示

 

圖3 異步模型

 

    在這個模型中,任務是交錯完成,值得注意的是:這是在單線程的控制下。這要比多線程模型簡單多了,由於編程人員總能夠認爲只有一個任務在執行,而其它的在中止狀態。雖然在單處理機系統中,線程也是像圖3那樣交替進行。但做爲程序員在使用多線程時,仍然須要使用圖2而不是圖3的來思考問題,以防止程序在挪到多處理機的系統上沒法正常運行(考慮到兼容性)。間單線程的異步程序不論是在單處理機仍是在多處理機上都 能很好的運行。

 

    在異步編程模型與多線程模型之間還有一個不一樣:在多線程程序中,對於中止某個線程啓動另一個線程,其決定權並不在程序員手裏而在操做系統那裏,所以,程序員在編寫程序過程當中必需要假設在任什麼時候候一個線程都有可能被中止而啓動另一個線程。相反,在異步模型中,一個任務要想運行必須顯式放棄當前運行的任務的控制權。這也是相比多線程模型來講,最簡潔的地方。

    值得注意的是:將異步編程模型與同步模型混合在同一個系統中是能夠的。但在介紹中的絕大多數時候,咱們只研究在單個線程中的異步編程模型。

 

動機

    咱們已經看到異步編程模型之因此比多線程模型簡單在於其單令流與顯式地放棄對任務的控制權而不是被操做系統隨機地中止。可是異步模型要比同步模型複雜得多。程序員必須將任務組織成序列來交替的小步完成。所以,若其中一個任務用到另一個任務的輸出,則依賴的任務(即接收輸出的任務)須要被設計成爲要接收系列比特或分片而不是一下所有接收。因爲沒有實質上的並行,從咱們的圖中能夠看出,一個異步程序會花費一個同步程序所須要的時間,可能會因爲異步程序的性能問題而花費更長的時間。

 

    所以,就要問了,爲何還要使用異步模型呢? 在這兒,咱們至少有兩個緣由。首先,若是有一到兩個任務須要完成面向人的接口,若是交替執行這些任務,系統在保持對用戶響應的同時在後臺執行其它的任務。所以,雖而後臺的任務可能不會運行的更快,但這樣的系統可能會歡迎的多。

    然而,有一種狀況下,異步模型的性能會高於同步模型,有時甚至會很是突出,即在比較短的時間內完成全部的任務。這種狀況就是任務被強行等待或阻塞,如圖4所示:

圖4 同步模型中出現阻塞

    在圖4中,灰色的部分表明這段時間某個任務被阻塞。爲何要阻塞一個任務呢?最直接的緣由就是等待I/O的完成:傳輸數據或來自某個外部設備。一個典型的CPU處理數據的能力是硬盤或網絡的幾個數量級的倍數。所以,一個須要進行大I/O操做的同步程序須要花費大量的時間等待硬盤或網絡將數據準備好。正是因爲這個緣由,同步程序也被稱做爲阻塞程序。

 

    從圖4中能夠看出,一個可阻塞的程序,看起來與圖3描述的異步程序有點像。這不是個巧合。異步程序背後的最主要的特色就在於,當出現一個任務像在同步程序同樣出現阻塞時,會讓其它能夠執行的任務繼續執行,而不會像同步程序中那樣所有阻塞掉。所以一個異步程序只有在沒有任務可執行時纔會出現「阻塞」,這也是爲何異步程序被稱爲非阻塞程序的緣由。

    任務之間的切換要不是此任務完成,要不就是它被阻塞。因爲大量任務可能會被阻塞,異步程序等待的時間少於同步程序而將這些時間用於其它實時工做的處理(如與人打交道的接口),這樣一來,前者的性能必然要高不少。

 

與同步模型相比,異步模型的優點在以下狀況下會獲得發揮:

 

    1.有大量的任務,所以在一個時刻至少有一個任務要運行

    2.任務執行大量的I/O操做,這樣同步模型就會在由於任務阻塞而浪費大量的時間

    3.任務之間相互獨立,以致於任務內部的交互不多。

 

    這些條件大多在CS模式中的網絡比較繁忙服務器端出現(如WEB服務器)。每一個任務表明一個客戶端進行接收請求並回復的I/O操做。客戶的請求(至關於讀操做)都是相互獨立的。所以一個網絡服務是異步模型的典型表明,這也是爲何twisted是第一個也是最棒的網絡庫。

相關文章
相關標籤/搜索