netty in action 笔记 一
Netty的异步模型是建立在Future和回调的基础之上,将事件派发到ChannelHandler的方法之上。
1. channel:一个到实体的开放连接,传出(出站)或传入(入站)数据的载体。为每个channel分配一个EventLoop,用以处理所有事件,这些事件包括:
a. 注册感兴趣的事件
b. 将事件派发给ChannelHandler
c. 安排进一步的动作
EventLoop本身由一个线程驱动,处理一个Channel所有的IO事件。
每个Channel 都将会被分配一个ChannelPipeline 和ChannelConfig。ChannelConfig 包含了该Channel 的所有配置设置,并且支持热更新。ChannelPipeline 持有所有将应用于入站和出站数据以及事件的ChannelHandler 实例,这些ChannelHandler 实现了应用程序用于处理状态变化以及数据处理的逻辑。ChannelPipeline 实现了一种常见的设计模式—拦截过滤器(上一个ChannelHandler的输出作为下一个ChannelHandler的输入)。
2. 回调:一个指向方法实体的引用。用于在调用端通知对方。
3. Future,该对象作为一个异步操作结果返回的占位符,在未来某个时刻提供对结果访问,只能手动检查对应操作是否完成。
Netty提供了自己的实现==>ChannelFuture,可以在该对象上注册ChannelFutureListenner实例(监听器),在操作完成时,监听器调用operationComplete(),以了解操作完成后的状态。每个netty 的IO操作都会返回一个ChannelFuture对象,不阻塞。
4. 事件和channelHandler:
Netty使用不同的事件来通知我们状态的改变或是操作的状态,是我们基于这些状态来触发适当的动作(如记录日志,数据转换,流控制,应用逻辑)。事件可以大体分类为出站 和入站事件(有更细节分类),随后分发给ChannelHandler类中的用户方法处理,Channelhandler可以看着是为响应某些事件而执行的回调。ChannelHandler,它充当了所有
处理入站和出站数据的应用程序逻辑的容器。
a. 针对不同类型的事件来调用不同的channelHandler实现。
b. 应用程序通过实现或扩展channelHandler来挂钩到事件的生命周期,提供自定义应用程序逻辑。
c. 在架构上,ChannelHandler使网络处理代码与业务逻辑分离。
Channel EventLoop及EventLoopGroup的关系:
一个EventLoopGroup包含一个或多个EventLoop;
一个EventLoop在它的生命周期内只和一个Thread绑定
所有由EventLoop处理的I/O事件都将在它专有的Thread上被处理
一个channel在它的生命周期内只注册于一个EventLoop
一个EventLoop可能会被分配给一个或多个Channel
所有属于同一个channel的操作将按它们的调用顺序执行,返回channelFuture.
ChannelPipeline :
ChannelPipeline 提供了ChannelHandler 链的容器,并定义了用于在该链上传播入站和出站事件流的API。当ChannelHandler 被添加到ChannelPipeline 时,它将会被分配一个ChannelHandlerContext,其代表了ChannelHandler 和ChannelPipeline 之间的绑定。
在Netty 中,有两种发送消息的方式,可以直接写到Channel 中,也可以写到和ChannelHandler相关联的ChannelHandlerContext 对象中。前一种方式将会导致消息从ChannelPipeline 的尾端开始流动,而后者将导致消息从ChannelPipeline 中的下一个ChannelHandler 开始流动。

