netty的核心组件(netty in action读书摘要)

  从高层次的说,Netty解决了两个相应的关注领域,我们可将其大致的标记为技术的,和体系结构的.首先,它的基于 Java NIO 的异步的和事件驱动的实现,保证了高负载下应用程序性能的最大化和可伸缩性。其次,Netty 也包含了一组设计模式,将应用程序逻辑从网络层解耦,简化了开发过程,同时也最大限度地提高了可测试性、模块化以及代码的可重用性.
  在我们更加详细地研究 Netty 的各个组件时,我们将密切关注它们是如何通过协作来支撑这些体系结构上的最佳实践的。通过遵循同样的原则,我们便可获得 Netty 所提供的所有益处。牢记这个目标,在本章中,我们将回顾到目前为止我们介绍过的主要概念和组件。

Channel -> Socket
EventLoop -> 控制流,多线程处理,并发
ChannelFuture -> 异步通知
这些类可以被认为是Netty网络抽象的代表.

Channel

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

EventLoop

  EventLoop定义了Netty的核心抽象,用于处理连接的生命周期中所发生的事件.
Channel、EventLoop、Thread 以及 EventLoopGroup 之间的关系.


image.png

这些关系是:
 一个 EventLoopGroup 包含一个或者多个 EventLoop;
 一个 EventLoop 在它的生命周期内只和一个 Thread 绑定;
 所有由 EventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理;
 一个 Channel 在它的生命周期内只注册于一个 EventLoop;
 一个 EventLoop 可能会被分配给一个或多个 Channel。
注意,在这种设计中,一个给定 Channel 的 I/O 操作都是由相同的 Thread 执行的,实际上消除了对于同步的需要.

ChanelFuture

  正如我们已经解释过的那样,Netty 中所有的 I/O 操作都是异步的。因为一个操作可能不会立即返回,所以我们需要一种用于在之后的某个时间点确定其结果的方法。为此,Netty 提供了ChannelFuture 接口,其 addListener()方法注册了一个 ChannelFutureListener,以便在某个操作完成时(无论是否成功)得到通知。关于 ChannelFuture 的更多讨论 可以将 ChannelFuture 看作是将来要执行的操作的结果的占位符。它究竟什么时候被执行则可能取决于若干的因素,因此不可能准确地预测,但是可以肯定的是它将会被执行。此外,所有属于同一个 Channel 的操作都被保证其将以它们被调用的顺序被执行。
我们将在第 7 章中深入地讨论 EventLoop 和 EventLoopGroup

ChannelHandler和ChannelPipeline

管理数据流以及执行应用程序处理逻辑的组件.

  从应用程序开发人员的角度来看,Netty 的主要组件是ChannelHandler,它充当了所有处理入站和出站数据的应用程序逻辑的容器。

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

ChannelHandler 安装到 ChannelPipeline 中的过程如下所示:
 一个ChannelInitializer的实现被注册到了ServerBootstrap中
 当 ChannelInitializer.initChannel()方法被调用时,ChannelInitializer将在 ChannelPipeline 中安装一组自定义的 ChannelHandler;
 ChannelInitializer 将它自己从 ChannelPipeline 中移除。
  使得事件流经 ChannelPipeline 是 ChannelHandler 的工作,它们是在应用程序的初始化或者引导阶段被安装的。这些对象接收事件、执行它们所实现的处理逻辑,并将数据传递给链中的下一个 ChannelHandler。它们的执行顺序是由它们被添加的顺序所决定的。实际上,被我们称为 ChannelPipeline 的是这些 ChannelHandler 的编排顺序.

出站和入站

图 3-3 说明了一个 Netty 应用程序中入站和出站数据流之间的区别。从一个客户端应用程序的角度来看,如果事件的运动方向是从客户端到服务器端,那么我们称这些事件为出站的,反之则称为入站的。


image.png

  图 3-3 也显示了入站和出站 ChannelHandler 可以被安装到同一个 ChannelPipeline中。如果一个消息或者任何其他的入站事件被读取,那么它会从 ChannelPipeline 的头部开始流动,并被传递给第一个 ChannelInboundHandler。这个 ChannelHandler 不一定会实际地修改数据,具体取决于它的具体功能,在这之后,数据将会被传递给链中的下一个ChannelInboundHandler。最终,数据将会到达 ChannelPipeline 的尾端,届时,所有处理就都结束了。
  数据的出站运动(即正在被写的数据)在概念上也是一样的。在这种情况下,数据将从ChannelOutboundHandler 链的尾端开始流动,直到它到达链的头部为止。在这之后,出站数据将会到达网络传输层,这里显示为 Socket。通常情况下,这将触发一个写操作.

netty两种发消息的方式

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

更深入的了解ChannelHandler。

有许多不同类型的ChannelHandler。他们各自的功能主要取决于他们的超类。Netty 以适配器类的形式提供了大量默认的 ChannelHandler 实现,其旨在简化应用程序处理逻辑的开发过程。

为什么需要适配器

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

编码解码

  当你通过netty发送或者接受一个消息的时候,就会发生一次数据转换。入站消息会被解码,从字节转换成对象。如果是出站消息,就会发生相反方向的转换。这两种方向的转换的原因很简单:网络数据总是一系列的字节。

引导

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

Bootstrap

1.想要连接到远程节点的客户端应用程序所使用的。
2.引导一个客户端只需要一个 EventLoopGroup

ServerBootstrap

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


image.png

  与 ServerChannel 相关联的 EventLoopGroup 将分配一个负责为传入连接请求创建Channel 的 EventLoop。一旦连接被接受,第二个 EventLoopGroup 就会给它的 Channel分配一个 EventLoop。(会专门记录下这个分配过程的源码)

你可能感兴趣的:(netty的核心组件(netty in action读书摘要))