Mongodb請求處理流程
Mongodb多存儲引擎支持機制 介紹了Mongodb存儲層創建數據庫、創建集合、插入文檔等數據庫操作接口,本文將介紹mongodb處理客戶端請求的模型。
Mongod在啟動時會調用createServer創建一個PortMessageServer對象,其繼承MessageServer和Listener兩個類,并依賴MyMessageHandler來處理請求。
class PortMessageServer: public MessageServer, public Listener { public: void accepted(boost::shared_ptr<Socket> psocket, long long connectionId ); void setupSockets(); void run(); private: MessageHandler* _handler; };
PortMessageServer
- 調用setupSockets為mongod配置的每個地址創建一個socket,并調用bind綁定地址。
- 調用initAndListen監聽所有的地址,調用select等待監聽fd上發生連接事件,調用accept系統調用接受新的連接請求,并為每個新連接創建一個線程,該線程執行handleIncomingMsg方法,不斷處理該連接上的客戶端請求。
handleIncomingMsg
- 連接建立時,調用MyMessageHander::connected方法,初始化一個新的Client對象,Client對象包含DB操作的上下文。
- 不斷調用recv從連接上讀取請求,當讀取到一個完整請求時,其將請求反序列化為一個Message對象,并調用MyMessageHandler::process方法處理請求,處理完后給客戶端發送應答。
- 連接斷開時,調用MyMessageHander::disconnected方法停止該連接對應的線程,釋放Client對象。
MyMessageHandler::process
調用assembleResponse方法,從Message對象里獲取請求類型( 參考Mongdb協議 ),根據請求類型進行響應的處理。
- 如果為請求dbQuery,調用receivedQuery處理
- 如果為請求dbInsert,調用receivedInsert處理
- 如果為請求dbUpdate,調用receivedUpdate處理
- 如果為請求dbDelete,調用receivedDelete處理
- ......
上述各種請求最終會調用Database類的接口來處理;比如receivedInsert,會先根據Database回去對應的Collection對象,最后調用insertDocument往集合中插入文檔。請求處理完后,給客戶端發送應答消息。
問題分析
select的使用
mongod調用select時,fdset里只會加入監聽fd,而監聽的地址通常很少,故不存在效率問題。
thread per client模型
mongod為每個連接創建一個線程,創建時做了一定優化,將棧空間設置為1M,減少了線程的內存開銷。當線程太多時,線程切換的開銷也會變大,但因為mongdb后端是持久化的存儲,切換開銷相比IO的開銷還是要小得多。
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!