單伺服器高性能模式
高性能模式涉及磁碟,操作系統,CPU,內存,緩存,網路,編程語言和平台,架構。很具有挑戰性。
高性能架構設計:
提高單伺服器性能,將單機性能發揮到極致
如果單機服務無法支撐,設計集群方案
架構設計決定了性能的上限,實現細節決定了性能的下限。
並發模型:
如何管理連接
如何處理請求
並發模型設計IO模型及進程模型
IO模型:阻塞,非阻塞,非同步,同步
進程模型:單進程,多進程,多線程
PPC
每次有新連接,fork()新的進程來處理連接請求。早期Unix網路模型,實現簡單,適用於連接數不高的場景。
父進程接收連接
父進程「fork」子進程
子進程處理連接的讀寫請求
子進程關閉連接
弊端體現在:
fork代價高,需要分配很多內核資源,還要拷貝父進程的內存映像
父子進程通信複雜,需要IPC來盡心信息傳遞
並發數量有限最大幾百, 如果連接持續時間很長,新連接不斷接入,進程調度和切換越來越高,系統壓力很大
Prefork
prefork採用預先fork,在啟動時就預先創建好進程,然後才開始接受用戶請求,省去了fork的耗時操作。多個進程,accept同一個socket,最終只有一個成功,存在「驚群」現象,即多個子進程都被喚醒去爭取,但只有一個成功,增加了不必要的進程調度和上下文切換。Linux 2.6以後已經解決accept驚群問題。
prefork仍然存在父子進程通信複雜,支持並發數量有限的問題。
TPC
每個新連接都創建一個新線程去處理這個連接的請求,線程比進程輕量級,創建消耗少。多線程共享進程空間,通信更簡單。
父進程接受新連接
創建子線程
子線程處理連接的讀寫數據
子線程關閉連接
註:TPC模式下,子線程不會複製文件描述符,TPP下會複製文件描述符
也有一些缺點:
線程創建仍然有代價
多線程共享進程內存,需要引用互斥,處理不好有死鎖,並發複雜
多線程會相互影響,特殊情況會導致主進程退出,exit,內存越界。
相比TPP,TPC更簡單,但同樣無法TPC也無法承載太多的並發。
Prethread同Prefork,但實現靈活。海量連接都不適合TPC和TPP。
Reactor和Proactor
針對TPC和TPP用完釋放提出資源復用,不為單獨的連接創建單獨的線程或者進程,創建一個進程池,將連接分配給其中一個進程。一個進程也可以處理多個連接。連接沒數據可讀是,會被阻塞到該連接上。將read改為非阻塞的,針對一個進程處理多個連接的話, 採用不斷輪詢,但如果連接數太多,挨個輪詢很消耗CPU,並且效率很低。
IO多路復用:
多連接共用一個阻塞對象,只需要在一個阻塞對象上等待,無需輪序所有連接,epoll,poll,kqueue
某個連接有數據可以處理時,OS通知進程,進程從阻塞態返回,開始業務處理
Reactor就是IO多路復用結合線程池,事件反應,通俗理解是:來了一個事件我就有相應的反應。我就是reactor,根據不同的時間類型,調用不同的邏輯。IO多路復用統一監聽事件,收到事件再Dispatch給某個進程。
Reactor模式的核心組成部分是Reactor和進程或者線程池。Ractor負責事件監聽和分配,線程池負責具體的事件處理。
Reactor有以下實現方式體現在:
Reactor的數量,可以一個或者多個
資源池的數量,一個或者多個
理論上四個組合,但多Reactor,單進程或線程比單Reactor和單進程或線程無性能優勢,還複雜,實際不使用。
資源池是線程還是進程根據具體語言和平台,Nginx多進程,Java多線程,C進程和線程均可。
1.單Reactor和單進程
Reactor監聽事件
是新連接建立,accept處理,創建Handler處理
非連接建立,Reactor直接調用handler處理
Handler完成raead-- 業務處理--send 整個流程
模式簡單,無IPC以及競爭,但無法發揮多核性能,必須等待Handler挨個處理。性能有瓶頸。
2.單Reactor和多線程
主線程Reactor通過select監聽連接接事件,收到後通過dispatch分發
不是連接事件,Acceptor通過Accept接受連接,並創建Handler處理後續連接
不是連接事件,Ractor會調用對應的Handler處理
Handler只負責響應事件,不進行業務處理,read到數據後,發給processor處理
processor在獨立線程中完成真正處理,Handler收到響應後把結果通過send給client
能夠充分利用多核多CPU的處理能力,但多線程數據共享和訪問較複雜,Ractor承擔所有事件的監聽和響應,瞬間高並發存在性能瓶頸。單Ractor多進程,IPC通信複雜,使用不多。
3.多Reactor多線程
mainReactor通過select監聽建立事件,收到事件後通過Acceptor接受,將新的連接分配給某個線程
subReactor將mainRactor分配的連接加入連接隊列,進行監聽,創建Handler用於處理連接的各種事件
新事件發生,subRactor來調用對應的Handler進行相應
Handler完成read-->業務處理-->send的完成業務流程
看起來比單Ractor和多線程池複雜,單實現其實更簡單:
父子進程職責明確,父進程只負責新連接建立,子進程負責後續業務處理
交互簡單,父進程直接把新連接給子進程,無需返回數據
字父進程間的文件連接互相獨立,無需同步共享處理
Proactor
Ractor是非阻塞同步網路模型,read和send都需要用戶進程同步操作。如果將read和send同步操作改為非同步的,就成了非同步網路模型Proactor。
Reactor可以理解為:來了事件通知你,你來處理。Proactor可以理解為:來了事件,我處理好了告訴你。這裡我是指操作系統內核,事件就是新的連接,數據可讀,可寫等I/O事件,你指事件的回調。
理論上Proactor模型比Reactor效率高,非同步性能更高,但系統層面並沒有對非同步的完全支持,Boost.Asio linux下都是用epoll模擬出來的非同步模型。
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
TAG:全球大搜羅 |