一起来学习Netty的管理数据流和业务逻辑处理组件

209 阅读5分钟

这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战

一、ChannelHandler和ChannelPipeline

1、ChannelHandler接口

  从应用程度开发人员的角度来看,Netty的主要组件是ChannelHandler,它充当了所有处理入站和出站数据的应用程序逻辑的容器。事实上,ChannelHandler可专门用于几乎任何类型的动作,例如将数据从一种格式转换为另一种格式,或者处理转换过程中所抛出的异常。

2、ChannelPipeline接口

  ChannelPipeline为ChannelHandler链提供了容器,并定义了用于在该链上传播入站和出站事件流的API。当Channel被创建时,它会被自动地分配到它专属的ChannelPipeline。
ChannelHandler安装到ChannelPipeline中的过程如下所示:

  • 一个ChannelInitializer的实现被注册到了ServerBootstrap中或Bootstrap中;
  • 当ChannelInitializer.initChannel()方法被调用时,ChannelInitializer将在ChannelPipeline中安装一组自定义的ChannelHandler;
  • ChannelInitializer将它自己从ChannelPipeline中移除。

  ChannelHandler是专为支持广泛的用途而设计的,可以将它看作是处理往来ChannelPipeline事件(包括数据)的任何代码的通用容器。下图说明了这一点,其展示了从ChannelHandler派生的ChnanelInboundHandler和ChannelOutboundHandler接口。

image.png   使得事件流经ChannelPipeline是ChannelHandler的工作,它们是应用程序的初始化或者引导阶段被安装的。这些对象接收事件、执行它们所实现的处理逻辑,并将数据传递给链中的下一个ChannelHandler。它们的执行顺序是由它们被添加的顺序所决定的。实际上,被我们称为ChannelPipeline的是这些ChanelHandler的编排顺序。
  下图说明了一个Netty应用程序中入站和出站数据流之间的区别。从一个客户端应用程序的角度来看,如果事件运动方向是从客户端到服务器端,那么我们称这些事件为出站的,反之则徐称为入站的。

image.png

  在Netty中,有两种发送消息的方式。一种是直接写到Channel中,另一种写到和ChannelHandler相关联的ChannelHandlerContext对象中。前一种方式将会导致消息从ChannelPipeline的尾端开始流动,而后者导致消息从ChannelPipeline中的下一个ChannelHandler开始流动。

3、编码器和解码器

  当你通过Netty发送或者接收一个消息的时候,就将会发生一次数据转换。入站消息会被解码;也就是说,从字节转换为另一种格式,通常是一个Java对象。如果是出站消息,则会发生相反方向的转换:它将从它的当前格式被编码为字节。这两种方向的转换的原因很简单:网络数据总是一系列的字节。
  通常来说,其他的处理器也可以完成编码器和解码器的功能。但是,正如有用来简化ChannelHandler的创建的适配器类一样,所有由Netty提供的编码器/解码器适配类都实现了ChannelOutboundHandler或者ChannelInboundHandler接口。
  对于入站数据来说,channelRead方法/事件已经被重写了。对于每个从入站Channel读取的消息,这个方法都将会被调用。随后,它将调用由预置解码器所提供的decode()方法,并将已解码的字节转发给ChannelPipeline中的下一个ChannelInboundHandler。出站消息的模式是相反方向的:编码器将消息转换为字节,并将它们转发给下一个ChannelOutboundHandler。

4、抽象类SimpleChannelInboundHandler

  最常见的情况是,你的应用程序会利用一个ChannelHandler来接收解码消息,并对该数据应用业务逻辑。要创建一个这样的ChannelHandler,你只需要扩展基类SimpleChannelInboundHandler<T>,其中T是你要处理的消息的Java类型。在这个ChannelHandler中,你将需要重写基类的一个或者多个方法,并且获取一个到ChannelHandlerContext的引用,这个引用将作为输入参数传递给ChannelHandler的所有方法。
  在这种类型的ChannelHandler中,最重要的方法是channelRead0(ChannelHandlerContext,T)。

二、引导

  Netty的引导类为应用程序的网络层配置提供了容器,这涉及将一个进程绑定到某个指定的端口,或者将一个 进程连接到另一个运行在某个指定主机的指定端口上的进程。
  因此,有两种类型的引导:一种用于客户端(简单地称为Bootstrap),而另一种(ServerBootstrap)用于服务器。下表比较了这两种类型的引导类。

类  别BootstrapServerBootstrap
网络编程中的作用连接到运程主机和端口绑定到一个本地端口
EventLoopGroup的数目12

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

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