在上一篇博客中(mongo源码学习(二)db.cpp之mongoDbMain方法分析),我们把db.cpp中的mongoDbMain的执行过程分析了一下,最后会调用initAndListen(serverGlobalParams.port)方法来监听端口,默认的是27017了。程序执行到这块就断开了,追踪不下去了。在另一个地方肯定有accept方法来接收客户端的请求。然后找了半天发现了文件夹transportlayer,发现了里面有相关的代码。

transport_layer.h

  1. // mongo的命名空间
  2. namespace mongo {
  3.  
  4. class OperationContext;
  5.  
  6. // transport的命名空间, 我是cpp小白, 命名空间还可以嵌套, TODO:namespace学习一下
  7. namespace transport {
  8.  
  9. // 连接的SSL模型, TODO:SSL可以了解一下哦
  10. enum ConnectSSLMode { kGlobalSSLMode, kEnableSSL, kDisableSSL };
  11.  
  12. // 这个应该声明的意思, TODO:C++声明类
  13. class Reactor;
  14.  
  15. // using还可以这么用, shared_ptr是啥, 可以了解一下
  16. // 妈的, 写不下去了, 就我这这样的还来看mongo的C++源码
  17. using ReactorHandle = std::shared_ptr<Reactor>;
  18.  
  19. /**
  20. * The TransportLayer moves Messages between transport::Endpoints and the database.
  21. * This class owns an Acceptor that generates new endpoints from which it can
  22. * source Messages.
  23. *
  24. * The TransportLayer creates Session objects and maps them internally to
  25. * endpoints. New Sessions are passed to the database (via a ServiceEntryPoint)
  26. * to be run. The database must then call additional methods on the TransportLayer
  27. * to manage the Session in a get-Message, handle-Message, return-Message cycle.
  28. * It must do this on its own thread(s).
  29. *
  30. * References to the TransportLayer should be stored on service context objects.
  31. */
  32. /**
  33. * TransportLayer在transport::Endpoints和database(也就是mongo了)之间传递消息(message)。
  34. * 这个类有一个Acceptor, 这个Acceptor可以从原始的message中生成一个新的endpoints。
  35. *
  36. * TransportLay创建新的Session对象,并且在内部将它们映射到endpoints。新的Session通过一个ServiceEntryPoint
  37. * 传递到database来运行的。database后面必须调用TransportLay的其他方法来管理get-Message,
  38. * handle-Message和return-Message周期中的Session。而且必须在它自己的线程中做这些事。
  39. */
  40. class TransportLayer {
  41. // 这是个什么鬼
  42. MONGO_DISALLOW_COPYING(TransportLayer);
  43.  
  44. public:
  45.  
  46. // 声明各种状态
  47. static const Status SessionUnknownStatus;
  48. static const Status ShutdownStatus;
  49. static const Status TicketSessionUnknownStatus;
  50. static const Status TicketSessionClosedStatus;
  51. // 把Session对象设为友元
  52. friend class Session;
  53. // virtual, TODO:虚方法了解一下
  54. virtual ~TransportLayer() = default;
  55. // 连接
  56. virtual StatusWith<SessionHandle> connect(HostAndPort peer,
  57. ConnectSSLMode sslMode,
  58. Milliseconds timeout) = ;
  59. // 异步连接
  60. virtual Future<SessionHandle> asyncConnect(HostAndPort peer,
  61. ConnectSSLMode sslMode,
  62. const ReactorHandle& reactor,
  63. Milliseconds timeout) = ;
  64.  
  65. /**
  66. * Start the TransportLayer. After this point, the TransportLayer will begin accepting active
  67. * sessions from new transport::Endpoints.
  68. */
  69. /**
  70. * 启动TransportLayer。在这之后,TransportLayer将开始从新的transport::Endpoints接收活跃的session。
  71. */
  72. virtual Status start() = ;
  73.  
  74. /**
  75. * Shut the TransportLayer down. After this point, the TransportLayer will
  76. * end all active sessions and won't accept new transport::Endpoints. Any
  77. * future calls to wait() or asyncWait() will fail. This method is synchronous and
  78. * will not return until all sessions have ended and any network connections have been
  79. * closed.
  80. */
  81. /**
  82. * 关闭TransportLay。在这之后,TransportLayer将终止所有活跃的sessions并且不再接收新的EndPoints。
  83. * 任何将来对wait()和asyncWait()的调用都会失败。这个方法是同步的,并且直到所有的sessions都结束了
  84. * 之后并且任何网络连接都关闭了才会返回。
  85. */
  86. virtual void shutdown() = ;
  87.  
  88. /**
  89. * Optional method for subclasses to setup their state before being ready to accept
  90. * connections.
  91. */
  92. /**
  93. * 这个是可选的方法,子类可以用这个方法在准备接收连接的时候去设置它们的状态。
  94. */
  95. virtual Status setup() = ;
  96.  
  97. enum WhichReactor { kIngress, kEgress, kNewReactor };
  98. virtual ReactorHandle getReactor(WhichReactor which) = ;
  99.  
  100. virtual BatonHandle makeBaton(OperationContext* opCtx) {
  101. return nullptr;
  102. }
  103.  
  104. protected:
  105. TransportLayer() = default;
  106. };
  107. } // namespace transport
  108. } // namespace mongo

