博客 / 詳情

返回

7種常見網絡併發模型介紹

概述

對於網絡服務器後端開發,為滿足不同併發場景的需要,一般來説,不外乎幾種常見的併發模型,除了一些教學場景常用的單線程、多進程(線程)的服務器實現外,生產用的服務器,一般都會考慮使用IO多路複用模型。

而常見的IO多路複用場景 ,可以設計得很簡單,也可以設計得比較複雜,一般根據業務需要而定。本文總結了一些比較常見的服務器併發模型,基本涵蓋了 大部分業務場景 。在實際業務開發的技術選型時,可根據場景,選取一款穩定、可靠的網絡模型,還是十分關鍵的。

模型一: 單線程Accept(無IO複用 )

在這裏插入圖片描述

模型分析

  • 主線程main thread執行阻塞accept, 每次客户端connect連接過來,main thread中accept響應並建立連接
  • 創建連接成功,得到connect fd套接字後,依然在main thread串行處理套接字讀寫,並處理業務
  • 在處理業務時,如果有新客户端connect過來,server無響應,直到當前socket全部業務處理完畢(結束while循環)
  • 當前客户端處理完畢之後,關閉連接,處理下一個客户端請求

優缺點

優點

  • socket編程流程清晰且簡單,適合學習使用,瞭解socket基本編程流程

缺點

  • 該模型並非併發模型 ,是串行服務器,同一時刻,監聽並響應的最大網絡請求量為1, 即併發量為1
  • 僅適學習基本socket編程,不適合任何服務器server構建

模型二: 單線程 Accept + 多線程讀寫業務(無 IO 複用)

在這裏插入圖片描述

模型分析

  • 主線程main thread阻塞在accept, 每次客户端 connect連接過來,main thread中accept響應並建立連接
  • 創建連接成功,得到connect fd套接字後,創建一個新的線程thread來處理客户端的讀寫業務,mian thread依然回到accept阻塞等待新客户端
  • thread通過套接字connect fd與客户端進行讀寫操作
  • server在處理業務時,如果有新的客户端連接過來,main thread中accept依然可以響應並建立連接,重複上述過程

優缺點

優點

  • 基於模型1的優化,支持了併發的特性
  • 使用比較靈活,一個客户端對應一個線程單獨處理,server處理業務的內聚性比較高, 客户端無論如何讀寫 ,服務端 均會有一個 線程做資源響應

缺點

  • 隨着客户端梳理增多,需要開闢的線程數量也增加了,和server線程的數量是1:1的關係,因此對於高併發場景,線程數量受到硬件的瓶頸,線程過多也會 增加CPU的切換成本,降低CPU利用率
  • 對於長連接,客户端一旦無業務讀寫,只要不關閉,server就應該對保持這個連接的狀態(心跳檢查,健康檢查機制),佔用連接資源和線程的開銷
  • 僅適合客户端數量不大的場景,且可控的場景來使用
  • 該模型僅適合學習基本的socket編程,不適合做併發服務器

模型三: 單線程多路IO複用

在這裏插入圖片描述

模型分析

  • 主線程main thread創建listen fd之後,採用多路IO複用機制(如select、epoll)進行IO狀態阻塞監控,有client連接請求,IO 複用機制檢測到listen fd觸發讀事件,則進行accept建立連接,並將新生成的connect fd加入到監聽IO集合中
  • client再次進行正常讀寫業務請求,main thread的多路IO複用機制阻塞返回,會觸發該套接字 的讀寫事件等
  • 對於client的讀寫業務,server依然在main thread執行流程繼續執行 ,此時如果有新的客户端connect請求過來,server將沒有即時響應
  • 等到server處理完一個連接的讀寫操作,繼續回到多路IO複用機制阻塞,其他連接過來才可以正常執行

優缺點

優點

  • 單流程體解決了可以同時監聽多個客户端讀寫狀態模型,不需要1:1客户端的線程數量關係
  • 多路IO複用機制 是阻塞的,非忙輪詢的狀態,不會浪費CPU資源,對CPU的利用率較高
  • 對於連接數較多,但是併發不大的場景,或對實時性沒有特別嚴格的場景,該模型已經足夠使用

缺點

  • 雖然可以監聽讀個客户端的讀寫狀態,但是同一時間內,只能夠處理一個客户端的讀寫操作,實際上讀寫業務併發為1
  • 當多個客户端訪問server,業務是串行執行,大量請求的會有排隊延遲現象。

模型四:單線程多路IO複用 + 多線程讀寫業務 (業務工作池)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1jEzEboN-1683502674351)(常見IO多路複用併發 模型介紹.assets/image-20230507101910587.png)]

模型分析

  • 主線程main thread 創建listen fd後,採用多路IO複用機制(如select、epoll)進行IO狀態阻塞監控,有client客户端connect請求 ,IO複用機制檢測到listenfd觸發讀事件,則進行accept建立連接,並將新生成的connect fd加入到監聽IO集合中
  • 當connect fd有 可讀消息,觸發讀時間,並進行讀寫消息
  • main thread按照固定協議讀取消息,並且交給worker pool工作線程池,工作線程池在server啓動之前就已經開啓固定數量的thread,裏面的線程只處理消息 業務,不進行套接字讀寫操作
  • 工作池處理完業務,觸發connect fd寫事件,將回執客户端的消息通過main thread寫給對方
  • 即:main thread只處理IO阻塞監聽以及具體的讀寫操作,讀寫到的數據交給具體的線程池處理,讓main thread專注於處理IO事件
  • 類似於Redis的處理機制

