第一部分:Twisted理論基礎

来源:https://www.cnblogs.com/uuser-ren/archive/2018/12/19/10145128.html
-Advertisement-
Play Games

前言: 最近有人在Twisted郵件列表中提出諸如”為任務緊急的人提供一份Twisted介紹”的的需求。值得提前透露的是,這個序列並不會如他們所願.尤其是介紹Twisted框架和基於Python 的非同步編程而言,可能短時間無法講清楚。因此,如果你時間緊急,這恐怕不是你想找的資料。 我相信如果對非同步編 ...


前言:

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

 

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

 

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

 

模型:

為了更好的理解非同步編程模型的特點,我們來回顧一下兩個大家都熟悉的模型。在闡述過程中,我們假設一個包含三個相互獨立任務的程式。在此,除了規定這些任務都要完成自己工作外,我們先不作具體的解釋,後面我們會慢慢具體瞭解它們。請註意:在此我用“任務”這個詞,這意味著它需要完成一些事情。

 

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

第一部分:Twisted理論基礎

1 同步模型

 

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

下麵我們來呈現第二個模型,如圖2所示:

 

第一部分:Twisted理論基礎

2 線程模型

在這個模型中,每個任務都在單獨的線程中完成。這些線程都是由操作系統來管理,若在多處理機、多核處理機的系統中可能會相互獨立的運行,若在單處理機上,則會交錯運行。關鍵點在於,線上程模式中,具體哪個任務執行由操作系統來處理。但編程人員則只需簡單地認為:它們的指令流是相互獨立且可以並行執行。雖然,從圖示看起來很簡單,實際上多線程編程是很麻煩的,你想啊,任務之間的要通信就要是線程之間的通信。線程間的通信那不是一般的複雜。什麼郵箱、通道、共用記憶體、、、 唉:(

一些程式用多處理機而不是多線程來實現並行運算。雖然具體的編程細節是不同的,但對於我們要研究的模型來說是一樣的。

 

下麵我們來介紹一下非同步編程模型,如圖3所示

 

第一部分:Twisted理論基礎

3 非同步模型

 

在這個模型中,任務是交錯完成,值得註意的是:這是在單線程的控制下。這要比多線程模型簡單多了,因為編程人員總可以認為只有一個任務在執行,而其它的在停止狀態。雖然在單處理機系統中,線程也是像圖3那樣交替進行。但作為程式員在使用多線程時,仍然需要使用圖2而不是圖3的來思考問題,以防止程式在挪到多處理機的系統上無法正常運行(考慮到相容性)。間單線程的非同步程式不管是在單處理機還是在多處理機上都 能很好的運行。

 

在非同步編程模型與多線程模型之間還有一個不同:在多線程程式中,對於停止某個線程啟動另外一個線程,其決定權並不在程式員手裡而在操作系統那裡,因此,程式員在編寫程式過程中必須要假設在任何時候一個線程都有可能被停止而啟動另外一個線程。相反,在非同步模型中,一個任務要想運行必須顯式放棄當前運行的任務的控制權。這也是相比多線程模型來說,最簡潔的地方。

值得註意的是:將非同步編程模型與同步模型混合在同一個系統中是可以的。但在介紹中的絕大多數時候,我們只研究在單個線程中的非同步編程模型。

 

動機

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

 

因此,就要問了,為什麼還要使用非同步模型呢? 在這兒,我們至少有兩個原因。首先,如果有一到兩個任務需要完成面向人的介面,如果交替執行這些任務,系統在保持對用戶響應的同時在後臺執行其它的任務。因此,雖然後臺的任務可能不會運行的更快,但這樣的系統可能會歡迎的多。

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

第一部分:Twisted理論基礎

4 同步模型中出現阻塞

在圖4中,灰色的部分代表這段時間某個任務被阻塞。為什麼要阻塞一個任務呢?最直接的原因就是等待I/O的完成:傳輸數據或來自某個外部設備。一個典型的CPU處理數據的能力是硬碟或網路的幾個數量級的倍數。因此,一個需要進行大I/O操作的同步程式需要花費大量的時間等待硬碟或網路將數據準備好。正是由於這個原因,同步程式也被稱作為阻塞程式。

 

從圖4中可以看出,一個可阻塞的程式,看起來與圖3描述的非同步程式有點像。這不是個巧合。非同步程式背後的最主要的特點就在於,當出現一個任務像在同步程式一樣出現阻塞時,會讓其它可以執行的任務繼續執行,而不會像同步程式中那樣全部阻塞掉。因此一個非同步程式只有在沒有任務可執行時才會出現“阻塞”,這也是為什麼非同步程式被稱為非阻塞程式的原因。

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

 

與同步模型相比,非同步模型的優勢在如下情況下會得到發揮:

 

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

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

3.任務之間相互獨立,以至於任務內部的交互很少。

 

這些條件大多在CS模式中的網路比較繁忙伺服器端出現(如WEB伺服器)。每個任務代表一個客戶端進行接收請求並回覆的I/O操作。客戶的請求(相當於讀操作)都是相互獨立的。因此一個網路服務是非同步模型的典型代表,這也是為什麼twisted是第一個也是最棒的網路庫。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本節內容主要介紹了C語言程式的基本數據類型。介紹了基本類型的整數類型和浮點類型,以及簡單的講解了void類型。整數類型又包括int型、char型、bool型,浮點類型又包括單精度浮點數(float)和雙精度浮點數(double)。 ...
  • Python學習心得——模塊的導入 在Python語言的編輯器里,除了預設的內置函數外,其他函數的調用,必須先通過import語句將其導入才能使用。 import語句導入整個函數模塊 導入方法: import 函數模塊名 示例 新建一個名為 func_test.py 的文件,內容為: 保存並退出,在 ...
  • 前言 本篇主要講述是Java中JDK1.8的一些新語法特性使用,主要是Lambda、Stream和LocalDate日期的一些使用講解。 Lambda Lambda介紹 Lambda 表達式(lambda expression)是一個匿名函數,Lambda表達式基於數學中的λ演算得名,直接對應於其中 ...
  • 1.變數名 命名規則: 在名稱中只能使用字母字元、數字和下劃線; 名稱的第一個字元不能是數字; 不能將C++關鍵詞用作名稱。 常用的首碼:n-整數,str/sz-字元串,b-布爾值,p-指針,c-單個字元,m-類成員值 2.整形 short 至少16位; int至少與short一樣長; long至少 ...
  • 1.文件讀模式 r f = open("helloworld", 'r', encoding="utf-8") 文件句柄: "helloworld" 表示讀的文件的文件名, 'r' 代表讀模式, encoding="utf-8" 表示字元編碼形式為utf-8。 有open就有close,不管是讀文件 ...
  • Python基礎知識(37):訪問資料庫(Ⅱ) 因臨近考試,本人即將進入複習階段,從明天12月19號至2019年的1月二十多號暫停更新 二、MySQL MySQL是Web世界中使用最廣泛的資料庫伺服器。SQLite的特點是輕量級、可嵌入,但不能承受高併發訪問,適合桌面和移動應用。而MySQL是為服務 ...
  • 在我們的世界中事物和事物之間總會有一些聯繫. 在面向對象中. 類和類之間也可以產生相關的關係 1. 依賴關係 執行某個動作的時候. 需要xxx來幫助你完成這個操作. 此時的關係是最輕的. 隨時可以更換另外一個東西來完成此操作 2. 關聯關係 在對象裡面埋對象 1. 一對一關係 2. 一對多關係 類中 ...
  • 本文說明瞭如何定製化JHipster-Registry,增加消息匯流排功能。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...