ChannelHandler的适配器类:
Netty 以适配器类的形式提供了大量默认的ChannelHandler 实现,其旨在简化应用程序处理逻辑的开发过程。ChannelPipeline中的每个ChannelHandler将负责把事件转发到链中的下一个ChannelHandler。这些适配器类(及它们的子类)将自动执行这个操作,所以你可以只重写那些你想要特殊处理的方法和事件。
ChannelHandlerAdapter、ChannelInboundHandlerAdapter、ChannelOutboundHandlerAdapter、ChannelDuplexHandler......
ChannelHandler的子类: 编码器和解码器
当你通过Netty 发送或者接收一个消息的时候,就将会发生一次数据转换。入站消息会被解码;也就是说,从字节转换为另一种格式,通常是一个Java 对象。如果是出站消息,则会发生相反方向的转换:它将从它的当前格式被编码为字节。对应于特定的需要,Netty 为编码器和解码器提供了不同类型的抽象类,所有由Netty 提供的编码器/解码器适配器类都实现了ChannelOutboundHandler 或者ChannelInboundHandler 接口。
这些基类的名称将类似于ByteToMessageDecoder 或MessageToByteEncoder。对于特殊的类型,你可能会发现类似于ProtobufEncoder 和ProtobufDecoder这样的名称——预置的用来支持Google 的Protocol Buffers。
引导:
Netty 的引导类为应用程序的网络层配置提供了容器,这涉及将一个进程绑定到某个指定的端口,或者将一个进程连接到另一个运行在某个指定主机的指定端口上的进程。通常来说,我们把前面的用例称作引导一个服务器,后面的用例称作引导一个客户端。 用于客户端(简单地称为Bootstrap),(ServerBootstrap)用于服务器。

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

与ServerChannel 相关联的EventLoopGroup 将分配一个负责为传入连接请求创建Channel 的EventLoop。一旦连接被接受,第二个EventLoopGroup 就会给它的Channel
分配一个EventLoop。
内置传输:
Netty 内置了一些可开箱即用的传输。


下面分别介绍这些传输方式:
1. NIO
NIO 提供了一个所有I/O 操作的全异步的实现。它利用了自NIO 子系统被引入JDK 1.4 时便可用的基于选择器的API。选择器运行在一个检查状态变化并对其做出相应响应的线程上,在应用程序对状态的改变做出响应之后,选择器将会被重置,并将重复这个过程。
选择器背后的基本概念是充当一个注册表,在Channel 的状态发生变化时得到通知。可能的状态变化有:
新的Channel 已被接受并且就绪;
Channel 连接已经完成;
Channel 有已经就绪的可供读取的数据;
Channel 可用于写数据。

2. Epoll 用于linux的本地非阻塞传输
Netty 的NIO 传输基于Java 提供的异步/非阻塞网络编程的通用抽象。虽然这保证了Netty 的非阻塞API 可以在任何平台上使用,但它也包含了相应的限制,因为JDK为了在所有系统上提供相同的功能,必须做出妥协。
(Linux JDK NIO API使用了epoll调用。)
Netty为Linux提供了一组NIO API,其以一种和它本身的设计更加一致的方式使用epoll,并且以一种更加轻量的方式使用中断。如果你的应用程序旨在运行于Linux系统,那么请考虑利用这个版本的传输;你将发现在高负载下它的性能要优于JDK的NIO实现。如果代码清单中使用epoll 替代NIO,只需要将NioEventLoopGroup替换为EpollEventLoopGroup , 并且将NioServerSocketChannel.class 替换为EpollServerSocketChannel.class 即可。
3. OIO—旧的阻塞I/O
它是建立在java.net 包的阻塞实现之上的,所以它不是异步的。
4. 用于JVM 内部通信的Local 传输
Netty 提供了一个Local 传输,用于在同一个JVM 中运行的客户端和服务器程序之间的异步通信。在这个传输中,和服务器Channel 相关联的SocketAddress 并没有绑定物理网络地址。但只要服务器还在运行,它就会被存储在注册表里,并在Channel 关闭时注销。
连接到本地传输服务器的行为与其他的传输实现几乎是相同的, 需要注意的是只能在本地的服务器和客户端上使用它们。Local 未绑定任何 Socket,只提供 JVM 进程之间的通信。
5. Embedded 传输
可以将一组ChannelHandler 作为帮助器类嵌入到其他的ChannelHandler 内部。通过这种方式,你将可以扩展一个ChannelHandler 的功能,而又不需要修改其内部代码。Embedded transport 使不同的 ChannelHandler 之间的交互变得容易,容易嵌入到其他的 ChannelHandler 实例并像一个辅助类一样使用它们。它一般用来测试特定的 ChannelHandler 实现,也可以在ChannelHandler 中重新使用一些 ChannelHandler 来进行扩展。现实中多用来做单元测试用。
浙公网安备 33010602011771号