物聯網高併發編程之網絡編程中的線程模型

如需瞭解更多物聯網網絡編程知識請點擊:物聯網雲端開發武器庫php


物聯網高併發編程之網絡編程中的線程模型

值得說明的是,具體選擇線程仍是進程,更可能是與平臺及編程語言相關。

例如 C 語言使用線程和進程均可以(例如 Nginx 使用進程,Memcached 使用線程),Java 語言通常使用線程(例如 Netty),爲了描述方便,下面都使用線程來進行描述。

編程

線程模型1:傳統阻塞 I/O 服務模型

特色:

緩存

  • 1)採用阻塞式 I/O 模型獲取輸入數據;
  • 2)每一個鏈接都須要獨立的線程完成數據輸入,業務處理,數據返回的完整操做。

存在問題:服務器

  • 1)當併發數較大時,須要建立大量線程來處理鏈接,系統資源佔用較大;
  • 2)鏈接創建後,若是當前線程暫時沒有數據可讀,則線程就阻塞在 Read 操做上,形成線程資源浪費。

線程模型2:Reactor 模式

基本介紹

針對傳統阻塞 I/O 服務模型的 2 個缺點,比較常見的有以下解決方案: 網絡

  • 1)基於 I/O 複用模型:多個鏈接共用一個阻塞對象,應用程序只須要在一個阻塞對象上等待,無需阻塞等待全部鏈接。當某條鏈接有新的數據能夠處理時,操做系統通知應用程序,線程從阻塞狀態返回,開始進行業務處理;
  • 2)基於線程池複用線程資源:沒必要再爲每一個鏈接建立線程,將鏈接完成後的業務處理任務分配給線程進行處理,一個線程能夠處理多個鏈接的業務。

Reactor 模式,是指經過一個或多個輸入同時傳遞給服務處理器的服務請求的事件驅動處理模式。 

服務端程序處理傳入多路請求,並將它們同步分派給請求對應的處理線程,Reactor 模式也叫 Dispatcher 模式。

即 I/O 多了複用統一監聽事件,收到事件後分發(Dispatch 給某進程),是編寫高性能網絡服務器的必備技術之一。




Reactor 模式中有 2 個關鍵組成:

多線程

  • 1)Reactor:Reactor 在一個單獨的線程中運行,負責監聽和分發事件,分發給適當的處理程序來對 IO 事件作出反應。 它就像公司的電話接線員,它接聽來自客戶的電話並將線路轉移到適當的聯繫人;
  • 2)Handlers:處理程序執行 I/O 事件要完成的實際事件,相似於客戶想要與之交談的公司中的實際官員。Reactor 經過調度適當的處理程序來響應 I/O 事件,處理程序執行非阻塞操做。

根據 Reactor 的數量和處理資源池線程的數量不一樣,有 3 種典型的實現:併發

  • 1)單 Reactor 單線程;
  • 2)單 Reactor 多線程;
  • 3)主從 Reactor 多線程。

單 Reactor 單線程

其中,Select 是前面 I/O 複用模型介紹的標準網絡編程 API,能夠實現應用程序經過一個阻塞對象監聽多路鏈接請求,其餘方案示意圖相似。

方案說明:

異步

  • 1)Reactor 對象經過 Select 監控客戶端請求事件,收到事件後經過 Dispatch 進行分發;
  • 2)若是是創建鏈接請求事件,則由 Acceptor 經過 Accept 處理鏈接請求,而後建立一個 Handler 對象處理鏈接完成後的後續業務處理;
  • 3)若是不是創建鏈接事件,則 Reactor 會分發調用鏈接對應的 Handler 來響應;
  • 4)Handler 會完成 Read→業務處理→Send 的完整業務流程。

優勢:模型簡單,沒有多線程、進程通訊、競爭的問題,所有都在一個線程中完成。
缺點:性能問題,只有一個線程,沒法徹底發揮多核 CPU 的性能。Handler 在處理某個鏈接上的業務時,整個進程沒法處理其餘鏈接事件,很容易致使性能瓶頸。編程語言

可靠性問題,線程意外跑飛,或者進入死循環,會致使整個系統通訊模塊不可用,不能接收和處理外部消息,形成節點故障。函數

使用場景:客戶端的數量有限,業務處理很是快速,好比 Redis,業務處理的時間複雜度 O(1)。

單 Reactor 多線程

方案說明:

  • 1)Reactor 對象經過 Select 監控客戶端請求事件,收到事件後經過 Dispatch 進行分發;
  • 2)若是是創建鏈接請求事件,則由 Acceptor 經過 Accept 處理鏈接請求,而後建立一個 Handler 對象處理鏈接完成後續的各類事件;
  • 3)若是不是創建鏈接事件,則 Reactor 會分發調用鏈接對應的 Handler 來響應;
  • 4)Handler 只負責響應事件,不作具體業務處理,經過 Read 讀取數據後,會分發給後面的 Worker 線程池進行業務處理;
  • 5)Worker 線程池會分配獨立的線程完成真正的業務處理,將響應結果發給 Handler 進行處理;
  • 6)Handler 收到響應結果後經過 Send 將響應結果返回給 Client。

