memcached採用的網絡模型

memcached採用的網絡模型是早前提到的半同步半異步的網絡模型.

簡 單的說,大致流程就是:主線程負責接收新的連接,接收到新的連接之後,選擇一個worker副線程,將該新連接push到副線程的連接隊列中.主副線程之 間通過管道進行通訊,因此主線程將新的連接push到工作線程之後,主線程要向該副線程的管道中寫一個字符,而每個副線程也都有自己的poll set, 其中會包含自己的管道fd, 副線程也會通過多路複用I/O來監控管道的情況,一旦可讀,說明有新的連接到來,此時從連接隊列中取出新連接,將其fd加入到自身的poll set中,最後對該連接的業務邏輯處理也全都在該副線程中進行(讀數據,處理,發送迴應等).

這個模型有以下的好處:
1) 接收操作只在主循環中處理,因此不會出現驚羣現象.
2) 主副線程分工明確, 主線程僅負責I/O, 副線程負責業務邏輯處理.我認爲這個可以抽象出來作爲一般服務器的網絡I/O架構, 以後要使用的時候只需要將業務邏輯處理函數傳遞進行就好了.簡單的說,就是主線程負責接客,副線程負責服務.
3) 多個副線程之間不會有影響.因爲大家都有各自獨立的連接隊列.主線程在新連接到來的時候是如何選擇處理副線程的呢?很簡單,有一個計數器last_thread, 每次將last_thread加一,再模線程數來選擇線程ID.

缺點是:
假 如業務邏輯是類似於web服務器之類的, 那麼一個簡單的請求也需要這個比較繁瑣的操作的話(最重要的是,很可能一個進程就能處理完的事情,非得從一個線程接收再到另一個線程去處理), 那麼顯然代價是不值得的.所以說,所謂的服務器網絡模型的選擇, 其實沒有一套通吃的方案, 還是按照具體的業務邏輯具體來分析吧.

需要 補充的是,主副線程之間相互通信採用的管道,現在新版的linux內核已經提供一種新的API:eventfd(),簡單的說,有以下好處:1)管道需要 分配兩個fd,一個讀一個寫,而eventfd一個fd就搞定了. 2) 管道需要不定長的緩衝區,往裏面寫數據才能通知讀一端有數據到來,而eventfd現在可以使用定長的數據了. 3) 最後,聽說eventfd性能上比管道要好,這個沒有做過測試了.反正, 對於簡單的類似上面分析的那樣通知機制, 用管道似乎太"重量級"了一點.

eventfd的man page在.




先看下memcahced啓動時線程處理的流程

b58adb92-b5ea-4245-8ba0-50f82522b4e6.jpg

memcached的多線程主要是通過實例化多個libevent實現的,分別是一個主線程和n個workers線程。

無論是主線程還是workers線程全部通過libevent異步事件模型來管理網絡事件,實際上每個線程都是一個單獨的libevent實例。

主線程負責監聽客戶端建立連接的請求,以及accept建立連接;

workers線程負責處理已經建立好的連接的讀寫等事件。

先看一下大致的圖示:

6716d6f5-1ab7-4929-b87d-37350dea1a3e.jpg


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章