服務端一般須要支持高併發業務訪問,如何設計優秀的服務端網絡IO工做線程/進程模型對業務的高併發訪問需求起着相當重要的核心做用。mysql
本文總結了了不一樣場景下的多種網絡IO線程/進程模型,並給出了各類模型的優缺點及其性能優化方法,很是適合服務端開發、中間件開發、數據庫開發等開發人員借鑑。nginx
(順便提一下,OPPO互聯網文檔數據庫團隊急缺mongodb內核及存儲引擎研發人才,歡迎加入oppo參與千萬級峯值tps/萬億級數據量數據庫研發。聯繫人:yangyazhou#oppo.com)git
說明:github
一個完整的請求處理過程主要包含如下幾個部分:web
步驟1:經過epoll_wait一次性獲取網絡IO事件redis
步驟2:讀取數據及協議解析sql
步驟3:解析成功後進行業務邏輯處理,而後應答客戶端mongodb
while (1) { //epoll_wait等待網絡事件,若是有網絡事件則返回,或者超時範圍 size_t numevents= epoll_wait(); //遍歷前面epoll獲取到的網絡事件,執行對應事件回調 for (j = 0; j < numevents; j++) { if(讀事件) { //讀數據 readData() //解析 parseData() //讀事件處理、讀到數據後的業務邏輯處理 requestDeal() } else if(寫事件) { //寫事件處理,寫數據邏輯處理 writeEentDeal() } else { //異常事件處理 errorDeal() } } }
說明:後續多線程/進程模型中,每一個線程/進程的主流程和該while()流程一致。數據庫
因爲以前工做須要,須要對redis內核作二次優化開發,所以對整個redis代碼作了部分代碼註釋,同時把redis的網絡模塊獨立出來作成了簡單demo,該demo對理解epoll網絡事件處理及Io複用實現會有幫助,代碼比較簡短,能夠參考以下項目:apache
該線程模型圖以下圖所示:
說明:
memcache緩存,適用於內部處理比較快的緩存場景、代理中間場景。memcache源碼實現中文分析能夠詳見: memcache源碼實現分析
該模型原型圖以下:
說明:
reuseport支持後,內核經過負載均衡的方式分發不一樣新連接到多個用戶態worker進程/線程,每一個進程/線程經過IO複用方式處理多個客戶端新連接fd的數據讀寫、報文解析、解析後的業務邏輯處理。每一個工做進程/線程同時處理多個連接的請求,若是某個連接的報文接收解析完畢後的內部處理時間過長,則其餘連接的請求就會阻塞排隊。
該模型雖然解決了listener單點瓶頸問題,可是工做線程內部的排隊問題沒有解決。
不過,Nginx做爲七層轉發代理,因爲都是內存處理,因此內部處理時間比較短,因此適用於該模型。
另,參考nginx源碼中文註釋分析
該線程模型圖以下圖:
說明:
該線程模型圖以下圖所示:
說明:
T1:調用底層asio庫接收一個完整mongodb報文的時間
T2:接收到報文後的後續全部處理(含報文解析、認證、引擎層處理、發送數據給客戶端等)
T3: 線程等待數據的時間(例如:長時間沒有流量,則如今等待讀取數據)
線程運行總時間=T1 + T2 +T3,其中T3是無用等待時間。若是T3的無用等待時間佔比很大,則說明線程比較空閒。工做線程每一次循環處理後判斷有效時間佔比,若是小於指定閥值,則本身直接exit退出銷燬
控制線程專門用於判斷線程池中工做線程的壓力狀況,以此來決定是否在線程池中建立新的工做線程來提高性能。
控制線程每過必定時間循環檢查線程池中的線程壓力狀態,實現原理就是簡單的實時記錄線程池中的線程當前運行狀況,爲如下兩類計數:總線程數_threadsRunning、當前正在運行task任務的線程數_threadsInUse。若是_threadsRunning=_threadsRunning,說明全部工做線程當前都在處理task任務,線程池中線程壓力大,這時候控制線程就開始增長線程池中線程數。
該模型詳細源碼實現過程更多細節咱們以前發佈的文章:MongoDB網絡傳輸處理源碼實現及性能調優——體驗內核性能極致設計
mongodb動態adaptive線程模型,適用於請求處理比較耗時的場景,如數據庫服務。
該模型詳細源碼優化分析實現過程參考:
Mongodb網絡傳輸處理源碼實現及性能調優-體驗內核性能極致設計
該線程模型圖以下:
說明:
把一個全局隊列拆分爲多個隊列,任務入隊的時候按照hash散列到各自的隊列,工做線程獲取獲取任務的時候,同理經過hash的方式去對應的隊列獲取任務,經過這種方式減小鎖競爭,同時提高總體性能。
OPPO自研mongodb內核多隊列adaptive線程模型優化,性能有很好的提高,適用於請求處理比較耗時的場景,如數據庫服務。
該模型詳細源碼優化分析實現過程一樣參考:Mongodb網絡傳輸處理源碼實現及性能調優-體驗內核性能極致設計
答:實際上全部服務均可以利用這一特性,包括數據庫服務(mongodb、mysql等)。可是由於數據庫服務訪問時延通常都是ms級別,若是reuseport特性利用起來,時延會有幾十us的性能提高,這相比數據庫內部處理的ms級時延,這幾十us的性能提高,基本上能夠忽略掉,這也是大部分數據庫服務沒有支持該功能的緣由。
緩存,代理等中間件,因爲自己內部處理時間就比較小,也是us級別,因此須要充分利用該特性。