Mongodb請求處理流程

jopen 9年前發布 | 14K 次閱讀 MongoDB NoSQL數據庫

 

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

  1. 調用setupSockets為mongod配置的每個地址創建一個socket,并調用bind綁定地址。
  2. 調用initAndListen監聽所有的地址,調用select等待監聽fd上發生連接事件,調用accept系統調用接受新的連接請求,并為每個新連接創建一個線程,該線程執行handleIncomingMsg方法,不斷處理該連接上的客戶端請求。

handleIncomingMsg

  1. 連接建立時,調用MyMessageHander::connected方法,初始化一個新的Client對象,Client對象包含DB操作的上下文。
  2. 不斷調用recv從連接上讀取請求,當讀取到一個完整請求時,其將請求反序列化為一個Message對象,并調用MyMessageHandler::process方法處理請求,處理完后給客戶端發送應答。
  3. 連接斷開時,調用MyMessageHander::disconnected方法停止該連接對應的線程,釋放Client對象。

MyMessageHandler::process

調用assembleResponse方法,從Message對象里獲取請求類型( 參考Mongdb協議 ),根據請求類型進行響應的處理。

  1. 如果為請求dbQuery,調用receivedQuery處理
  2. 如果為請求dbInsert,調用receivedInsert處理
  3. 如果為請求dbUpdate,調用receivedUpdate處理
  4. 如果為請求dbDelete,調用receivedDelete處理
  5. ......

上述各種請求最終會調用Database類的接口來處理;比如receivedInsert,會先根據Database回去對應的Collection對象,最后調用insertDocument往集合中插入文檔。請求處理完后,給客戶端發送應答消息。

問題分析

select的使用

mongod調用select時,fdset里只會加入監聽fd,而監聽的地址通常很少,故不存在效率問題。

thread per client模型

mongod為每個連接創建一個線程,創建時做了一定優化,將棧空間設置為1M,減少了線程的內存開銷。當線程太多時,線程切換的開銷也會變大,但因為mongdb后端是持久化的存儲,切換開銷相比IO的開銷還是要小得多。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!