客戶端與服務端使用約定的消息(格式)進行通信,其消息頭結構與C語言中的struct類似。具體的代碼(位於message.cpp):
- struct MSGHEADER {
- int32 messageLength; // 消息長度(字節),包括它自身
- int32 requestID; // 消息標識符,用於在請求響應過程中唯一標識該消息
- int32 responseTo; // 源請求id(用於服務端發送應答信息時)requestID from the original request
- // (used in reponses from db)
- int32 opCode; //消息類型,參見enum中描述
- };
- enum Operations {
- opReply = 1, /* 對客戶端請求的響應. */
- dbMsg = 1000, /* 通常的消息命令(跟着字符串) */
- dbUpdate = 2001, /* 更新document消息 */
- dbInsert = 2002, /* 插入新document消息*/
- //dbGetByOID = 2003,/*保留*/
- dbQuery = 2004, /* 查詢一個集合*/
- dbGetMore = 2005, /* 從(一個)查詢中獲取更多數據,參見 Cursors */
- dbDelete = 2006, /* 刪除一個或多個document*/
- dbKillCursors = 2007 /* 通知數據庫,客戶端已執行完畢,可以關閉該Cursors*/
- };
注:客戶端可以使用除上面Reply之外的所有消息類型,因爲Reply是數據庫保留使用的。同時客戶端可以使用QUERY和GETMORE消息來讓服務端發送響應信息,其它消息類型則不會。
下面分別進行介紹。
Client 請求消息包括:
1.對於更新 (document)消息,其消息結構如下:
- struct OP_UPDATE {
- MsgHeader header; // 前面介紹的標準消息類信息
- int32 ZERO; // 0 - 爲將來使用而保留的數據位
- cstring fullCollectionName; // 完整的集合名稱,形如:"dbname.collectionname"
- int32 flags; // 位向量,參見下面介紹
- document selector; // 查詢選擇器,用於指定查詢條件
- document update; // 指定要執行的更新(document)
- }
flags 標誌位向量:
bit 名稱 描述
0 Upsert 如設置該位爲0,同時未查詢到相關document時,數據庫會把提供的對象插入到集合中
1 MultiUpdate 如設置該位爲1,則數據庫會更新所有查詢到的document,否則僅更新查詢到的第一個
document
2-31 Reserved 必須設置爲0.
2.對於插入 (document)消息,其結構如下:
- struct {
- MsgHeader header; // 前面介紹的標準消息類信息
- int32 ZERO; // 0 - 爲將來使用而保留的數據位
- cstring fullCollectionName; // 完整的集合名稱,形如:"dbname.collectionname"
- document * documents; // 要插入的一個或多個document,如爲多個時,這些document會依次逐個寫到socket裏
- }
3. 對於查詢 (document)消息,其結構如下:
- struct
- OP_QUERY {
- MsgHeader header; // 標準消息類信息
- int32 flags; // 位向量,參見下面介紹
- cstring fullCollectionName; //
- 完整的集合名稱,形如:"dbname.collectionname"
- int32 numberToSkip; //
- 設置從第一個document起,跳過(忽略)的document數
- int32 numberToReturn; // 返回的document數
- // in the first OP_REPLY batch
- document query; // 查詢對象,該對象同時包括一個或多個元素($query,
- $orderby, $hint, $explain, $snapshot),這些元素用於匹配(match)包含在結果集(result
- set)中的對象
- [ document returnFieldSelector; ] // 可選頂.
- 要求返回的document應包含的字段(fields)
- }
flags 標誌位向量:
bit 名稱 描述
0 保留 必須設置爲0
1 TailableCursor Tailable 表示在返回最後一條數據後,不要關閉當前 cursor。這是因爲系統
考慮到稍後你可以再次使用該cursor.
2 SlaveOk 是否允許查詢replica slave結點. 通過返回錯誤信息,除非是在"local"名空間.
3 OplogReplay 僅限內部replication時使用
4 NoCursorTimeout 服務器爲了防止內存使用過量,會在一段時間(10分鐘)後將空閒的cursors
暫停(times out).
5 AwaitData 與TailableCursor配合使用. 如果在數據尾部, 阻塞一會而不是返回無數據信息
(no data). 當(阻塞)時間之後,通常執行返回(return)操作.
6 Exhaust 個人理解:把數據作爲一個包,整個下載下來。後面是英文原文說明:
Stream the data down full blast in multiple "more" packages,
on the assumption that the client will fully read all data queried.
Faster when you are pulling a lot of data and know you want to pull it
all down. Note: the client is not allowed to not read all the data unless
it closes the connection.
7 Partial 如一些shards宕掉,爲了不拋出異常,則從 mongos 那裏返回部分結果
8-31 Reserved 必須設置爲0
4. 對於查詢更多 (document)消息,其結構如下:
- struct {
- MsgHeader header; // 標準消息類信息
- int32 ZERO; // 0 - 爲將來使用而保留的數據位
- cstring fullCollectionName; // 完整的集合名稱,形如:"dbname.collectionname"
- int32 numberToReturn; // 返回的document數
- int64 cursorID; // 在REPLY消息中的Cursor標識符,其必須來自於數據庫
- }
5. 對於刪除 (document)消息,其結構如下:
- struct {
- MsgHeader header; // 標準消息類信息
- int32 ZERO; // 0 - 爲將來使用而保留的數據位
- cstring fullCollectionName; // 完整的集合名稱,形如:"dbname.collectionname"
- int32 flags; // 位向量,參見下面介紹
- document selector; // 查詢條件
- }
flags 標誌位向量:
bit 名稱 描述
0 SingleRemove 如設置,則僅刪除查詢到的第一個document,否則刪除所有查詢到的document
1-31 Reserved 必須設置爲0
6.對於KILL_CURSORS 消息,該消息用於在數據庫裏關閉一個活動(active)的遊標, 其結構如下:
- struct {
- MsgHeader header; // 標準消息類信息
- int32 ZERO; // 0 - 爲將來使用而保留的數據位
- int32 numberOfCursorIDs; // 消息中游標數
- int64 * cursorIDs; // cursorIDs的關閉順序,其會依次寫入到socket中
- }
注意:如果遊標正在讀時,如果未exhausted (直到 OP_QUERY 或 OP_GETMORE 返回 zero ), 則不必關閉遊標
7.對於MSG (document)消息,它是向數據庫發送診斷消息(diagnostic message). 而數據庫到發送確定(fixed)順應其結構如下:
- struct {
- MsgHeader header; // 標準消息類信息
- cstring message; // message for the database
- }
數據庫響應消息(針對QUERY或GET_MORE的順應)包括:
對於REPLY 消息,其結構如下:
- struct {
- MsgHeader header; // 標準消息類信息
- int32 responseFlags; // 位向量,參見下面介紹
- int64 cursorID; // cursor id if client needs to do get more's
- int32 startingFrom; // 應答(reply)的遊標中的起始位置
- int32 numberReturned; // 應答中的document數
- document * documents; // 應答的document(一或多個)
- }
responseFlags 標誌位向量:
bit 名稱 描述
0 CursorNotFound 當執行getMore時,服務器上當前遊標失效.返回 zero 結果信息.
1 QueryFailure 查詢失敗時. 在返回信息(document)中包括一個 "$err" 字段對該
失敗加以描述.
2 ShardConfigStale Drivers should ignore this. Only mongos will ever see this set,
in which case, it needs to update config from the server.
3 AwaitCapable 在服務器支持AwaitData查詢選項時進行設置. 如不設置,客戶端會在
一個Tailable 遊標的兩個getMore操作之間停止(sleep)一會.
在Mongod 1.6版本中支持該選項並一直設置.
4-31 Reserved 可忽略
上面是一些關於消息類型的介紹,下面讓我們來看一下MongoDB的具體實現類。
在mongodb中,其提供瞭如下幾個類對消息進行定義,封裝及解析, 接收/發送等操作(位於message.h和dbmessage.h):
其中:
MsgData (struct類型):提供了對消息數據信息部分的結構定義,如操作標誌位_operation,以及上面所說的flags.
Message : 對MsgData封裝以及對消息的操作方法(比如:設置消息數信息(MsgData),獲取消息頭信息,消息信息重置,消息設置追加等)
MessagingPort :提供消息的發送,接收等。並將接收到的信息(如char *類型)進行分解,並調用消息(Message)的相關方法將分解結果作爲參數傳入,反之一樣,這裏它相當於一個轉換器。
DbMessage :特別的消息類型,它是對Message封裝,用於提供針對數據庫操作類型消息的訪問
QueryMessage : 對DbMessage中的查詢請求消息進行解析封裝
好了,今天的內容就先到這裏了。
參考鏈接:http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol
原文鏈接:http://www.cnblogs.com/daizhj/archive/2011/04/02/2003335.html
作者: daizhj, 代震軍
微博: http://t.sina.com.cn/daizhj
Tags: mongodb,message,protocol,c++