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

来源:互联网 发布:筑波大学 知乎 编辑:程序博客网 时间:2024/05/31 00:39

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

      客户端与服务端使用约定的消息(格式)进行通信,其消息头结构与C语言中的struct类似。具体的代码(位于message.cpp):
    
  
view plaincopy to clipboardprint?
  1. struct MSGHEADER {  
  2.        int32 messageLength; // 消息长度(字节),包括它自身  
  3.        int32 requestID;     // 消息标识符,用于在请求响应过程中唯一标识该消息  
  4.        int32 responseTo;  // 源请求id(用于服务端发送应答信息时)requestID from the original request  
  5.        //   (used in reponses from db)  
  6.        int32 opCode; //消息类型,参见enum中描述  
  7.    };  
  8.    enum Operations {  
  9.        opReply = 1,     /* 对客户端请求的响应. */  
  10.        dbMsg = 1000,    /* 通常的消息命令(跟着字符串) */  
  11.        dbUpdate = 2001, /* 更新document消息 */  
  12.        dbInsert = 2002, /* 插入新document消息*/  
  13.        //dbGetByOID = 2003,/*保留*/  
  14.        dbQuery = 2004,  /* 查询一个集合*/  
  15.        dbGetMore = 2005, /* 从(一个)查询中获取更多数据,参见 Cursors */  
  16.        dbDelete = 2006, /* 删除一个或多个document*/  
  17.        dbKillCursors = 2007 /* 通知数据库,客户端已执行完毕,可以关闭该Cursors*/  
  18.    };  


       注:客户端可以使用除上面Reply之外的所有消息类型,因为Reply是数据库保留使用的。同时客户端可以使用QUERY和GETMORE消息来让服务端发送响应信息,其它消息类型则不会。 

      下面分别进行介绍。


Client 请求消息包括: 

    1.对于更新 (document)消息,其消息结构如下:

view plaincopy to clipboardprint?
  1. struct  OP_UPDATE {  
  2.     MsgHeader header;              //  前面介绍的标准消息类信息  
  3.     int32     ZERO;                //  0 - 为将来使用而保留的数据位  
  4.     cstring   fullCollectionName;  //  完整的集合名称,形如:"dbname.collectionname"  
  5.     int32     flags;               //  位向量,参见下面介绍  
  6.     document  selector;            //  查询选择器,用于指定查询条件  
  7.     document  update;              //  指定要执行的更新(document)  
  8. }  


      flags 标志位向量:

bit         名称              描述  
0        Upsert             如设置该位为0,同时未查询到相关document时,数据库会把提供的对象插入到集合中 
1        MultiUpdate      如设置该位为1,则数据库会更新所有查询到的document,否则仅更新查询到的第一个

                                document 
2-31    Reserved         必须设置为0.   



    2.对于插入 (document)消息,其结构如下:

view plaincopy to clipboardprint?
  1. struct  {  
  2.     MsgHeader header;              //  前面介绍的标准消息类信息  
  3.     int32     ZERO;                //  0 - 为将来使用而保留的数据位  
  4.     cstring   fullCollectionName;  //  完整的集合名称,形如:"dbname.collectionname"  
  5.     document *  documents;      //  要插入的一个或多个document,如为多个时,这些document会依次逐个写到socket里  
  6. }  


    3. 对于查询 (document)消息,其结构如下:

view plaincopy to clipboardprint?
  1. struct  
  2.   OP_QUERY {  
  3.     MsgHeader header;                 //  标准消息类信息  
  4.     int32     flags;                  //  位向量,参见下面介绍  
  5.     cstring   fullCollectionName;     //    
  6. 完整的集合名称,形如:"dbname.collectionname"  
  7.     int32     numberToSkip;           //    
  8. 设置从第一个document起,跳过(忽略)的document数  
  9.     int32     numberToReturn;         //  返回的document数  
  10.                                       //   in the first OP_REPLY batch  
  11.     document  query;                  //  查询对象,该对象同时包括一个或多个元素($query,   
  12. $orderby, $hint, $explain, $snapshot),这些元素用于匹配(match)包含在结果集(result   
  13. set)中的对象  
  14.   [ document  returnFieldSelector; ]  //  可选顶.   
  15. 要求返回的document应包含的字段(fields)                                   
  16. }  


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

view plaincopy to clipboardprint?
  1. struct  {  
  2.     MsgHeader header;              //  标准消息类信息  
  3.     int32     ZERO;                //  0 - 为将来使用而保留的数据位  
  4.     cstring   fullCollectionName;  //  完整的集合名称,形如:"dbname.collectionname"  
  5.     int32     numberToReturn;      //  返回的document数  
  6.     int64     cursorID;            //  在REPLY消息中的Cursor标识符,其必须来自于数据库  
  7. }  



     5.  对于删除 (document)消息,其结构如下:

