-
作者:陈硕
-
编程语言:C++
-
架构模式:Reactor
-
代码链接:GitHub - chenshuo/muduo: Event-driven network library for multi-threaded Linux server in C++11
-
设计自述:https://www.cnblogs.com/Solstice/archive/2010/08/29/muduo_net_lib.html
-
-
以下内容,主要援引于自述
-
设计目标
-
线程安全,支持多线程
-
只支持 Linux,不支持 Windows
-
IO multiplexing 使用 poll 和 epoll
-
主要支持 x86-64,兼顾 IA32
-
不支持 UDP,只支持 TCP
-
不支持 IPv6,只支持 IPv4
-
不考虑广域网应用,只考虑局域网
-
只支持一种使用模式:non-blocking IO + one event loop per thread,不考虑阻塞 IO
-
API 简单易用,只暴露具体类和标准库里的类,不使用 non-trivial templates,也不使用虚函数
-
只做 library,不做成 framework
-
争取全部代码在 5000 行以内(不含测试)
-
搭配 Google Protocol Buffers RPC
实现简述
Muduo是基于Reactor模式的网络库,其核心是个事件循环EventLoop,用于响应计时器和IO事件。Muduo采用基于对象(object based)而非面向对象(object oriented)的设计风格,其接口多以boost::function + boost::bind表达。
头文件关系
- 白底:public
- 黑底:private

接口细节
公开接口
-
Buffer仿 Netty ChannelBuffer 的 buffer class,数据的读写通过 buffer 进行 -
InetAddress封装 IPv4 地址 (end point),注意,muduo 目前不能解析域名,只认 IP -
EventLoop反应器 Reactor,用户可以注册计时器回调 -
EventLoopThread启动一个线程,在其中运行 EventLoop::loop() -
TcpConnection整个网络库的核心,封装TCP连接 -
TcpClient用于编写网络客户端,能发起连接,并且有重试功能 -
TcpServer用于编写网络服务器,接受客户的连接 -
在这些类中,
TcpConnection的生命期依靠 shared_ptr 控制(即用户和库共同控制)。Buffer的生命期由TcpConnection控制。其余类的生命期由用户控制。 -
HttpServer 和 Inspector,暴露出一个 http 界面,用于监控进程的状态,类似于 Java JMX。这么做的原因是,《程序员修炼之道》第 6 章第 34 条提到“对于更大、更复杂的服务器代码,提供其操作的内部试图的一种漂亮技术是使用内建的 Web 服务器”,Jeff Dean 也说“(每个 Google 的服务器进程)Export HTML-based status pages for easy diagnosis”。
内部实现
-
Channel是 Selectable IO channel,负责注册与响应 IO 事件,它不拥有 file descriptor。它是 Acceptor、Connector、EventLoop、TimerQueue、TcpConnection 的成员,生命期由后者控制。 -
Socket封装一个 file descriptor,并在析构时关闭 fd。它是 Acceptor、TcpConnection 的成员,生命期由后者控制。EventLoop、TimerQueue 也拥有 fd,但是不封装为 Socket。 -
SocketsOps封装各种 sockets 系统调用。 -
EventLoop封装事件循环,也是事件分派的中心。它用 eventfd(2) 来异步唤醒,这有别于传统的用一对 pipe(2) 的办法。它用 TimerQueue 作为计时器管理,用 Poller 作为 IO Multiplexing。 -
Poller是 PollPoller 和 EPollPoller 的基类,采用“电平触发”的语意。它是 EventLoop 的成员,生命期由后者控制。 -
PollPoller和EPollPoller封装 poll(2) 和 epoll(4) 两种 IO Multiplexing 后端。Poll 的存在价值是便于调试,因为 poll(2) 调用是上下文无关的,用 strace 很容易知道库的行为是否正确。 -
Connector用于发起 TCP 连接,它是 TcpClient 的成员,生命期由后者控制。 -
Acceptor用于接受 TCP 连接,它是 TcpServer 的成员,生命期由后者控制。 -
TimerQueue用timerfd实现定时,这有别于传统的设置 poll/epoll_wait 的等待时长的办法。为了简单起见,目前用链表来管理 Timer,如果有必要可改为优先队列,这样复杂度可从 O(n) 降为 O(ln n) (某些操作甚至是 O(1))。它是EventLoop的成员,生命期由后者控制。 -
EventLoopThreadPool用于创建IO线程池,也就是说把 TcpConnection 分派到一组运行 EventLoop 的线程上。它是 TcpServer 的成员,生命期由后者控制。
线程模型
Muduo的线程模型符合one loop per thread + thread pool模型。
-
每个线程最多有一个
EventLoop -
每个
TcpConnection必须归某个EventLoop管理:所有IO操作,所有FDFile Descriptor读写
-
-
TcpConnection所在的线程由其所属的EventLoop决定 -
TcpConnection和EventLoop是线程安全的,可以跨线程调用
-
-
TcpServer直接支持多线程,它有两种模式:
-
-
单线程,
Acceptor与TcpConnection用同一个线程做IO。 -
多线程,
Acceptor与EventLoop在同一个线程,另外创建一个EventLoopThreadPool,新到的连接会按Round-Robin方式分配到线程池中。
-


















