1. 程式人生 > 程式設計 >深入瞭解Netty【五】執行緒模型

深入瞭解Netty【五】執行緒模型


引言

不同的執行緒模型對程式的效能有很大的影響,Netty是建立在Reactor模型的基礎上,要搞清Netty的執行緒模型,需要了解一目前常見執行緒模型的一些概念。 具體是程式還是執行緒,是和平臺或者程式語言相關,本文為了描述方便,以執行緒描述。 目前存在的執行緒模型有:

  • 傳統阻塞IO服務模型
  • Reactor模型
  • Proactor模型

1、傳統阻塞IO服務模型

傳統阻塞IO服務模型.png

採用阻塞IO模型獲取輸入的資料。 每個連線需要獨立的完成資料的輸入,業務的處理,資料返回。 當併發數大的時候,會建立大量的執行緒,佔用系統資源,如果連線建立後,當前執行緒沒有資料可讀,會阻塞,造成執行緒資源浪費。

2、Reactor模型

IO多路複用 執行緒池 = Reactor模型

Reactor.png

根據Reactor的數量和處理執行緒的數量,Reactor模型分為三類:

  • 單Reactor單執行緒
  • 單Reactor多執行緒
  • 主從Reactor多執行緒

下面分別描述。

2.1、單Reactor單執行緒

單Reactor單執行緒.png
圖中:

  • Reactor中的select模組就是IO多路複用模型中的選擇器,可以通過一個阻塞物件監聽多路連線請求。
  • Reactor物件通過Select監控客戶端請求事件,收到事件後,通過Dispatch進行分發。
  • 如果是建立連線事件,則用Acceptor通過Accept處理連線請求,然後建立一個Handler物件,處理連線完成後的業務處理。
  • 如果不是建立連線事件,則Reactor會分發呼叫連線對應的Handler處理。
  • Handler會處理Read-業務-Send流程。

這種模型,在客戶端數量過多時,會無法支撐。因為只有一個執行緒,無法發揮多核CPU效能,且Handler處理某個連線的業務時,服務端無法處理其他連線事件。 以前在學習Redis原理的時候,發現它內部就是這種模型:深入瞭解Redis【十二】Reactor事件模型在Redis中的應用

2.2、單Reactor多執行緒

單Reactor多執行緒.png

圖中多執行緒體現在兩個部分:

  • Reactor主執行緒 Reactor通過select監聽客戶請求,如果是連線請求事件,則由Acceptor處理連線,如果是其他請求,則由dispatch找到對應的Handler,這裡的Handler只負責響應事件,讀取和響應,會將具體的業務處理交由Worker執行緒池處理。
  • Worker執行緒池 Worker執行緒池會分配獨立執行緒完成真正的業務,並將結果返回給Handler,Handler收到響應後,通過send將結果返回給客戶端。

這裡Reactor處理所有的事件監聽和響應,高併發情景下容易出現效能瓶頸。

2.3、主從Reactor多執行緒

主從Reactor多執行緒.png

這種模式是對單Reactor的改進,由原來單Reactor改成了Reactor主執行緒與Reactor子執行緒。

  • Reactor主執行緒的MainReactor物件通過select監聽連線事件,收到事件後,通過Acceptor處理連線事件。
  • 當Acceptor處理完連線事件之後,MainReactor將連線分配給SubReactor。
  • SubReactor將連線加入到連線佇列進行監聽,並建立handler進行事件處理。
  • 當有新的事件發生時,SubReactor就會呼叫對應的handler處理。
  • handler通過read讀取資料,交由Worker執行緒池處理業務。
  • Worker執行緒池分配執行緒處理完資料後,將結果返回給handler。
  • handler收到返回的資料後,通過send將結果返回給客戶端。
  • MainReactor可以對應多個SubReactor。

這種優點多多,各個模組各司其職,缺點就是實現複雜。

3、Proactor模型

Proactor.png

Proactor模型在理論上是比Reactor模型效能更好,但是因為依賴於作業系統的非阻塞非同步模型,而linux的非阻塞非同步模型還不完善,所以還是以Reactor為主。

總結

在學習這一部分知識的時候,想到redis中Reactor的應用,又想到了以前分析Tomcat原始碼時,其內部就是這種Reactor的思想。 突然感覺被我發現了一個天大的祕密:技術原理是通用的!

參考

Netty 系列之 Netty 執行緒模型 理解高效能網路模型

tencent.jpg