view plaincopy to clipboardprint?
  1. struct  {  
  2.     MsgHeader header;              //  标准消息类信息  
  3.     int32     ZERO;                //  0 - 为将来使用而保留的数据位  
  4.     cstring   fullCollectionName;  //  完整的集合名称,形如:"dbname.collectionname"  
  5.     int32     flags;               //  位向量,参见下面介绍  
  6.     document  selector;            //  查询条件  
  7. }  


     flags 标志位向量:

bit     名称                      描述 
0       SingleRemove      如设置,则仅删除查询到的第一个document,否则删除所有查询到的document   
1-31   Reserved            必须设置为0   


      6.对于KILL_CURSORS 消息,该消息用于在数据库里关闭一个活动(active)的游标, 其结构如下:

view plaincopy to clipboardprint?
  1. struct  {  
  2.     MsgHeader header;             //  标准消息类信息  
  3.     int32     ZERO;               //  0 - 为将来使用而保留的数据位  
  4.     int32     numberOfCursorIDs;  //  消息中游标数  
  5.     int64 *     cursorIDs;          //  cursorIDs的关闭顺序,其会依次写入到socket中  
  6. }  



      注意:如果游标正在读时,如果未exhausted (直到 OP_QUERY 或 OP_GETMORE 返回 zero ), 则不必关闭游标


      7.对于MSG (document)消息,它是向数据库发送诊断消息(diagnostic message). 而数据库到发送确定(fixed)顺应其结构如下:

view plaincopy to clipboardprint?
  1. struct  {  
  2.     MsgHeader header;   //  标准消息类信息  
  3.     cstring   message;  //  message for the database  
  4. }  



   
数据库响应消息(针对QUERY或GET_MORE的顺应)包括:

      对于REPLY 消息,其结构如下:

 

view plaincopy to clipboardprint?
  1. struct  {  
  2.     MsgHeader header;          //  标准消息类信息  
  3.     int32     responseFlags;   //  位向量,参见下面介绍  
  4.     int64     cursorID;        //  cursor id if client needs to do get more's  
  5.     int32     startingFrom;    //  应答(reply)的游标中的起始位置  
  6.     int32     numberReturned;  //  应答中的document数  
  7.     document *  documents;       //  应答的document(一或多个)  
  8. }  

 

      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++

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高考报名用的电话号码变换了怎么办 弟媳妇一个月就大闹一次怎么办 丈夫出轨我亲弟媳妇我怎么办 被山西博大泌尿医院坑了怎么办 家长反应孩子学校受欺负老师怎么办 白色衣服和牛仔裤洗变色了怎么办 生完孩子肚子上的松皮怎么办 xp电脑玩cf进入地图黑屏怎么办 爸妈吵架妈妈走了爸爸哭了该怎么办 总担心旅馆被拍视频传上网怎么办 微博买了猜冠军现在停了怎么办 脸上毛孔大有黑头怎么办小窍门去 进去精神病院出来真的疯了怎么办 房子已过户新业主不交物业费怎么办 村委会欠百姓征地补偿款不给怎么办 因为近亲人人都不看好的婚姻怎么办 碰到工作中特别积极的同事怎么办 丈夫车祸死亡妻子和孩子以后怎么办 丈夫死后妻子改嫁儿子不同意怎么办 满了60岁社保没满15年怎么办 捷豹的dpf灯亮了怎么办 朋友如新直销产品是你该怎么办 传福音接受了却被家人拦阻该怎么办 奶奶出钱由孙子抓奖中奖后怎么办 我不想学车了驾校不同意退学怎么办 2017年大学挂科面临退学怎么办 微信重新登录后东西全没了怎么办 宝宝吃鸡蛋过敏全身起红疹怎么办 180在产蛋鸡因断鸡减产怎么办 住友39熔接机熔接损耗大怎么办 支付宝实名认证刷脸失败怎么办 支付宝注册刷脸不是本人怎么办 小学科学只考88分中学怎么办 收银机关机时才上传数据是怎么办 刚做的系统玩cf卡屏怎么办 办健康证的资料掉了怎么办 刚刚办得的健康证掉了怎么办 房子都过户了银行贷不了款怎么办 我要办大病迁出应该怎么办啊? 遗产继承后户口没地迁出怎么办 安徽蒙城怎么办去韩国的签证的