事件驱动的Netty
前言
Netty官网对自己的描述是一个异步的事件驱动的网络框架。异步如何表现和异步背后的线程模型在上文已经分析过了。
事件驱动是Netty中另外一个非常重要的概念。Netty框架中描述的事件是一种抽象概念,其将框架运行过程中会发生的许多“动作”以事件的概念定义。并且在事件发生时,触发对应的回调方法。对于开发者而言,只需要实现自己感兴趣的事件的回调方法。因此,对于事件的回调方法的实现,构成了对Netty的主要使用。
简单的说,了解了Netty中的事件,也就掌握了大部分在Netty中进行业务开发所要使用的API。下面就来逐一的介绍这些事件。
事件的线程触发机制
在分析事件的触发条件和触发内容之前,需要再明确几个要点:
- Netty的事件是一种抽象的概念,事件的触发在代码上表现为
ChannelHandler上某个具体方法的调用 - 一个
ChannelHandler会被唯一一个线程所绑定,其事件触发的所有代码都是在这个线程上被串行执行。 - 当
ChannelHandler没有显示指定绑定的线程时,直接绑定于ChannelHandler关联的Channel所绑定的线程
查看Netty的代码,大部分事件方法都有如下的模板式代码

这个模式方法实际上就是在践行“ChannelHandler上的方法都是在其绑定的线程上串行执行”这个原则。如果要执行事件方法的线程不是其绑定线程,则将事件方法的执行包装为一个runnable对象,投入到该绑定线程的任务队列中,等待后续被该线程取出处理。而如果当前线程就是其绑定线程,则直接执行事件方法。
事件的传递机制
在前文中我们提到过管道的概念,也就是pipeline机制。事件的流转方向根据入站和出站的不同,入站是从pipeline头部向尾部传递的,而出站是从尾巴向头部传递。
pipeline上事件的传递并不是每一个ChannelHandler都会经历,而是只有实现了对应的事件方法的ChannelHandler才会被传递到这个事件。并且每一个ChannelHandler可以决定是否继续向后传递这个事件。如果想要继续传递这个事件,一般而言都需要调用方法ctx.fireXXXX来将事件继续传递。而如果什么都不做的话,事件传递就到此为止了。整体的控制权都在用户的手里。
简而言之就是两个重要原则:
- 实现了对应事件方法的
ChannelHandler才会传递给对应的事件 - 可以通过
ChannelHandlerContext.fireXXXX来决定是否继续传递事件
由于ChannelHandler可以决定是否继续传递事件,因此后续的事件触发分析都是针对管道中的第一个ChannelHandler。
公共事件
公共事件被定义在接口io.netty.channel.ChannelHandler中。每一个业务实现都会实现这个接口。但是更具体的,一般是要实现进站事件接口或者出站事件接口。单纯只是实现这个接口,则无法实现业务所需。
handlerAdded
当一个Channel的管道pipeline上添加了一个ChannelHandler实例时,添加事件被触发,handlerAdded方法被触发。
这里有个注意点,在一个Channel刚生成时,其上还没有绑定线程。此时如果有ChannelHandler被添加到管道上,handlerAdded方法暂时不会被触发。但是会将需要触发的handlerAdded方法的对象实例存储在一个列表中,等到channel绑定到一个线程上时,就会从这个列表上拿出所有的实例,触发其handlerAdded方法。
为什么会有这样的取舍,主要还是在于Netty的设计原则:ChannelHandler上的所有方法调用都串行的执行于其唯一绑定线程。通过这种方式,也保证了事件触发的先后顺序。在ChannelHandler中,handlerAdded方法必然是所有事件中最先被触发的,而后才是其他的事件。也很好理解,只有添加了,才能执行后续的事件动作。
handlerRemoved
当ChannelHandler从一个管道上被删除时,handlerRemoved事件被触发。
一般而言我们会执行方法io.netty.channel.ChannelPipeline#remove(java.lang.String)去删除一个ChannelHandler。同样的,基于任何事件都需要在ChannelHandler绑定的线程上执行,即使被删除也是一样。如果执行remove的线程就是其绑定线程,则直接触发handlerRemoved方法,否则将方法调用包装为runnable任务,投递到线程的任务队列中等待后续执行。
入站事件
按照数据的流动方向,数据的读取处理属于入站事件,即从通道流向的。入站事件都定义在接口上。大多数时候开发者不会对每一个事件都感兴趣,Netty也提供了一个适配器抽象类。开发者只需要实现自己感兴趣的事件就
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
<p> 通过本专刊的学习,对网络开发所需掌握的基础理论知识会更加牢固,对网络应用涉及的线程模型,设计模式,高性能架构等更加明确。通过对Netty的源码深入讲解,使得读者对Netty达到“知其然更之所以然”的程度。在遇到一些线上的问题时,具备了扎实理论功底的情况,可以有的放矢而不会显得盲目。 本专刊购买后即可解锁所有章节,故不可以退换哦~ </p> <p> <br /> </p>