这里看着有点绕,主要的几个角色有:

TransportLayer:有Acceptor接收请求,产生新的EndPoints,创建Session,并将Session在内部映射到EndPoints上;同时TransportLayer也在EndPoints和database之间传递消息。

Session:get-Message,handle-Message和return-Message,但是这些需要TransportLayer来管理。

EndPoints:抽象出来的端的概念。

Acceptor:接收请求的。

database:我们的mongo后台

TransportLayer类图

这里画了一下TransportLayer的类图:

我倒是在浏览代码的时候对TransportLayer所起的作用有了一定的认识,但是还不是很深入。对TransportLayer角色的定位不清楚,就像类图中所说的,尼玛,它怎么会有connect方法呢?我现在非常想找的是服务器端接收客户端的accept方法在哪儿?

经过了一番摸索,终于找到了accept方法了,原来就在TransportLayerASIO中。根据这几天的学习,大概总结出了下面的这个模型:

纯属本人自己看源码总结的,不一定保证正确。其实到这里来我们压根还没深入到数据库中,最多只是到了数据库的门口,也就是ServiceEntryPoint,不过也算开了个头。在上图中我画了一条水平的虚线,我想表达的是,在虚线上方的东西基本上给哪个C/S架构的系统都是可以用的,在根本模型还是最简单的Socket的通信,不过加了很多东西。

虽然这些代码对我这个小白来说也也挺用处的,但是看mongo的源码个人觉得重要的还是:存储引擎,事务,锁,集群这些东西更好玩。功力较浅加上C++不怎么熟,所有看起来还是有点吃力,喜欢的朋友可以关注下,我就更有动力了。有了面向对象的思想看C++如果不执着于细节,看懂的话可以达到5,6成。有些时候只用看一些函数调用,但是有些时候需要深入到函数里面看一下,这个也没有啥经验,反正就是做实验一样去试吧。

在看TransportLayer的代码的时候,看到了一个叫状态机的玩意,注释解释的意思是,mongod是一个无状态的服务,但是客户端是有状态的,为了进行这种有状态/无状态的转换,就用到了这个向量机。感觉挺叼的,无状态的好处很多,但是自己实际工作中用的还比较少。

另外一个就是用到了命令设计模式,也是值得我去看的。

我有一个大胆而不成熟的想法,看mongo的C++源码,然后用golang去重写一遍,带垃圾回收的除了java都不用,好疯狂。

