
1. 落寞的小黑 上周北京很冷,周五晚上大白下班奔地铁站,收到了好基友小黑的微信:
![]() 小黑: 你今天下班挺早呀! 大白: 就咱这觉悟,心里有工作,哪里都是办公桌,不要拘泥于形式嘛。明显能感觉得到小黑哥最近好像比较累,之前眼里bulingbuling闪的光是看不到了。 大白: 下午去面的哪家?啥岗位?咋样? 小黑: 是一家做自动驾驶的创业公司,网站是看团队介绍还不错,就去看看了,这次没咋准备,很多问题其实都熟悉,但是回答的不到位。 大白: 哦,明白了,那就是当时理解的不到位,稀里糊涂过去了,现在忽然问起来,想不起重点。 小黑: 差不多吧,问我都做过哪些高性能的网络框架模型,也就是IO和事件驱动那一套。话说完,小黑喝了一大口啤酒,大白看出了小黑心里有一些落寞。毕竟在帝都这个地方竞争和工作压力,以及生活琐事都一直围绕着我们,但是金钱和好运都巧妙地避开了自己... ![]() 大白:黑哥,你说这个问题确实不好回答,全是术语和略带歧义的东西,我觉得我们抓住本质去阐述就好。 小黑:来,请开始你的表演,我学习学习。大白决定和小黑好好聊聊,Linux开发中常用的高性能网络框架中的一些事儿,火锅的映衬下让夜色和天气都不那么寒冷了。 ![]()
2. IO事件和IO复用 2.1 什么是IO事件IO指的是输入Input/输出Output,但是从汉语角度来说,出和入是相对的,所以我们需要个参照物。这里我们的参照物选择为程序运行时的主存储空间,外部通常包括网卡、磁盘等。有了上述的设定理解起来就方便多了,我们来一起看下:IO的本质是数据的流动,数据可以从网卡到程序内存,也可以从程序内存写到网卡,磁盘操作也是如此。所以可以把常见的IO分为:
![]()
![]() 2.2 什么是IO复用设想假如有几万个IO事件,那么应用程序该如何管理呢?这就要提到IO复用了。IO复用从本质上来说就是应用程序借助于IO复用函数向内核注册很多类型的IO事件,当这些注册的IO事件发生变化时内核就通过IO复用函数来通知应用程序。 ![]() ![]() 3. 网络框架设计要素 要理解网络框架有哪些,必须要清楚网络框架完成了哪些事情。
![]()
备注:上述例子是以同步IO为例,并且将线程中的角色分为Listen线程、Handler线程、Worker线程,分别完成不同的工作,后续会详细展开。所以我们可以知道,要完成一个数据交互,涉及了几大块内容:
![]() 4. 高性能网络框架实践 4.1 基于线程模型在早期并发数不多的场景中,有一种One Request One Thread的架构模式。该模式下每次接收一个新请求就创建一个处理线程,线程虽然消耗资源并不多,但是成千上万请求打过来,性能也是扛不住的。
![]() ![]() 事件驱动编程是一种编程范式,程序的执行流由外部事件来决定,它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。通俗来说就是:有一个循环装置在一直等待各种事件的到来,并将到达的事件放到队列中,再由一个分拣装置来调用对应的处理装置来响应。 ![]() 4.3 Reactor反应堆模式第一次听到这个模式的时候很困惑,究竟反应堆是个啥?研究了一下发现,反应堆是个核物理的概念,大致是这个样子的: 核反应堆是核电站的心脏 ,它的工作原理是这样的:原子由原子核与核外电子组成,原子核由质子与中子组成。 当铀235的原子核受到外来中子轰击时,一个原子核会吸收一个中子分裂成两个质量较小的原子核,同时放出2-3个中子。 这裂变产生的中子又去轰击另外的铀235原子核,引起新的裂变,如此持续进行就是裂变的链式反应。 ![]() 5.反应堆模式详解 反应堆模式是一种思想,形式却有很多种。5.1 反应堆模式的本质是什么从本质上理解,无论什么网络框架都要完成两部分操作:
![]()
![]() ![]() ![]() ![]() ![]() 5.4 多Reactor线程和线程池模式水平扩展往往是提供性能的有效方法。 ![]() ![]() ![]() 6. 小结 本文从IO事件和IO复用出发,阐述了网络架构最底层的组成。继续展开了基于线程模型和基于事件驱动模型的网络框架特点及其设计要素。之后重点描述了反应堆模式的核心本质,以及生产环境中的多种形式。最后简单介绍了同步IO和异步IO的区别,以及Preactor模式的优势。希望读者朋友可以摒弃专业术语和表述,抓住问题的本质和重点,找到一个适合自己思维方法去理解和掌握高性能网络架构的设计之道。或许,高性能网络框架只是一个纸老虎。 |