muduo网络库架构总结

综合技术 2018-12-08 阅读原文

目录

本篇结束muduo网络库部分学习的笔记,总结一下muduo网络库的模块组成,同时会提供笔记中个模块的实现代码,这些模块代码单独抽出同时去除了muduo中对boost的依赖,改用c++11中的组件或者用单独的类替换,会使得muduo的各个组件会更为简洁易学,不过代码还不完善,简单使用和学习的话完全够用。

muduo网络库简介

muduo是一个高质量的事件驱动型的网络库,其核心代码不超过4500行,使用的non-blocking IO(IO multiplexing)+ one loop per

thread模型。此模型每个IO线程里面只有一个事件循环(即一个Reactor),处理读写和定时事件,激活的事件通过回调方式提供用户处理业务逻辑。

在linux下的话,可以把事件当做一个文件描述符,换句话也就是说一个file descriptor只能由一个线程读写。

一个线程最多只有一个EventLoop,而EventLoop中的循环即是在不停的监视这些描述符,当描述符可读或可写的时候,通过回调函数提供给用户处理。

这样我们可以很方便地把不同的socket套接字的描述符放到不同的线程去, 也可以把一些socket放到一个线程里,这样这些socket就是线程安全的,因为始终只有EventLoo所在线程在读写它们,极大的降低了我们的编程复杂性。

它看上去就是这个样子,EventLoop一直处在事件循环中,通过IO复用机制select/poll/epoll等待激活的事件。

muduo网络库模块组成

muduo的组件大致可划分为 5个部分, Reactor、TimerQueue和Eventfd、Acceptor和Connector、TcpConnection、TcpServer和TcpClient。

muduo网络部分的简化类图

如果只注重服务端的话,可以TcpClient省去,Poller在muduo中是个纯虚基类,现在用poll(2)具体化它,省略它们后的结构应该是这样的。

EventLoop和Poller及Channel组成Reactor部分、Acceptor作为TcpServer的监听器、TcpConnection负责处理socket的读写等事件、而TcpServer处理TcpConnection读写完成后的回调事件。

Recator反应器

Reactor由三部分组成,EventLoop、Poller、Channel.

EventLoop 即IO线程中的事件循环.它能确保所有注册的事件都在EventLoop对象所在的线程中执行,不用考虑事件的并发。它是线程安全的,且允许其他线程往EventLoop里面塞东西。

Poller 是IO multiplexing的封装,它是EventLoop的组成,与EventLoop的生命期相当,为EventLoop提供poll()方法。

Channel 每个Channel对象自始至终只负责一个文件描述符(fd) 的IO事件分发,但它不拥有这个fd,也不会在析构的时候关闭这个fd。每个Channel对象自始至终只属于一个EventLoop,因此每个Channel对象都只属于某一个IO线程。 Channel会把不同的IO事件分发为不同的回调, 例如ReadCallback、 WriteCallback等

Reactor结构实现可参阅我的笔记二
muduo学习笔记(二)Reactor关键结构

Reactor部分实现源码及简单测试 : https://github.com/BethlyRoseDaisley/SimpleMuduo/tree/master/Reactor

Reactor的时序图 :

EventLoop的两个组件

TimerQueue定时器

TimerQueue 并未在类图中单独给出,它是EventLoop的组件,为EventLoop提供了定时任务,和周期任务的接口。通过注册一个Timerfd到Poller实现.

TimerQueue的实现笔记 muduo网络库学习笔记(三)TimerQueue定时器队列

TimerQueue实现部分源码及简单测试 : https://github.com/BethlyRoseDaisley/SimpleMuduo/tree/master/TimerQueue

Eventfd

Eventfd 这个就是其他线程能往EventLoop线程里面塞任务的实现核心,它是 一个事件文件描述符fd,EventLoop通过将它注册到Poller,当其他线程往EventLoop里面塞任务的时候,先将任务存储在EventLoop的容器中,然后激活Eventfd,处理容器中存储的任务,当然赛任务需要一把锁来保护。

Eventfd的实现笔记 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

Connector和Acceptor连接器和监听器

Acceptor

Acceptor 它是服务端TcpServer类的主要组件,封装服务端的连接监听部分,在非阻塞网络编程中,accept的描述符可读,表明有新的连接上来,连接建立后通过回调告知用户有新的连接上来。

Acceptor的笔记 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

Acceptor实现部分源码及简单测试 : https://github.com/BethlyRoseDaisley/SimpleMuduo/tree/master/Acceptor

Acceptor的时序图 :

Connector

在非阻塞网络编程中,发起连接的基本方式是调用connect(2),当socket变得可写时表明连接建立完毕,但是其中要处理各种类型的错误,muduo中把它封装为Connector class.

Connector 和 Acceptor 设计思路基本一致,只是Acceptor通过判断套接字是否可读来执行回调,而Connector是判断套接字是否可写来执行回调,但是要注意的是socket可写不一定就是连接建立好了 , 当连接建立出错时,套接口描述符变成既可读又可写,这时我们可以通过调用getsockopt来得到套接口上待处理的错误(SO_ERROR),如果错误是0表示连接成功。