mongo源码学习(三)请求接收传输层的更多相关文章

  1. mongo源码学习(四)服务入口点ServiceEntryPoint

    在上一篇博客mongo源码学习(三)请求接收传输层中,稍微分析了一下TransportLayer的作用,这篇来看下ServiceEntryPoint是怎么做的. 首先ServiceEntryPoint ...

  2. mybatis源码学习(三)-一级缓存二级缓存

    本文主要是个人学习mybatis缓存的学习笔记,主要有以下几个知识点 1.一级缓存配置信息 2.一级缓存源码学习笔记 3.二级缓存配置信息 4.二级缓存源码 5.一级缓存.二级缓存总结 1.一级缓存配 ...

  3. Vue源码学习三 ———— Vue构造函数包装

    Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...

  4. spring源码学习(三)--spring循环引用源码学习

    在spring中,是支持单实例bean的循环引用(循环依赖)的,循环依赖,简单而言,就是A类中注入了B类,B类中注入了A类,首先贴出我的代码示例 @Component public class Add ...

  5. [spring源码学习]三、IOC源码——自定义配置文件读取

    一.环境准备 在文件读取的时候,第9步我们发现spring会根据标签的namespace来选择读取方式,联想spring里提供的各种标签,比如<aop:xxx>等应该会有不同的读取和解析方 ...

  6. OKHttp源码学习同步请求和异步请求(二)

    OKHttp get private void doGet(String method, String s) throws IOException { String url = urlAddress ...

  7. mongo源码学习(四)invariant

    前言 在看MongoDB源码的时候,经常会看到这个玩意儿:invariant. invariant的字面意思是:不变式. 在emacs上跳转到函数定义要安装一个插件,ggtags,费了老大劲儿.这都可 ...

  8. mongo源码学习(一)

    在git上把mongo的源码给拉下来了,然后目录大概是这样的: 这个mongo是用C++写的,编译并没有用Makefile而是用的scons工具,这个好像是python写的. mongo后台进程的入口 ...

  9. vue 源码学习三 vue中如何生成虚拟DOM

    vm._render 生成虚拟dom 我们知道在挂载过程中, $mount 会调用 vm._update和vm._render 方法,vm._updata是负责把VNode渲染成真正的DOM,vm._ ...

随机推荐

  1. MongoDB学习笔记(6)--find

    MongoDB 查询文档 MongoDB 查询文档使用 find() 方法. find() 方法以非结构化的方式来显示所有文档. 语法 MongoDB 查询数据的语法格式如下: db.collecti ...

  2. Shell脚本开发环境的配置和优化实践

    1. 配置vim编辑器 1-1. 为什么不使用vi而是vim vi适合编辑普通文本,不适用编写脚本代码,例如:缺少高亮显示代码.自动缩进等重要功能: vim相当于高级编辑器,可以提高开发效率. 1-2 ...

  3. Mongodb 安装(Windows)

  4. 讲讲python“=”运算符上的优雅语法

    心路历程: 之前学linux,虽然学的行算不错,不过总感觉差了点什么,自己找不到也说不出来:直到有一天我看到别人mount上了一个普通文件: 当时给我的感觉这太不可思议了,这个文件又不是块设备:后来脑 ...

  5. get the code of function in matlab

    >> edit <function>>> edit perform

  6. Another app is currently holding the yum lock; waiting for it to exit.. yum被锁定无法使用

    yum被锁定无法使用 Another app is currently holding the yum lock; waiting for it to exit.. 解决方法: rm -rf /var ...

  7. redis 3.2.3的源码安装

    Install necessary packages On CentOS : yum install wget make gcc tcl On CentOS yum install wget make ...

  8. Android 抓包并通过 Wireshark 分析

    分析 Android 中 app 的网络数据交互,需要在 Android 上抓包,常用工具为 tcpdump ,用 tcpdump 生成 Wireshark 识别的 pcap 文件,把 pcap 文件 ...

  9. Android-Cannot merge new index 66195 into a non-jumbo instruction的解决办法

    转载请注明来源:http://blog.csdn.net/goldenfish1919/article/details/33729679 用eclispe打包的时候报错: [2014-06-23 13 ...

  10. ImageView 最大bitmap 4096

    ImageView 最大bitmap 4096,超出不显示图片