常見併發服務器方案

1. 循環式/迭代式服務器
1)短連接(如果是長連接則需要在read與write之間增加一個循環,那樣的話外層循環無法退出,接收不到其它連接請求,即只能服務一個客戶端);

2)單線程,無法充分利用多核CPU;

3)不適合執行時間較長的服務(encode->compute->decode執行時間過長會影響其他客戶端連接的響應速度)。

 
2. 併發式(concurrent)服務器
1)長連接;

2)one connection per process(主進程每次fork 後要關閉connfd,子進程要關閉listenfd),one connection per thread(線程間共享文件描述符,因此不用也不能關閉socket,否則會影響主線程的監聽和子線程與客戶端之間的通信);

3)適合執行時間較長的服務。

 

3. pre-fork or pre-threaded(UNP chapter27)
1)預先創建進程/線程;

2)可以提高連接的響應速度;

3)當多個子進程阻塞於accept時,若有一個客戶端連接請求到來,則多個子進程都會被觸發,但只有一個accept有成功返回,這種現象稱爲“驚羣”。

 


4. 反應式服務器(reactor模式)
1)select/poll/epoll;

2)併發處理多個請求,實際上是在一個線程中完成的,無法充分利用多核CPU(單線程輪詢);

3)不適合執行時間較長的服務(爲了讓客戶端感覺是在“併發”處理而不是“循環”處理,每個請求必須在相對較短時間內執行)。

 


5. reactor + thread per request(過渡方案)

6. reactor + worker thread(過渡方案)
每個連接都在一個工作線程中完成,能充分利用多核CPU。

 
7. reactor + threadpool(能適應密集計算)
第五、第六種方法的改進。

muduo庫的/example/suduku/中有一個reactor + threadpool的例子,因爲數獨求解是計算密集型任務。

在實踐中,爲了使reactor能快速返回事件循環中去響應請求,經常將讀到的數據put到一個環形內存隊列(一般內存or共享內存),而threadpool的線程則從這個環形內存隊列中讀取數據進行計算。

 

8. multiple reactors(能適應更大的突發I/O請求)
1)reactors in threads(one loop per thread) Memcached就是這種模型,一個主線程,多個工作線程,主線程reactor負責接收客戶端連接,每個線程有各自的reactor負責執行任務隊列中的任務。

2)reactors in processes;

3)round robin(輪叫);

4)一般來說一個subReactor適用於一個千兆網口。

 

9. multiple reactors + threadpoll(one loop per thread + threadpool) (能適應突發I/O與密集計算)
Muduo庫主推的一種併發服務器模型!!!

多個subReactor共享一個線程池。

 

10. proactor服務器(proactor模式,基於異步I/O)
1)理論上proactor比reactor效率要高一些;

2)異步I/O能夠讓I/O操作與計算重疊,充分利用DMA特性;

3)Linux異步I/O:

         glibc aio (aio_*),有bug;

         kernel native aio (io_*),也不完美。目前僅支持O_DIRECT方式來對磁盤讀寫,跳過系統緩存。要自己實現緩存,難度不小。

4)boost asio實現的proactor,實際上不是真正意義上的異步I/O,底層是用epoll來實現的,模擬異步I/O。

 

多種併發服務器之間的對比

 

發佈了19 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章