不灭的焱

革命尚未成功,同志仍须努力

作者:php-note.com  发布于:2018-09-23 17:32  分类:Java库/系统 

1.3 Netty’s core components

 

 在这个章节中,我们将浅析Netty的几个核心组件

  1)Channels

  2)Callbacks

  3) Futures

  4) Events and handlers

 

这些构建模块代表了不同的结构种类:资源,逻辑,和通知,你的应用可以使用这些连接到网络,并且通过这些这些获取到数据流

对于每一个组件而言,我们将给一个最基本的定义,并且给出一个合适简单的例子说明它的作用

 

1.3.1 Channels

 

channel就是JAVA NIO中一个最基本的组件,它表示:

与某个模型的连接,例如与硬件设备,与某个文件,或者网络的socket,抽象地可以是程序组件中的一次或者多次的不同的I/O操作

 

现在,你可以将Channel想象成一个货车,用来装载或者卸载数据的货车,因此,这个“货车”可以打开关闭,连接或者关闭连接

 

1.3.2 Callbacks

 

回调可以简单的这么理解,定义一个方法,这个方法的引用被另一个方法所持有,这样做的好处就是另一个方法可以在一个恰当的时候“回头”调用这个方法

回调这种方式被大量的编程环境中被使用,并且当某些事件完成的时候,回调可以作为一个最为常见的普通方式来通知某些对应的组件

Netty内部使用回调来处理事件,我们举一个Netty使用回调的例子,例如当回调被触发的时候,有些类如果实现了ChannelHandler接口的话,里面定义的方法将会被执行,下面的代码清单展现了一个简单的回调的例子:当有一个新的连接建立的时候,实现ChannelHandler接口ConnectHandler的channelActive方法将被回调执行,然后会打印一个信息

 

1.3.3 Futures

 

Futue提供了另外一种方法来通知其他的组件已经有一个操作完成了,Future这个对象表演的角色就像一个异步操作的结果的占位符,先占着地方,等操作结束了,操作返回了一个结果集,再用这个结果集将刚才Future占好位置填充好

 

JDK有默认的Future实现,位于java.util.concurrent.Future,但是有缺陷,原生的Future的实现需要你手动去检查操作是否完成,需要你去循环去检查它是否完成,这是相当的麻烦,所以Netty提供了它自己的实现-----ChannelFuture,用来当异步操作已经被执行完成的时候来获取操作的结果

 

ChannelFuture提供了额外的方法来允许我们注册一个或者多个的ChannelFutureListener的实例,监听着的回调方法----operationComplete()将在一个操作完成的时候执行,监听器还可以做更加细致的工作,它可以确定你的操作是否正确成功执行,错误执行还是执行的时候发生了异常

 简而言之,由ChannelFutureListener提供的通知机制可以使我们不需要手动去循环查询操作是否已经执行结束

 

每一个Netty外在的I/O操作都将返回一个ChannelFuture,并且没有一个是阻塞的,我们很早之前说过,Netty是一个异步的基于事件驱动的模型框架

 

代码清单1.3展示了一个ChannelFuture作为一个I/O操作的结果返回了,在这里,请注意connect()方法将直接返回,没有任何阻塞,回调将在后台完成,返回之后,到底是否连接成功,我们并不知道,即将要发生什么取决于一些未知的因素,但是这些已经被Netty抽象了,在代码层次是看不出来的,与此同时,当前的连接线程不会阻塞等待连接操作的完成,它可以同时去做一些其他的事情,来达到资源更加高效的运用

代码清单1.4向我们展示如何利用ChannelFutureListener,首先你去连接一个远程的节点,然后你将ChannelFutureListener这个注册到connect()方法返回的ChannelFuture上,当监听器被通知连接建立上的时候,你可以检查连接的状态(①),如果连接成功了,你可以写入一些数据到Channel中,否则你将从channelFuture中获取抛出的异常

 

注意一点:处理异常完全取决于你个人,具体异常具体分析,可以做不同的处理,举例来说,如果连接失败了,你可以尝试去重新连接到另一台远程主机

 

到目前为止,如果你觉得ChannelFutureListener是一个更加精致的更加高级的回调,你的理解是对的,事实上,回调和Future是互补的,联合他们。或者说更好的灵活运用他们是Netty框架构建的关键之一

 