優缺點

優點

  • 將業務處理的部分,通過工作池分離出來,能夠減少客户端訪問server導致業務串行執行會有大量請求排隊的延遲時間
  • 實際上讀寫的業務併發為1,但是業務流程的併發為線程池數量,加快了業務處理的並行效率

缺點

  • 讀寫依然是main thread單獨處理,最高的讀寫並行通道依然是1
  • 雖然多個worker thread處理業務,最後返回給client依舊也需要排隊,因為出口還是main thread的一個通道

模型五:單線程IO複用 + 多線程IO複用

在這裏插入圖片描述

模型分析

  • server在 啓動監聽前,開闢固定數量 (N)的 線程,用thread poll線程池管理
  • 主線程main thread創建listen fd之後,採用IO多路複用機制(如select、epoll)進行IO狀態阻塞監控 ,有 client 連接請求,IO複用機制 檢測到listen fd觸發讀事件,則進行accept建立連接 ,並將新生成的connect fd分發給thread pool中的某個線程進行監聽
  • thread pool中的每個thread都啓動IO多路複用機制 ,用來監聽main thread建立成功並且分發下來的connect fd的讀寫事件,處理對應的讀寫業務,並將處理完的結果通過該thread自己的IO多路複用機制回執給客户端

優缺點

優點

  • 將之前的main thread單流程的讀寫,分散到多線程來完成,這樣就增加了同一時刻 讀寫的並行通道,並行通道的數量N,N 就是線程池的數量
  • server同時監聽connect fd的數量,幾乎是成倍增加,之前的全部監控數量取決於main thread的多路IO複用機制的最大限制,所以理論上單點server最高響應併發數量應該是之前的N倍(N是 線程池數量,建議線程數量和 CPU核心數1:1)
  • 如果良好的 線程池數量可CPU核心數適配,那麼可以嘗試將CPU 與thread綁定,從而降低CPU的切換頻率,提高每個thread處理合理業務的效率,降低CPU的切換成本
  • memchached的併發模型與該模型比較類似

缺點

  • 雖然監聽的併發數量提升,但是最高的讀寫並行通道依然為N,並且多個身處於同一個thread的客户端,會出現讀寫排隊現象,實際上每個thread模型與單線程IO多路複用機制是一致的

模型六: 單進程IO 複用 + 多進程IO複用

在這裏插入圖片描述

模型分析

  • 與單線程IO複用+ 多線程IO 複用(線程池)無太大差異
  • 不同點

    • 進程和線程的內存佈局不同,導致main process(主進程)不再進行accept操作,而是將accept過分散到各個子進程中
    • 進程的特性,資源獨立,所以main process如果accept成功的fd,其他進程無法資源共享,所以需要各個進程自行accept創建連接
    • main process 只是監聽listen fd的狀態,一旦觸發讀事件(有新連接請求),通過一些IPC (進程間通信,如信號、共享內存、管道等),讓各自子進程process競爭accpet完成連接建立,並各自監聽

優缺點

  • 與單線程IO複用+ 多線程IO 複用(線程池)無太大差異
  • 不同點:

    • 多進程內存資源空間佔用稍微大一些
    • 多進程模型安全穩定性較強,這也是各自進程互不干擾的特點導致
    • 實際上每個子進程process都是一個單線程IO多路複用模型

模型七: 單線程IO複用+ 多線程IO複用+ 多線程

在這裏插入圖片描述

模型分析

  • server在啓動監聽之前,開闢固定數量(N)的線程,用thread pool線程池管理
  • 主線程main thread創建listen fd之後,採用IO多路複用機制(如select、epoll)進行IO狀態阻塞監控 ,有 client 連接請求,IO複用機制 檢測到listen fd觸發讀事件,則進行accept建立連接 ,並將新生成的connect fd分發給thread pool中的某個線程進行監聽
  • thread pool中的每個thread都啓動IO多路複用機制 ,用來監聽main thread建立成功並且分發下來的connect fd的讀寫事件,一旦有某個connect fd的讀寫事件被觸發,立即開闢一個新的 線程開處理IO讀寫業務
  • 當某個線程處理完當前的讀寫業務,如果當前connect fd沒有被關閉,那麼將當前fd重新加回到thread pool的IO複用集合,並將自身線程銷燬

優缺點

優點

  • 除了能夠保證同時響應最高的併發數,又能夠解決讀寫並行通道的侷限問題
  • 同一時刻讀寫並行通道,達到最大化極限,一個客户端可以對應一個單獨的執行流程處理讀寫業務

缺點

  • 該模型過於理想化,要求CPU核心數足夠大
  • 如果硬件CPU數量有限,那麼該模型就造成大量CPU切換的成本浪費。
  • 實際開發中,幾乎用不到如此複雜的網絡模型,當前流行的開源網絡組件中,也沒有哪一款軟件做到了如此複雜的程度

本專欄知識點是通過<零聲教育>的系統學習,進行梳理總結寫下文章,對C/C++課程感興趣的讀者,可以點擊鏈接,查看詳細的服務:C/C++Linux服務器開發/高級架構師

user avatar carlos0321 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.