How-Does-Netty-Support-Millions-Of-Concurrency
说到Netty,我们知道他极其强悍的性能以及纯异步模型,释放出了极强的生产力,内置的各种编解码编排,心跳包检测,粘包拆包处理等,高效且易于使用,以至于很多耳熟能详的组件都在使用,比如hadoop,dubbo等。但是他是如何做到这些的呢?本章将会以庖丁解牛的方式,一步一步的来拔出此剑。
Netty的异步模型
说起netty的异步模型,我相信大多数人,只要是写过服务端的话,都是耳熟能详的,bossGroup和workerGroup被ServerBootstrap所驱动,用起来简直是如虎添翼,再加上各种配置化的handler加持,组装起来也是行云流水,俯拾即是。但是,任何一个好的架构,都不是一蹴而就实现的,那她经历了怎样的心路历程呢?
1. 经典的多线程模型
此模型中,服务端起来后,客户端连接到服务端,服务端会为每个客户端开启一个线程来进行后续的读写操作。客户端少的时候,整体性能和功能还是可以的,但是如果客户端非常多的时候,线程的创建将会导致内存的急剧飙升从而导致服务端的性能下降,严重者会导致新客户端连接不上来,更有甚者,服务器直接宕机。此模型虽然简单,但是由于其简单粗暴,所以难堪大用,建议在写服务端的时候,要彻底的避免此种写法。
2. 经典的Reactor模型
由于多线程模型难堪大用,所以更好的模型一直在研究之中,Reactor模型,作为天选之子,也被引入了进来,由于其强大的基于事件处理的特性,使得其成为异步模型的不二之选,其起源可以参考这篇文章。
Reactor模型由于是基于事件处理的,所以一旦有事件被触发,将会派发到对应的event handler中进行处理。所以在此模型中,有两个最重要的参与者,列举如下:
-
Reactor:主要用来将IO事件派发到相对应的handler中,可以将其想象为打电话时候的分发总机,你先打电话到总机号码,然后通过总机,你可以分拨到各个分机号码。 -
Handlers:主要用来处理IO事件相关的具体业务,可以将其想象为拨通分机号码后,实际上为你处理事件的员工。

上图 为Reactor模型的描述图,具体来说一下:
Initiation Dispatcher其实扮演的就是Reactor的角色,主要进行Event Demultiplexer,即事件派发。而其内部一般都有一个Acceptor,用于通过对系统资源的操纵来获取资源句柄,然后交由Reactor,通过handle_events方法派发至具体的EventHandler的。
Synchronous Event Demultiplexer其实就是Acceptor的角色,此角色内部通过调用系统的方法来进行资源操作,比如说,假如客户端连接上来,那么将会获得当前连接,假如需要删除文件,那么将会获得当前待操作的文件句柄等等。这些句柄实际上是要返回给Reactor的,然后经由Reactor派发下放给具体的EventHandler。
Event Handler这里,其实就是具体的事件操作了。其内部针对不同的业务逻辑,拥有不同的操作方法,比如说,鉴权EventHandler会检测传入的连接,验证其是否在白名单,心跳包EventHanler会检测管道是否空闲,业务EventHandler会进行具体的业务处理,编解码EventHandler会对当前连接传输的内容进行编码解码操作等等。
由于Netty是Reactor模型的具体实现,所以在编码的时候,我们可以非常清楚明白的理解Reactor的具体使用方式,这里暂时不讲,后面会提到。
由于Doug Lea写过一篇关于NIO的文章,整体总结的极好,所以这里我们就结合他的文章来详细分析一下Reactor模型的演化过程。

上图模型为单线程Reator模型,Reactor