并發服務器模型
引子
從09年在企鵝廠實習起開始接觸服務器開發,第一次看到是一份內部的PPT,相較于之前接受的ACM/ICPC算法訓練、工具程序開發、和Visual Studio可視化的GUI開發,有種開天辟地的感覺。
然后接著看UNP(《UNIX Network Programming》),逐步的學到兩點:
1)UNIX系提供的編程接口(帶緩沖的IO、Socket接口、鎖、共享內存);2)并發服務器的設計模式(阻塞/非阻塞、多線程/多進程、select/poll多路復用)。
再來看POSA2(《Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects》),其結合了比GOF更加實際的例子來說明,POSA2給出的例子幾乎都是實際開發中遇得到實實在在的服務器設計問題。GOF也更偏向編程技法,而POSA2更偏向于架構設計。
UNIX系提供的編程接口
從這里開始,接觸到了一個最純粹的操作系統——UNIX:1)面向程序員;2)提供高性能可編程的計算和資源操控(內存、硬盤、網絡)的平臺。
這個系統并不面向:1)GUI界面,2)日常辦公。
它的核心就是:1)計算,2)資源操控。
這對于以一種純凈的方式理解好操作系統非常重要:1)程序員需要什么;2)操作系統提供了什么;3)操作系統為什么這樣設計。從這些接口、操作方式的設計中,我們可以從其中學習到大型系統在設計時候如何做設計權衡(tradeoff&consequence),如何定義設計空間(design space)并在其中調節設計。
并發服務器的設計模式
首先來看UNP中最重要的章節:“第六章:I/O多路復用”。
Unix提供了五種不同的I/O模型,并給出了詳細的配圖:
- 阻塞式I/O模型
- 非阻塞式I/O模型
- I/O復用模型
- 信號驅動式I/O模型
- 異步I/O模型
下面這個圖可以很直觀的說明問題:
再來看UNP中最最重要的章節:“第三十章:服務器程序設計范式”。
UNP列出下面9種服務器范式,代碼主要邏輯也不難,不過首先得理解:阻塞/非阻塞、多線程/多進程、select/poll多路復用。然后再看看直觀的圖解。
- 迭代服務器
- 每個請求fork一個進程
- prefork若干個進程
- prefork對accept加文件鎖
- prefork對accept加線程鎖
- prefork在父進程統一accept傳遞fd
- 每個請求一個thread
- prethread線程,每個線程各自accept,互斥鎖保護
- prethread線程,主線程統一accept傳遞fd
另外,陳碩老師的《Linux 多線程服務端編程:使用muduo C++ 網絡庫》也列出了其他更多服務器范式:
- reactor + thread-per-task
- reactor + worker thread
- reactor + thread poll
- reactors in threads
- reactors in processes
- reactors + thread pool
有哪些可以評價一個并發服務器的指標?
- 吞吐量(Throughput)
- QPS
- 延遲(latency)
- 并發數目(concurrency)