Mongodb源码分析–消息(message)

在Mongodb中,客户端和服务端进行通信是基于mongodb wire protocol。说白了,该协议是一个简单的基于socket,请求/响应方式的协议,客户端使用常规的TCP/IP套接字(socket)进行通信。



客户端与服务端使用约定的消息(格式)进行通信,其消息头结构与C语言中的struct类似。具体的代码(位于message.cpp):



structMSGHEADER {

int32 messageLength;
//消息长度(字节),包括它自身

int32 requestID;//消息标识符,用于在请求响应过程中唯一标识该消息

int32 responseTo;//源请求id(用于服务端发送应答信息时)requestID from the original request

//(used in reponses from db)

int32 opCode;//消息类型,参见enum中描述

};



enumOperations {

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)消息,其消息结构如下:



structOP_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)消息,其结构如下:




structOP_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;//消息中游标数

int64cursorIDs;//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):

Mongodb源码分析--消息(message)



其中:

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++
原文链接: https://www.cnblogs.com/daizhj/archive/2011/04/02/2003335.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/23276

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午1:14
下一篇 2023年2月8日 上午1:16

相关推荐