優勢:能夠充分利用多核 CPU 的處理能力。
缺點:多線程數據共享和訪問比較複雜;Reactor 承擔全部事件的監聽和響應,在單線程中運行,高併發場景下容易成爲性能瓶頸。

主從 Reactor 多線程

針對單 Reactor 多線程模型中,Reactor 在單線程中運行,高併發場景下容易成爲性能瓶頸,可讓 Reactor 在多線程中運行。

方案說明:

  • 1)Reactor 主線程 MainReactor 對象經過 Select 監控創建鏈接事件,收到事件後經過 Acceptor 接收,處理創建鏈接事件;
  • 2)Acceptor 處理創建鏈接事件後,MainReactor 將鏈接分配 Reactor 子線程給 SubReactor 進行處理;
  • 3)SubReactor 將鏈接加入鏈接隊列進行監聽,並建立一個 Handler 用於處理各類鏈接事件;
  • 4)當有新的事件發生時,SubReactor 會調用鏈接對應的 Handler 進行響應;
  • 5)Handler 經過 Read 讀取數據後,會分發給後面的 Worker 線程池進行業務處理;
  • 6)Worker 線程池會分配獨立的線程完成真正的業務處理,如何將響應結果發給 Handler 進行處理;
  • 7)Handler 收到響應結果後經過 Send 將響應結果返回給 Client。

優勢:父線程與子線程的數據交互簡單職責明確,父線程只須要接收新鏈接,子線程完成後續的業務處理。

父線程與子線程的數據交互簡單,Reactor 主線程只須要把新鏈接傳給子線程,子線程無需返回數據。

這種模型在許多項目中普遍使用,包括 Nginx 主從 Reactor 多進程模型,Memcached 主從多線程,Netty 主從多線程模型的支持。

小結

3 種模式能夠用個比喻來理解:(餐廳經常僱傭接待員負責迎接顧客,當顧客入坐後,侍應生專門爲這張桌子服務)

  • 1)單 Reactor 單線程,接待員和侍應生是同一我的,全程爲顧客服務;
  • 2)單 Reactor 多線程,1 個接待員,多個侍應生,接待員只負責接待;
  • 3)主從 Reactor 多線程,多個接待員,多個侍應生。

Reactor 模式具備以下的優勢:

  • 1)響應快,沒必要爲單個同步時間所阻塞,雖然 Reactor 自己依然是同步的;
  • 2)編程相對簡單,能夠最大程度的避免複雜的多線程及同步問題,而且避免了多線程/進程的切換開銷;
  • 3)可擴展性,能夠方便的經過增長 Reactor 實例個數來充分利用 CPU 資源;
  • 4)可複用性,Reactor 模型自己與具體事件處理邏輯無關,具備很高的複用性。

線程模型2:Proactor 模型

在 Reactor 模式中,Reactor 等待某個事件或者可應用或者操做的狀態發生(好比文件描述符可讀寫,或者是 Socket 可讀寫)。

而後把這個事件傳給事先註冊的 Handler(事件處理函數或者回調函數),由後者來作實際的讀寫操做。

其中的讀寫操做都須要應用程序同步操做,因此 Reactor 是非阻塞同步網絡模型。

若是把 I/O 操做改成異步,即交給操做系統來完成就能進一步提高性能,這就是異步網絡模型 Proactor。

Proactor 是和異步 I/O 相關的,詳細方案以下:

  • 1)Proactor Initiator 建立 Proactor 和 Handler 對象,並將 Proactor 和 Handler 都經過 AsyOptProcessor(Asynchronous Operation Processor)註冊到內核;
  • 2)AsyOptProcessor 處理註冊請求,並處理 I/O 操做;
  • 3)AsyOptProcessor 完成 I/O 操做後通知 Proactor;
  • 4)Proactor 根據不一樣的事件類型回調不一樣的 Handler 進行業務處理;
  • 5)Handler 完成業務處理。

能夠看出 Proactor 和 Reactor 的區別:

  • 1)Reactor 是在事件發生時就通知事先註冊的事件(讀寫在應用程序線程中處理完成);
  • 2)Proactor 是在事件發生時基於異步 I/O 完成讀寫操做(由內核完成),待 I/O 操做完成後纔回調應用程序的處理器來進行業務處理。

理論上 Proactor 比 Reactor 效率更高,異步 I/O 更加充分發揮 DMA(Direct Memory Access,直接內存存取)的優點。

可是Proactor有以下缺點: 

  • 1)編程複雜性,因爲異步操做流程的事件的初始化和事件完成在時間和空間上都是相互分離的,所以開發異步應用程序更加複雜。應用程序還可能由於反向的流控而變得更加難以 Debug;
  • 2)內存使用,緩衝區在讀或寫操做的時間段內必須保持住,可能形成持續的不肯定性,而且每一個併發操做都要求有獨立的緩存,相比 Reactor 模式,在 Socket 已經準備好讀或寫前,是不要求開闢緩存的;
  • 3)操做系統支持,Windows 下經過 IOCP 實現了真正的異步 I/O,而在 Linux 系統下,Linux 2.6 才引入,目前異步 I/O 還不完善。

所以在 Linux 下實現高併發網絡編程都是以 Reactor 模型爲主。

參考:http://www.52im.net/forum.php

相關文章
相關標籤/搜索