Connector的笔记 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

Connector实现部分源码及简单测试 : https://github.com/BethlyRoseDaisley/SimpleMuduo/tree/master/Connector

Connector的时序图 :

TcpConnection

Buffer muduo中的buffer通过vector和一个栈上空间实现,动态可调,其结构很精妙,感兴趣的话建议直接阅读陈硕Buffer部分设计的文章. 这个buffer主要做为TcpConnection的组件。

Socket 封装一个套接字,管理了这个套接字描述符的生命期,是TcpConnection的组件,TcpConnection 通过这个套接字描述符注册读写事件,SocketHelp一个纯接口文件,封装了Socket的操作接口。

TcpConnection 封装一条Tcp连接, 处理这条连接中的读写及错误,连接关闭等事件,这些事件会在TcpConnection的内部先进行处理,然后通过回调函数将TcpConnection缓冲的Buffer提供给用户处理。

TcpServer和TcpClient

Tcpserver 主要使用组件Acceptor,有新的连接到来时会new一个TcpConnection保存在ConnectionMaps(TcpConnection共享指针的一张映射表)中,通过创建时注册的名字索引管理所有的连接;有数据可读时通过MessgeCallBack回调提供用户使用。

TcpClient 主要组件Connector, 它的实现与TcpServer相似,只不过每个TcpClient只管理一个TcpConnection。

Reactor部分和EventLoop的组件理解后,TcpConnection和TcpServer部分就很好看懂了,所以也没有单独写新的文章。

TcpServer实现部分源码及简单测试 : https://github.com/BethlyRoseDaisley/SimpleMuduo/tree/master/TcpServer

TcpClient实现部分源码及简单测试 : https://github.com/BethlyRoseDaisley/SimpleMuduo/tree/master/TcpClient

Tcpserver的时序图 :

muduo中的线程安全日志

AsyncLogging异步日志

AsyncLogging 一个C++Stream风格的多线程安全非阻塞日志,是muduo库中的另一个部分组成。

这个日志使用了双缓冲机制,这样新建的日志不必等待磁盘操作,也避免了每条新的日志都触发日志线程,而是将多条日志拼程一个大的buffer 和后端buffer交换,后端线程就实时将后端buffer写入本地文件. 相当于批处理,减少线程唤醒频率 ,大大降低开销。

另外 ,为了及时将 日志消息写入文件, 即是 buffer A 中还没有push进来日志 也会每周期执行一次上述的写入操作。

但是有个问题,如果宕机,宕机瞬间缓存中的日志肯定是还没写完的。

用了一阵子,总的来说,这个日志个人很喜欢,轻巧简洁,十分便利。

AsyncLogging日志的格式化部分实现笔记 一个轻巧高效的多线程c++stream风格异步日志(一)

AsyncLogging的双缓冲机制 一个轻巧高效的多线程c++stream风格异步日志(二)

AsyncLogging的源码 : https://github.com/BethlyRoseDaisley/SimpleMuduo/tree/master/AsyncLogging

直接包含Logger.hh 和 AsycnLogging.hh即可直接使用。

AsyncLogging类结构 :

博客园-原创精华区

责编内容by:博客园-原创精华区阅读原文】。感谢您的支持!

您可能感兴趣的

十年Java架构师从阿里离职,分享这些年的面试经验——offer篇... 时隔两年再一次的面临离职找工作,这一次换工作有些许的不舍,也有些许的无奈。个人所在的技术团队不错,两年时间成长了很多,也很不舍这个团队。但是,由于公司的某些原因和对于自身未来发展的综合考虑,又不得不得离去,去寻找更合适的地方成长和发展。相比...
ACP互联网架构认证笔记-ARMS业务实时监控服务... ARMS是一款 阿里云应用性能管理(APM)类监控产品 。 一共提供三种监控,应用监控,前端监控,自定义监控。 服务开通,免费开通 ARMS 基础版后,可在 ARMS 控制台开通按量付费的监控服务。 开通按量付费后,才可购买应用监...
行业咨询 – 收藏集 – 掘金 漫无目标的假学习者 - 工具资源 - 掘金 前几篇文章我们反复提到学习的目的,为什么反复提以及反复写,只因为它太重要、太重要、太重要… 说十遍、一百遍都不为过。 我们好多人因为无意间看到一篇文章,...
各大厂分布式链路跟踪系统架构对比 随着互联网架构的扩张,分布式系统变得日趋复杂,越来越多的组件开始走向分布式化,如微服务、消息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式网络,那现在的问题是一个请求经过了这些服务后其中出现了一个调...
Airflow 成为 Apache 软件基金会的顶级项目... Airflow 是一个开源的大数据工作流管理系统,在 Adobe、Airbnb、Etsy、谷歌、ING、Lyft、PayPal、Reddit、Square、推特和美联航等组织得到广泛应用。 2019 年 1 月 8 日,位于马萨诸塞州 ...