zoukankan      html  css  js  c++  java
  • Netty组件

    一、Channel、EventLoop 和ChannelFuture

    这些类合在一起,可以被认为是Netty 网络抽象的代表:

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

    Channel 接口  

      基本的I/O 操作(bind()、connect()、read()和write())依赖于底层网络传输所提供的原语。在基于Java 的网络编程中,其基本的构造是class Socket。Netty 的Channel 接
    口所提供的API,大大地降低了直接使用Socket 类的复杂性。此外,Channel 也是拥有许多预定义的、专门化实现的广泛类层次结构的根,下面是一个简短的部分清单:

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

    EventLoop 接口
    EventLoop 定义了Netty 的核心抽象,用于处理连接的生命周期中所发生的事件。我们将在第7 章中结合Netty 的线程处理模型的上下文对EventLoop 进行详细的讨论。目前,图3-1
    在高层次上说明了Channel、EventLoop、Thread 以及EventLoopGroup 之间的关系。

    这些关系是:

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

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

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

    关于ChannelFuture 的更多讨论 可以将ChannelFuture 看作是将来要执行的操作的结果的占位符。它究竟什么时候被执行则可能取决于若干的因素,因此不可能准确地预测,但是可以肯定的是它将会被执行。此外,所有属于同一个Channel 的操作都被保证其将以它们被调用的顺序被执行。
    我们将在第7 章中深入地讨论EventLoop 和EventLoopGroup。

    二、ChannelHandler 和ChannelPipeline

    2.1、ChannelHandler 接口

    从应用程序开发人员的角度来看,Netty 的主要组件是ChannelHandler,它充当了所有处理入站和出站数据的应用程序逻辑的容器。这是可行的,因为ChannelHandler 的方法是
    由网络事件(其中术语“事件”的使用非常广泛)触发的。事实上,ChannelHandler 可专门用于几乎任何类型的动作,例如将数据从一种格式转换为另外一种格式,或者处理转换过程
    中所抛出的异常。
    举例来说,ChannelInboundHandler 是一个你将会经常实现的子接口。这种类型的ChannelHandler 接收入站事件和数据,这些数据随后将会被你的应用程序的业务逻辑所处
    理。当你要给连接的客户端发送响应时,也可以从ChannelInboundHandler 冲刷数据。你的应用程序的业务逻辑通常驻留在一个或者多个ChannelInboundHandler 中。

    2.2、ChannelPipeline 接口

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

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

    为了审查发送或者接收数据时将会发生什么,让我们来更加深入地研究ChannelPipeline和ChannelHandler 之间的共生关系吧。
    ChannelHandler 是专为支持广泛的用途而设计的,可以将它看作是处理往来ChannelPipeline 事件(包括数据)的任何代码的通用容器。图3-2 说明了这一点,其展示了从Channel-
    Handler 派生的ChannelInboundHandler 和ChannelOutboundHandler 接口。

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

    2.3、更加深入地了解ChannelHandler

    正如我们之前所说的,有许多不同类型的ChannelHandler,它们各自的功能主要取决于它们的超类。Netty 以适配器类的形式提供了大量默认的ChannelHandler 实现,其旨在简化
    应用程序处理逻辑的开发过程。你已经看到了,ChannelPipeline中的每个ChannelHandler将负责把事件转发到链中的下一个ChannelHandler。这些适配器类(及它们的子类)将自动执行这个操作,所以你可以只重写那些你想要特殊处理的方法和事件。

    为什么需要适配器类
    有一些适配器类可以将编写自定义的ChannelHandler 所需要的努力降到最低限度,因为它们提
    供了定义在对应接口中的所有方法的默认实现。
    下面这些是编写自定义ChannelHandler 时经常会用到的适配器类:
     ChannelHandlerAdapter
     ChannelInboundHandlerAdapter
     ChannelOutboundHandlerAdapter
     ChannelDuplexHandler

    2.4、3 个ChannelHandler 的子类型:编码器、解码器和SimpleChannelnboundHandler<T> —— ChannelInboundHandlerAdapter 的一个子类。

    编码器和解码器

    入站消息会被解码;也就是说,从字节转换为另一种格式,通常是一个Java 对象。

    出站消息,则会发生相反方向的转换:它将从它的当前格式被编码为字节。

    这两种方向的转换的原因很简单:网络数据总是一系列的字节。

    Netty中的解码和编码的基类的名称将类似于ByteToMessageDecoder 或MessageToByteEncoder。对于特殊的类型,你可能会发现类似于ProtobufEncoder 和ProtobufDecoder
    这样的名称——预置的用来支持Google 的Protocol Buffers。除此之外,Netty还提供了一些编码器/解码器适配器类,这些适配器类都实现了ChannelOutboundHandler 或者ChannelInboundHandler 接口。

    三、引导类

      Netty 的引导类为应用程序的网络层配置提供了容器,这涉及将一个进程绑定到某个指定的端口,或者将一个进程连接到另一个运行在某个指定主机的指定端口上的进程。
    通常来说,我们把前面的用例称作引导一个服务器,后面的用例称作引导一个客户端。虽然这个术语简单方便,但是它略微掩盖了一个重要的事实,即“服务器”和“客户端”实际上表示了不同的网络行为;换句话说,是监听传入的连接还是建立到一个或者多个进程的连接。

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

    比较Bootstrap 类

    类 别 Bootstrap  ServerBootstrap
    网络编程中的作用 连接到远程主机和端口 绑定到一个本地端口
    EventLoopGroup 1 2①

    注释:ServerBootstrap 类也可以只使用一个EventLoopGroup,此时其将在两个场景下共用同一个EventLoopGroup。

    这两种类型的引导类之间的第一个区别已经讨论过了:ServerBootstrap 将绑定到一个端口,因为服务器必须要监听连接,而Bootstrap 则是由想要连接到远程节点的客户端应用程
    序所使用的。
    第二个区别可能更加明显。引导一个客户端只需要一个EventLoopGroup,但是一个ServerBootstrap 则需要两个(也可以是同一个实例)。为什么呢?

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

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

  • 相关阅读:
    autolayout--约束的优先级
    CV
    iOS及Mac开源项目和学习资料(超级全面)
    终端中命令总结
    git使用方法笔记
    Shell命令
    git-在控制台下向gitHub中的repository中上传一个文件
    iOS
    iOS -雪花动画
    copy语法
  • 原文地址:https://www.cnblogs.com/duanxz/p/3724426.html
Copyright © 2011-2022 走看看