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

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

      客户端与服务端使用约定的消息(格式)进行通信,其消息头结构与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++

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值