Channel、EventLoop和ChannelFuture

Netty网络抽象的代表:

  • Channel ——Socket;
  • EventLoop ——控制流、多线程处理、并发;
  • ChannelFuture ——异步通知。

  • Channel

    基本的I/O操作(bind()connect()read()write() )依赖于底层网络传输所提供的原语。Netty的Channel 接口所提供的API,大大地降低了直接使用Socket 类的复杂性。

Channel 也是拥有许多预定义的、专门化实现类:

  • EmbeddedChannel;
  • LocalServerChannel;
  • NioDatagramChannel;
  • NioSctpChannel;
  • NioSocketChannel。


``

EventLoop接口

EventLoop 定义了Netty的核心抽象,用于处理连接的生命周期中所发生的事件。下图说明了ChannelEventLoopThread 以及EventLoopGroup 之间的关系。

image.png

  • 一个EventLoopGroup 包含一个或者多个EventLoop
  • 一个EventLoop 在它的生命周期内只和一个Thread 绑定;
  • 所有由EventLoop 处理的I/O事件都将在它专有的Thread 上被处理;
  • 一个Channel 在它的生命周期内只注册于一个EventLoop ;(一个Channel只能指向一个EventLoop)
  • 一个EventLoop 可能会被分配给一个或多个Channel 。(EventLoop可以包含多个Channel)

image.png

一个给定Channel 的I/O操作都是由相同的Thread 执行的,实际上消除了对于同步的需要。

ChannelFuture接口

Netty中所有的I/O操作都是异步的。因为一个操作可能不会立即返回,所以我们需要一种用于在之后的某个时间点确定其结果的方法。为此,Netty提供了ChannelFuture 接口,其addListener() 方法注册了一个ChannelFutureListener ,以便在某个操作完成时(无论是否成功)得到通知。


ChannelHandler和ChannelPipeline

ChannelHandler接口

从应用程序开发人员的角度来看,Netty的主要组件是ChannelHandler

ChannelHandler 的方法是由网络事件(其中术语“事件”的使用非常广泛)触发的。

ChannelPipeline接口

ChannelPipeline 提供了ChannelHandler 链的容器(通俗地将,ChannnelPipeline内部维护着一个ChannelHandler列表)

Channel在创建是会被自动分配到某个ChannelPipeline上。

ChannelHandler的执行顺序是由添加到ChannelPipeline的顺序决定的。

从一个客户端应用程序的角度来看,如果事件的运动方向是从客户端到服务器端,那么我们称这些事件为出站的 ,反之则称为入站的
image.png
图3-3也显示了入站和出站ChannelHandler 可以被安装到同一个ChannelPipeline 中。如果一个消息或者任何其他的入站事件被读取,那么它会从ChannelPipeline 的头部开始流动,并被传递给第一个ChannelInboundHandler 。这个ChannelHandler 不一定会实际地修改数据,具体取决于它的具体功能,在这之后,数据将会被传递给链中的下一个ChannelInboundHandler 。最终,数据将会到达ChannelPipeline 的尾端,届时,所有处理就都结束了。

ChannelHandler 被添加到ChannelPipeline 时,它将会被分配一个ChannelHandler-Context ,其代表了ChannelHandlerChannelPipeline 之间的绑定。虽然这个对象可以被用于获取底层的Channel ,但是它主要还是被用于写出站数据。

在Netty中,有两种发送消息的方式。你可以直接写到Channel 中,也可以写到和ChannelHandler 相关联的ChannelHandlerContext 对象中。

更加深入地了解ChannelHandler

ChannelPipeline 中的每个ChannelHandler 将负责把事件转发到链中的下一个ChannelHandler 。这些适配器类(及它们的子类)将自动执行这个操作,所以你可以只重写那些你想要特殊处理的方法和事件。

下面这些是编写自定义ChannelHandler时经常会用到的适配器类:

  • ChannelHandlerAdapter
  • ChannelInboundHandlerAdapter
  • ChannelOutboundHandlerAdapter
  • ChannelDuplexHandler


``

``

编码器和解码器

当你通过Netty发送或者接收一个消息的时候,就将会发生一次数据转换。入站消息会被解码 。

Netty为编码器和解码器提供了不同类型的抽象类。这些基类的名称将类似于ByteToMessageDecoderMessageToByte-Encoder

所有由Netty提供的编码器/解码器适配器类都实现了ChannelOutboundHandler 或者ChannelInboundHandler 接口。

抽象类SimpleChannelInboundHandler

你的应用程序会利用一个ChannelHandler 来接收解码消息,你只需要扩展基类SimpleChannel-InboundHandler<T> ,其中T 是你要处理的消息的Java类型。

引导

有两种类型的引导:一种用于客户端(简单地称为Bootstrap ),而另一种(ServerBootstrap )用于服务器。

image.png
引导一个客户端只需要一个EventLoopGroup ,但是一个ServerBootstrap 则需要两个。

因为服务器需要两组不同的Channel 。第一组将只包含一个ServerChannel ,代表服务器自身的已绑定到某个本地端口的正在监听的套接字。而第二组将包含所有已创建的用来处理传入客户端连接(对于每个服务器已经接受的连接都有一个)的Channel

image.png
ServerChannel 相关联的EventLoopGroup 将分配一个负责为传入连接请求创建ChannelEventLoop 。一旦连接被接受,第二个EventLoopGroup 就会给它的Channel 分配一个EventLoop