Netty源码(一)Netty架构解析

前言

 分析一个框架的源码首先要知道这个框架的设计思路是什么,是基于什么原理去实现的。不然直接去看源码,很容易丢失在代码的海洋,比如看Spring源码要先知道IOC和AOP是什么,Mybatis要知道动态代理的概念。而学习Netty最关键的要知道NIO和Reactor模式,本文将简单介绍NIO与Reactor的概念,重点说明Netty的关键组件和它们之间的协同关系,先了解Netty是怎么工作的再去分析源码就比较轻松。
 本文将介绍:

  1. NIO
  2. Reactor
  3. Netty核心组件
  4. Netty工作流程

这些概念有的不会特别详细的去介绍,只是做一个大概的介绍,如果要深入了解还需要去查看其它资料,这里只是对Netty的工作流程和基本原理的介绍。

I/O模型

 学习Netty要先知道NIO,而学习NIO要先了解IO多路复用。IO多路复用是指由一个线程去管理多个IO通道,通过轮询或者事件回调的形式将检测到的IO事件通知出去,实现单线程管理多个IO。
 NIO则是JAVA基于IO多路复用的实现,NIO三大组件Selector、Channel、Buffer。其中Selector 是Java 的非阻塞 I/O 实现的关键,用于管理一组套接字,监听其IO事件(如读、写、连接),当所监听事件就绪之后会理解返回。Channel是对I/O操作事件的抽象,可以使文件的读写,网络的传输等,Buffer是数据的载体。

NIO模型

 由上图所示,使用NIO用较少的线程便可以处理许多连接,因此也减少了内存管理和上下文切换所带来开销,而且是基于事件驱动,在事件未发生时线程可以做其他事情。本文只是简单介绍NIO与IO多路复用如果想要深入了解可以查看其它资料和我之前写的Java NIO与Reactor模式,总而言之基于JAVA所提供的NIO我们可以编写基于IO事件驱动的代码,而非传统IO的阻塞式编程。

Reactor模式

 编写基于NIO的事件驱动框架,就不得不提Reactor模式,基于网络事件驱动的设计思想。


Reactor

 Reactor模式有两个关键角色mainReactor负责监听连接事件和subReactor负责监听读写事件。其工作流程是:mainReactor不断监听连接事件,一旦有新的连接接入,将其转交给一个为acceptor的角色。acceptor拿到新的连接之后将其注册到subReactor上,由subReactor去负责这个Channel的读写事件。而subReactor只关心和处理读写事件,所有有关业务操作的流程交给一个线程池去处理,这样能使整个处理流程不会阻塞,吞吐量很高。
 其工作模式很像一个流水线的工厂,有老板去接项目,然后交给员工去处理加工,分工明确,高效处理。

核心组件

 在正式介绍Netty工作原理之前先介绍Netty的几个关键组件。

  • EventLoop
    EventLoop是Netty中最重要的组件,相当于上图的reactor角色,负责IO事件的监听,任务的处理是整个流程最关键的部分,关于EventLoop后续我会详细的介绍,这里做一个简单的介绍。
  • EventLoopGroup
    EventLoopGroup顾名思义,管理多个EventLoop。
  • Channel
    Channel是能够进行IO操作组件的抽象,如读、写、连接和绑定。
  • ChannelHandler
    ChannelHandler是我们使用Netty开发最关心的一个组件,它是对IO事件的具体处理逻辑。
  • ChannelPipeline
    ChannelPipeline则是ChannelHandler的容器,本质是一个双向链表,将所有的ChannelHandler按照顺序连接起来,后续也会对ChannelPipeline进行详细的介绍。

这些组件有如下关系:

  1. 一个 EventLoopGroup 包含一个或者多个 EventLoop;
  2. 一个 EventLoop 在它的生命周期内只和一个 Thread 绑定;
  3. 一个EventLoop管理一个或者多个Channel;
  4. 一个 Channel 在它的生命周期内只注册于一个 EventLoop;
  5. 所有由 EventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理;
  6. 一个Channel对应一个ChannelPipeline。
关系图

服务架构

Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients.

 Netty是异步事件驱动的框架,异步意味着Netty的所有IO操作都是非阻塞的,事件驱动是由事件发生之后,主动去通知,将事件散播出去,达到对事件处理的有效性和及时性。下图是Netty的工作流程:

工作流程

 Netty的整体工作流程与Ractor模式差不多,都是由一个负责监听连接事件,另一个负责读写事件。由bossGroup将连接的channel转交给acceptor,然后acceptor将Channel注册到的workGroup中,有workGroup去处理读写事件。
 EventLoop是一个单线程的死循环在它的生命周期中只做三件事情:

  1. select: 返回EventLoop所持有的selector上已经准备就绪的Channel;
  2. processSelectedKeys: 处理准备就绪的IO操作;
  3. ranTasks: 执行队列里的任务;

其实可以把netty看做一个黑工厂,员工和老板都是24小时不间断工作的狂人,非常有自律性24小时内循环不断的做三件事情,1、检查新分配的工作(select);2、处理已分配的工作(processSelectedKeys);3、执行其他渠道分配的任务(ranTasks)。当一个客户端连接之后,boos检测到了新分配的工作,boss对这个新建立的连接(Channel)之后自己做一些简单的处理之后,转交给work。work也检测到了新的事件发生,开始处理读写事件,其中每次事件的处理都会通知Channel所对应的ChannelPipeline,将事件传播出去。

总结

 本文对netty的工作流程和基本原理做了一个简单的梳理,后续的文章会详细分析netty的源码。先了解netty的整个流程不需要每个点都了解的很细,站在高度去学习之后再深入了解,学习一些框架源码,个人喜欢分析组件之间的关系,和为什么这样去设计和这样设计的思想是什么,对于具体的代码细节分析的不是很多,重要的思想,代码是其次的。希望本文对大家学习netty有所帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。