深刻了解Netty【五】線程模型


引言

不一樣的線程模型對程序的性能有很大的影響,Netty是創建在Reactor模型的基礎上,要搞清Netty的線程模型,須要瞭解一目前常見線程模型的一些概念。 具體是進程仍是線程,是和平臺或者編程語言相關,本文爲了描述方便,以線程描述。 目前存在的線程模型有:linux

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

一、傳統阻塞IO服務模型

傳統阻塞IO服務模型.png

採用阻塞IO模型獲取輸入的數據。 每一個鏈接須要獨立的完成數據的輸入,業務的處理,數據返回。 當併發數大的時候,會建立大量的線程,佔用系統資源,若是鏈接建立後,當前線程沒有數據可讀,會阻塞,形成線程資源浪費。redis

二、Reactor模型

IO多路複用 線程池 = Reactor模型 Reactor.png編程

根據Reactor的數量和處理線程的數量,Reactor模型分爲三類:網絡

  • 單Reactor單線程
  • 單Reactor多線程
  • 主從Reactor多線程

下面分別描述。多線程

2.一、單Reactor單線程

單Reactor單線程.png 圖中:併發

  • Reactor中的select模塊就是IO多路複用模型中的選擇器,能夠經過一個阻塞對象監聽多路鏈接請求。
  • Reactor對象經過Select監控客戶端請求事件,收到事件後,經過Dispatch進行分發。
  • 若是是創建鏈接事件,則用Acceptor經過Accept處理鏈接請求,而後建立一個Handler對象,處理鏈接完成後的業務處理。
  • 若是不是創建鏈接事件,則Reactor會分發調用鏈接對應的Handler處理。
  • Handler會處理Read-業務-Send流程。

這種模型,在客戶端數量過多時,會沒法支撐。由於只有一個線程,沒法發揮多核CPU性能,且Handler處理某個鏈接的業務時,服務端沒法處理其餘鏈接事件。 之前在學習Redis原理的時候,發現它內部就是這種模型:深刻了解Redis【十二】Reactor事件模型在Redis中的應用異步

2.二、單Reactor多線程

單Reactor多線程.png

圖中多線程體如今兩個部分:編程語言

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

這裏Reactor處理全部的事件監聽和響應,高併發情景下容易出現性能瓶頸。高併發

2.三、主從Reactor多線程

主從Reactor多線程.png

這種模式是對單Reactor的改進,由原來單Reactor改爲了Reactor主線程與Reactor子線程。post

  • Reactor主線程的MainReactor對象經過select監聽鏈接事件,收到事件後,經過Acceptor處理鏈接事件。
  • 當Acceptor處理完鏈接事件以後,MainReactor將鏈接分配給SubReactor。
  • SubReactor將鏈接加入到鏈接隊列進行監聽,並建立handler進行事件處理。
  • 當有新的事件發生時,SubReactor就會調用對應的handler處理。
  • handler經過read讀取數據,交由Worker線程池處理業務。
  • Worker線程池分配線程處理完數據後,將結果返回給handler。
  • handler收到返回的數據後,經過send將結果返回給客戶端。
  • MainReactor能夠對應多個SubReactor。

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

三、Proactor模型

Proactor.png

Proactor模型在理論上是比Reactor模型性能更好,可是由於依賴於操做系統的非阻塞異步模型,而linux的非阻塞異步模型還不完善,因此仍是以Reactor爲主。

總結

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

參考

Netty 系列之 Netty 線程模型 理解高性能網絡模型

tencent.jpg

相關文章
相關標籤/搜索