1.3.4 Events and handlers

 

Netty使用不同的事件来通知我们状态的改变或者操作状态的改变,这将使我们更加方便地根据返回的事件的种类的不同触发相对应的事件处理,一般对应的事件处理包括:

1)日记处理

2)数据传输

3)流信息控制

4)应用程序逻辑处理

 

Netty是一个网络框架,所以事件是按照他们关联的输入输出流来区分的,事件可能是因为输入数据或者是因为某些状态的改变而被触发,包括:

1) 活跃或者不活跃的连接

2) 数据读取

3) 用户事件

4) 错误事件

 

一个输出事件是一个操作的结果,它可能在未来会触发一个动作,可能会是:

1) 打开或者关闭一个远程主机的连接

2) 写入数据并刷入数据到socket

 

每一个事件都可以分派给用户自定义的处理器去处理,Netty是一个很好的例子,将事件驱动模型的理念转化为具体的应用实现,图1.3展示了一个事件可以被一系列的事件处理器处理

Netty的ChannelHandler可以提供自定义处理器的基本抽象就如我们上图1.3中展示的那样,我们将在对应的章节详细讲解一下ChannelHandler这个对象,但是此时你可以把每一个处理器实例想象成一个回调函数被调用来响应你的具体的事件请求

 

Netty提供了大量的预定义的处理器供你使用,其中包括例如Http,SSL和TLS等协议的处理器,Netty内部使用事件和future这些机制来实现ChannelHandler,这样就可以使我们这些使用Netty的人采用相同的抽象去完成事情

 

1.3.5 Putting it all together

 

在这个章节中,我们已经向你简述了Netty的高性能网络之道,同时也简述了一些核心组件的具体实现,让我们在自己的心中将上述讲的绘画成一张架构蓝图吧~

 

FUTURES,CALLBACKS,AND HANDLERS

Netty的异步编程模型是建立在回调和Future这两个思想基础之上的,不同的事件处理分发给不同的处理器去处理也是设计理念之一,将这些设计理念合理的糅合在一起,效果也是很明显的,可以使你的应用逻辑处理,更加独立于网络的操作,这也是Netty的最最核心的设计之道

 

如果拦截或者转换正在传输的输入输出数据,对于你来说,是很简单的,只需要你在网络操作时返回的回调或者future函数中写出自己自定义的逻辑实现就可以了,链式处理的操作将会变得更加高效和简单,同时这也会促进你写出更加可重复利用易懂的代码

 

SELECTORS,EVENTS,AND EVENT LOOPS

Netty通过触发事件来将Selector从你的应用中抽象出来,为了消除所有主动通过手动的方式来调度事件所触发对应方法的冗余代码,Netty幕后使用EventLoop,用EventLoop分配给每一个Channel来处理所有的事件,包括如下:

1)注册所有自己关注的事件

2)分发或者调度对应的事件给那些注册该事件的ChannelHandlers

3)指定下一个处理流程

 

EventLoop本身就是仅有一个线程去驱动的,但是它可以管控一个Channel的所有I/O事件,并且在EventLoop整个生命周期也不会变更,仅此一个线程实例,如此简单且高效的设计应该可以消除你们自定义的ChannelHandlers的异步操作处理的所有顾虑了吧,所以你只需要关注当你感兴趣的数据传输的时候给出正确的逻辑处理然后正确的执行就可以了,在接下来的章节我们将会进一步去探索Netty的线程模型,线程模型的API还是很简洁实用的

 

1.4 Summary

 

在这个章节中,我们学习了Netty框架的背景,包括java网络编程的API的进化史,阻塞和非阻塞IO操作的不同,高吞吐量高性能的异步I/O的优越性

然后,我们大体介绍了Netty的一些特性,设计或者优点,这些都包括Netty的异步模型机制,回调,Future或者这两者的结合,我们也谈到了事件是如何产生并触发的,事件是如何被拦截处理的

接下来的章节里,我们将更加深入的介绍,看看Netty这个丰富框架工具如何满足我们日常开发的需要的

在下一个章节中,我们将研究一下最基本的Netty的API和编程模型,并且你将自己亲自写一个Netty的服务器端和客户端

 

 

摘自:https://blog.csdn.net/linuu/article/details/51075484