線程模型
-
傳統線程模型
采用阻塞IO模型,一個鏈接一個線程問題:
- 當並發過多,創建大量線程會造成資源的大量占用
- 連接建立后,很可能一直阻塞在等待讀和寫的狀態
-
Reactor模型(反應堆模型)/Dispatcher模型(分發模式)
Reactor 模式,是指通過一個或多個輸入同時傳遞給服務處理器的服務請求的事件驅動處理模式。針對第一個問題,我們使用線程池,不是每個連接一個線程,而是在線程建立以后,把業務處理的任務交給線程去處理,這樣一個線程就可以處理多個鏈接的業務了
針對第二個問題,我們使用IO復用模型,多個連接公用一個阻塞對象,IO復用模型,當某個連接有數據可以處理,操作系統會通知應用程序
-
單Reactor單線程
就是一個接待員,一個服務員
優點:簡單,沒有多線程,沒有進程通信
缺點:性能,無法發揮多核的極致,一個handler卡死,導致當前進程無法使用,IO和CPU不匹配
場景:客戶端有限,業務處理快,比如redis
-
單Reactor多線程
就是一個接待員,多個服務員,但是真正的多線程是在Worker中,你可以認為是多個廚師
優點:充分利用的CPU
缺點:進程通信,復雜,Reactor承放了太多業務,高並發下可能成為性能瓶頸
-
主從Reactor多線程
就是多個接待員,多個服務員,多個廚師
主Reactor負責建立連接,建立連接后的句柄丟給子Reactor,子Reactor負責監聽所有事件進行處理
優點:職責明確,分攤壓力
Nginx/netty/memcached都是使用的這
-
-
Proactor 模型(前攝器)
reactor中等待時間發生,然后讓實現准備好的handler去處理,后者來實際讀寫,它是同步非阻塞的線程模型
如果IO改為異步,交給操作系統來完成,則可以進一步提高效率,這就是異步網絡模型,Proactor
Proactor讀寫在內核中完成,Reactor讀寫在Handler里面完成
1)編程復雜性,由於異步操作流程的事件的初始化和事件完成在時間和空間上都是相互分離的,因此開發異步應用程序更加復雜。應用程序還可能因為反向的流控而變得更加難以 Debug;
2)內存使用,緩沖區在讀或寫操作的時間段內必須保持住,可能造成持續的不確定性,並且每個並發操作都要求有獨立的緩存,相比 Reactor 模式,在 Socket 已經准備好讀或寫前,是不要求開辟緩存的;
3)操作系統支持,Windows 下通過 IOCP 實現了真正的異步 I/O,而在 Linux 系統下,Linux 2.6 才引入,目前異步 I/O 還不完善。