事件驱动的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>

全部评论

相关推荐

从小父母离异家里没人管,靠着心里的不安和学校的环境也算是坚持到了学有所成的地步。到了大学环境开始松散不知道该做什么,只觉得在不挂科的基础上能往上考多少就考多少,等到秋招来临才发现自己有多么幼稚无能,今年九月份初才发现自己原来连一个求职的方向都没有。因为之前做过前后端一体的课设,算是有过了解,而对于其他岗位连做什么都不知道,因此这一个半个月在越来越焦虑的同时埋头苦学,事到如今想要活下去我似乎只能走前端这条路了,9月初先是靠着虚假夸大能力的简历得到一些笔试来确定了考察的方向,有一个大厂的无笔试面试最终是拒绝了没有勇气去面对。然后在这个基础上埋头苦学,如今也算是搭好了自己前端学习的框架和思考的瞄,可以逐渐给自己扩展新的知识和能力了,但这并不是一件多好的事儿,因为我发现学的越多越焦虑,学的越多便越无力。因为我感觉我如今努力学习的知识都是竞争对手们早就掌握了的东西,我如今困惑追求答案的难题早就被别人解决。别人早就能得心应手地做出项目而我连思考都会卡壳,看着别人的笔试和面经上那些闻所未闻的题目,我才知道别人到底有多强而我有多幼稚,我什么时候才能达到别人那种堪称熟练的能力呢?而且网上的焦虑越多越多,即便是真有这么高的能力最后也大概落得一个低薪打工人的下场,我真的感到迷茫。秋招都快结束了,而我还在继续痛苦的学习之旅,这些天找前端面试发现似乎问的有些简单跟网上搜到的内容不符(可能因为并不是大厂),我是不是本来就没打算被招所以别人懒得细问呢?我不知道,我只能继续总结下去学习下去,不管如何我都要活下去,如果我能早一些准备就好了,如果暑假能意识到现在这个情况就好了,可惜没有如果。种下一棵树的最好时间是十年前,其次是现在,虽然我相信自己的学习能力,但已经错过了最好的时机,只能在焦虑与痛苦中每天坚持学下去。目前的路还有很长很长,先去把typescript看了,再去巩固vue3的基础,再去练习elementui的使用,如果这能找到实习的话就好了。接下来呢?去学uniapp和小程序,不管如何我都要对得起曾经努力的自己。即便我们都感到痛苦,但我心中还是希望我们都能靠自己的努力来获取自己想要的幸福。
紧张的牛牛等一个of...:在担心什么呢,有一手985的学历在,就算是小厂别人都会要的,咱们双非的人更多,多少还在沉沦的,怕什么了
一句话证明你在找工作
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务