1、Netty 是一款异步的事件驱动的网络应用程序框架,支持快速地开发可维护的高性能的面向协议的服务器和客户端。

 

2、早期Java API 使用的阻塞函数

// 创建一个新的ServerSocket,用以监听指定端口上的连接请求

ServerSocket serverSocket = new ServerSocket(portNumber);

// 对 accept的调用将被阻塞,直到一个连接建立

SufferedReader in = serverSocket.accept();

— 这种方案,任何时候都有大量线程在休眠,资源浪费。每个线程的调用栈分配内存,默认64KB – 1MB。多线程上下文切换开销巨大。

 

3、Java NIO 非阻塞调用

一个单一的线程就可以处理多个并发连接。

 

4、Netty 的特性总结

【1】设计  统计API,支持多种传输类型(阻塞的和非阻塞的),简单强大的线程模型,真正无连接数据报套接字支持,连接逻辑组件支持复用。

【2】易于使用

【3】性能  比Java核心API更高的吞吐量和更低的延迟

【4】健壮性  不会因为慢速、快速、超载的连接导致OutOfMemoryError,消除高速网络中NIO常见的不公平读\写比率

【5】安全性  完整的SSL\TLS\StartTLS支持

【6】社区驱动  发布快速且频繁

 

5、Netty 核心组件

Channel  传入、传出数据的载体

回调   一个方法,一个指向已经被提供给另一个方法的方法的引用

Future  提供了另一种在操作完成时通知应用程序的方式。(将来提供对其结果的访问)

事件和ChannelHandler  事件是对我们的通知(改变状态、记录日志等)。 ChannelHandler 一种为了响应特定事件而执行的回调。

 

6、Echo服务器

所有Netty服务器都需要的两部分:

【1】至少一个ChannelHeadler 该组件实现了服务器对从客户端接收的数据的处理(业务逻辑)

【2】引导  配置服务器启动代码。 将服务器绑定到它要监听连接请求的端口上。

 

7、Echo服务器端 方法

channelRead()  对于每个传入的消息都要调用

channelReadComplete()  通知ChannelInboundHandler最后一次对channelRead()的调用是当前批量读取中的最后一条消息。

exceptionCaught()   读取期间,有异常抛出会调用。

在方法内打印异常并关闭。如果不捕获异常,接收的异常会                           

      被传递到ChannelPipeline尾端并记录。 应用程序应该提供至少一个实现exceptionCaught()

方法的channelHandler。

 

8、ChannelHandler

针对不同类型事件调用ChannelHandler

应用程序通过实现或者扩展ChannelHandler来挂钩到事件的生命周期,并且提供自定义的应用程序逻辑。

架构上,ChannelHandler用于保持业务逻辑与网络处理代码的分离。简化开发过程。

 

9、传输

因特网通信是建立在TCP传输之上的,NIO传输大多时候指的就是TCP传输(除了一些由Java NIO实现提供的服务器端性能)。

 

10、Echo客户端

(1)连接到服务器

(2)发送一个或多个消息

(3)对每个消息,等待并接收从服务器发回的相同的消息。

(4)关闭连接

主要代码:【业务逻辑】【引导】

 

11、Echo客户端 方法

channelActive()  与服务器建立连接后 调用

channelRead0()  接收到服务器消息后 调用

exceptionCaught()  处理过程中有异常时 调用

 

12、客户端 继承 SimpleChannelInboundHandler 与 服务端 继承ChannelInboundHandlerAdapter 原因

在客户端:当ChannelRead0完成时,已经传入消息并处理完。该方法返回后,SimpleChannelInboundHandler会释放指定的内存应用。

在客户端:仍然需要将消息返回给发送者,write()是异步操作,ChannelInboundHandlerAdapter 不会释放消息内存。内存在channelReadComplete()方法中,writeAndFlush()方法被调用时被释放。

 

13、Netty网络抽象代表,三大接口

Channel – Socket

EventLoop – 控制流、多线程处理、并发(Netty核心抽象,处理连接的生命周期中发生的事件)

ChannelFuture – 异步通知

 

14、ChannelHandler 和 ChannelPipeline

ChannelHandler 充当了所有处理入站和出站数据的应用程序逻辑的容器

ChannelPipeline 为ChannelHandler链提供了容器

(可以在ChannelPipeline 中将ChannelHandler 链接在一起以组织处理逻辑)

 

15、入站和出站

入站:事件运动方向是从 服务端 客户端 

出站:事件运动方向是从 客户端 服务端                             (例:客户端是内,服务端是外   外->内 :入; 内->外:出)

 

16、编码器和解码器

入站消息会被解码

出站消息会被编码

 

17、引导

Netty引导类为应用程序的网路层提供容器。

将一个进程绑定到某个指定的端口。

或者 将一个进程连接到另一个运行在某个指定主机的指定端口上的进程。

两种引导,一种用于客户端(Bootstrap),一种用于服务端(ServerBootStrap)

 

类别

Bootstrap

ServerBootStrap

网络编程中的作用

连接到远程主机和端口

绑定到一个本地端口

EventLoopGroup

1

2

 

18、ChannelHandler 典型用途

(1)将数据从一种格式转换为另一种格式

(2)提供异常的通知

(3)提供Channel变为活动的或者非活动的通知

(4)提供当Channel注册到EventLoop或者从EventLoop注销时的通知

(5)提供有关用户自定义事件的通知

 

19、Channel 方法

方法名

描述

eventLoop

 返回分配给Channel 的EventLoop

pipeline

 返回分配给Channel 的 ChannelPipeline

isActive

 如果Channel是活动的,返回true,活动的意义可能依赖于底层的传输。

(例:一个Socket 传输一旦连接到远程节点便是活动的,一个Datagram传输一旦被打开便是活动的)

localAddress

返回本地的SocketAddress

remoteAddress

返回远程的SocketAddress

write

将数据写到远程节点。数据将被传递给ChannelPipeline,并排队知道数据被冲刷

flush

将之前已写的数据冲刷到底层传输,(如一个socket)

writeAndFlush

一个简便的方法,等同于调用write()并接着调用flush()

 

20、Netty 提供的内置传输

名称

描述

NIO

io.netty.channel.socket.nio

使用java.nio.channels 包作为基础  — 基于选择器的方式

Epoll

io.netty.channel.epoll

由JNI驱动的epoll()和非租塞IO。这个传输支持只有在Linux上可用的多种特性,

(如:so_reuseport, 比NIO传输更快,而且是完全非租塞的)

OIO

io.netty.channel.socket.oio

使用java.net 包作为基础 — 使用阻塞流

Local

io.netty.channel.local

可以在VM内部通过管道进行通信的本地传输

Embedded

io.netty.channel.embedded

Embedded传输,允许使用ChannelHandler而又不需要一个真正的基于网络的传输。

这在测试你的ChannelHandler实现时非常有用

 

21、零拷贝

一种目前只有在使用NIO和Epoll传输时才可以使用的特性。

可以快速高效的将数据从文件系统移动到网络接口,且不需要将其从内核空间复制到用户空间。在FTP或HTTP协议中可以显著地提升性能

注:只能传输文件的原始内容。可以传输加密的文件,不可以传输加密的数据或压缩的文件。

 

22、应用程序最佳传输

应用程序的需求

推荐的传输

非阻塞代码库或者一个常规的起点

NIO(或者LInux上使用epoll)

阻塞代码库

OIO

在同一个JVM内部的通信

Local

测试 ChannelHandler 的实现

Embedded

 

23、ByteBuf API 的优点

l  可以被用户自定义的缓冲区类型扩展

l  通过内置的复合缓冲区类型实现了透明的零拷贝

l  容量可以按需增长(类似于JDK的StringBuffer)

l  在读写两种类型切换时不需要调用byteBuffer的flip()方法

l  读写使用了不同的索引

l  支持方法的链式调用

l  支持引用计数

l  支持池化

 

24、ByteBuffy类  — Netty 的数据容器

ByteBuf 维护了两个不同的索引:一个用于读取,一个用于写入。

ByteBuf 使用模式:

堆缓冲区  ByteBuf.hasArray()   为 true

直接缓冲区 ByteBuf.hasArray()   为 false

复合缓冲区 ByteBuf 的聚合视图,通过子类 CompositeByteBuf 实现

 

25、字节操作

随机访问索引:

ByteBuf 索引从0开始,最后一个索引为 capacity() – 1 。

例: byte b = byteBuf.getByte(i);

顺序访问索引:

0 – (已被读过的:可被丢弃的字节) ->readerIndex – (尚未被读的:可读字节) ->writeIndex – (可添加更多字节:可写字节) -> capacity

可丢弃字节:

 调用 discardReadBytes() ,将可丢弃字节丢弃并回收空间到可写字节。(建议在内存宝贵时候调用)

可读字节:

ByteBuf 的可读字节分段存储实际数据。

名称以 read 或者 skip 开头的操作将增加已读字节数

可写字节:

可写字节分段 指一个拥有未定义内容的、写入就绪的内存区域。

任何以write开头的操作都将从当前的writeIndex处开始写数据,并将增加已经写入的字节数

索引管理:

mark(int readlimit) 将流中的当前位置标记为指定的值

reset()   将流重置到该位置

markReaderIndex() / markWriteIndex()            标记 ByteBuf 的 readerIndex 和WriteIndex

resetWriterIndex() / resetReaderIndex()  重置 ByteBuf 的 readerIndex 和WriteIndex

readerIndex(int)  /  writerIndex(int)    将索引移动到指定位置

clear()         将readerIndex 和writerIndex 都设置为0 且不会清除内存中的内容

查找操作:

Netty 4.1 中 使用io.netty.util.ByteProcessor  接口下方法。 来确定指定值的索引

派生缓冲区:

为ByteBuf提供专门的方式呈现视图。例:duplicate() , slice() , slice(int, int) , Unpooled.unmodifiableBuffer(…) , order(ByteOrder) , readSlice(int). 方法返回新的ByteBuf实例,具有自己的读、写索引和标记索引。  派生换缓冲区修改内容,也会修改对应的源实例内容。

【ByteBuf复制:使用copy() 或者 copy(int, int) 方法,返回ByteBuf 拥有的独立数据副本。】

读、写操作:

get() 和 set() 操作,从给定的索引开始,保持索引不变。

read() 和 write() 操作,从给定的索引开始,会根据已经访问过的字节

 

get() 操作

名称

描述

getBoolean(int)

 返回给定索引处的 Bollean值

getByte(int)

 返回给定索引处的 字节

getUnsignedByte(int)

 将给定索引处的 无符号字节值作为short返回

getMedium(int)

 返回给定索引处的 24位的中等int值

getUnsignedMedium(int)

 返回给定索引处的 无符号的24位的中等 int 值

getInt(int)

 返回给定索引处的 int 值

getUnsignedInt(int)

 将给定索引处的 无符号 int 值作为 long 返回

getLong(int)

 返回给定索引处的 long 值

getShort(int)

 返回给定索引处的 short 值

getUnsignedShrt(int)

 将给定索引处的无符号 short 值作为 int 返回

getByte(int, …)

 将该缓冲区中从给定索引开始的数据传送到指定的目的地

set() 操作

名称

描述

setBoolean(int, boolean)

 设定给定索引处的 Boolean 值

setByte(int index, int value)

 设定给定索引处的 字节值

setMedium(int index, int value)

 设定给定索引处的 24位的中等 int 值

setInt(int index, int value)

 设定给定索引处的 int 值

setLong(int index, long value)

 设定给定索引处的 long 值

setShort(int index, int value)

 设定给定索引处的 short 值

read() 操作

名称

描述

 readBoolean()

返回当前 readerIndex 处的 Boolean, 并将readerIndex 增加 1

 readByte()

 返回当前readerIndex 处的字节,并将readerIndex 增加 1

 readUnsignedByte()

 将当前 readerIndex 处的无符号字节值作为short 返回,并将readerIndex 增加 1

 readMedium()

 返回当前readerIndex 处的24位的中等int 值,并将readerIndex 增加 3

 readUnsignedMedium()

 返回当前 readerIndex 处的 24位的无符号的中等int 值, 并将readerIndex 增加 3

 readInt()

 返回当前 readerIndex 处的int 值,并将readerIndex增加 4

 readUnsignedInt()

 将当前readerIndex处的无符号的int值作为long值返回, 并将readerIndex 增加 4

 readLong()

 返回当前readerIndex 处的long值,并将readerIndex 增加 8

 readShort()

 返回当前readerIndex 处的short 值,并将readerIndex 增加 2

 readUnsignedShort()

 将当前 readerIndex 处无符号 short 值 作为 int 值返回,并将readerIndex 增加 2

 readBytes( ByteBuf | byte [] destinatuion, int dstIndex [ , int length] )

 将当前 ByteBuf 中 从当前 readerIndex 处 开始的数据传送到一个目标 ByteBuf 或者 byte[],从目标的dstIndex开始的位置。本地的readerIndex将被增加已经传输的字节数。

write() 操作

名称

描述

writeBoolean( boolean )

 在当前 writeIndex 处写入一个Boolean ,并将 writeIndex 增加 1

writeByte( int )

 在当前 writeIndex 处写入一个字节值,并将writeIndex 增加 1

writeMedium( int )

 在当前 writeIndex 处写入一个中等的 int 值, 并将writeIndex 增加 3

writeInt ( int )

 在当前 writeIndex 处写入一个 int 值,并将writeIndex 增加 4

writeLong ( long )

 在当前 writeIndex 处写入一个 long 值,并将 writeIndex 增加 8

writeShort ( int )

 在当前writeIndex 处写入一个 short 值, 并将 writeIndex 增加 2

writeBytes ( source ByteBuf | byte [] [ , int srcIndex , int length ] )

 从 当前writeIndex 开始,传输来自于指定源的数据,如果提供了srcIndex 和 length, 则从 srcIndex 开始读取,并且处理长度为 length 的字节,当前 writeIndex 将会被增加所写入的字节数。

更多操作

名称

描述

isReadable()

如果至少有一个字节可读取,返回 true

isWritable()

如果至少有一个字节可写入,返回 true

readableByte()

返回可被读取的字节数

writableBytes()

返回可被写入的字节数

capacity()

返回ByteBuf 可容纳的字节数, 此后,会尝试再次扩展,直到达到maxCapacity()

maxCapacity()

返回ByteBuf 可以容纳的最大字节数

hasArray()

如果ByteBuf 由一个字节数组支撑,则返回 true

array()

如果ByteBuf 由一个字节数组支撑则返回该数组,否则,它将抛出一个 UnsupportedOperationException 异常

26、ByteBufAllocator 池化和引用计数

池化:为了降低分配和释放内存的开销,可以分配任意类型的ByteBuf类型。

引用计数:通过某个对象持有的资源不在被其他对象引用时,释放该对象持有资源来 优化内存使用和性能的技术。

 

27、ChannelHandler

Channel 的生命周期状态

状态

描述

ChannelUnregistered

Channel 已经被创建,但还未注册到EventLoop

ChannelRegistered

Channel 已经被注册到了EventLoop

ChannelActive

Channel 处于活动状态(已经连接到它的远程节点)。它现在可以接收和发送数据了

ChannelInactive

Channel 没有连接到远程节点

ChannelHandler 的生命周期

状态

描述

handlerAdded

当把 ChannelHandler 添加到 ChannelPipeline 中时被调用

handlerRemoved

当从 ChannelPipeline 中移除 ChannelHandler 时被调用

exceptionCaught

当处理过程中在 ChannelPipeline 中有错误时被调用

ChannelHandler 两个重要的子接口: ChannelInboundHandler 、 ChannelOutboundHandler

(1)ChannelInboundHandler 的实现重写 channelRead() 方法,负责显示地释放与池化 ByteBuf 内存。

Netty一个实用方法 — ReferenceCountUtil.release(msg);

或者 另一种简单方式:实用 SimpleChannelInboundHandler

(2)ChannelOutBoundHandler 接口

ChannelOutBoundHandler  功能在于 按需推迟操作或者事件。

ChannelOutboundHandler 中大部分方法都需要一个ChannelPromise 参数,在操作完成时得到通知。

 

28、资源管理

诊断潜在的资源泄露。 有四种检测级别

级别

描述

DISABLED

禁用泄漏检测。只有在详尽的测试之后才应使用

SIMPLE

使用1%的默认采样率检测并报告任何发现的泄露。这是默认级别,适合绝大部分情况。

ADVANCED

使用默认的采样率,报告所发现的任何的泄露以及对应的消息被访问的位置

PARANOID

类似于ADVANCED,但是其将会对每次(对消息的)访问都进行采样。这对性能将会有很大影响,在调试阶段使用

总之:如果消息被消费或者丢弃了,并且没有传递给ChannelPipeline 中的下一个ChannelOutboundHandler ,那么用户就有责任调用 ReferenceCountUtil.release()。 如果消息到达了实际传输层,当它被写入时,或者Channel关闭时,会自动释放。

 

29、ChannelPipeline 接口

每个新创建的 Channel 都将会被分配一个新的 ChannelPipeline 。这是永久性关联。

Netty 总是将 ChannelPipeline 的入站口作为头部,出站口作为尾部。

ChannelHandler 可以添加、删除、替换 其他的ChannelHandler,从而实时修改ChannelPipeline 布局。

名称

描述

 addFirst

 addBefore

 addAfter

 addLast

将一个ChannelHandler 添加到ChannelPipeline 中

remove

将一个ChannelHandler 从 ChannelPipeline 中移除

replace

将 ChannelPipeline 中的一个 ChannelHandler 替换为另一个ChannelHandler

ChannelPipeline 用于访问 ChannelHandler 的操作

名称

描述

 get

 通过类型或者名称返回 ChannelHandler

 context

 返回和ChannelHandler 绑定的 ChannelHandlerContext

 names

 返回ChannelPipeline 中所有 ChannelHandler 的名称

总结:

l  ChannelPipeline 保存了与Channel 相关联的ChannelHandler;

l  ChannelPipeline 可以根据需要,通过添加或者删除ChannelHandler 来动态地修改;

l  ChannelPipeline 有着丰富的 API 用以被调用,以响应入站和出站事件。

 

30、ChannelHandlerContext 接口

ChannelHandlerContext 主要功能是管理它所关联的ChannelHandler 和在同一个 ChannelPipeline 中的其他 ChannelHandler 之间的交互。

如果调用 Channel 或者ChannelPipeline 上的方法,流程将沿着ChannelPipeline 进行传播。调用ChannelHandlerContext 上的相同方法,流程从关联的ChannelHandler 开始,并且只会传播位于该 ChannelPipeline 中的下一个能够处理的该事件的 ChannelHandler。

注:重要   ChannelHandlerContext 和 ChannelHandler 之间关联(绑定)是永远不会改变的,所以缓存对它的引用是安全的。

相对于其他类的同名方法,ChannelHandlerContext 的方法将产生更短的事件流,可以用这个特定获得最大性能。

 

31、共享同一个 ChannelHandler

在多个 ChannelPipeline 中安装同一个ChannelHandler 的一个常见原因:用于收集跨域多个 Channel 的统计信息。

 

32、处理入站异常

l  ChannelHandler.exceptionCaught()的默认将异常转发给 ChannelPipeline 中的下一个ChannelHandler;

l  如果异常到达ChannelPipeline 尾端,将会被记录为未被处理;

l  想要定义自定义的处理逻辑,需要重写 exceptionCaught() 方法。然后决定是否把异常传播出去。

 

33、处理出站异常

l  出站操作都返回一个ChannelFuture。注册到ChannelFuture 的ChannelFutureListener 将在操作完成时被通知操作是成功还是出错了。

l  所有 ChannelOutboundHandler 上的方法都会传入 ChannelPromise 。ChannelPromise 可以被分配用于异步通知的监听器。ChannelPromise 还具有提供立即通知的可写方法。

 

34、ChannelPromise 的可写方法

通过调用 ChannelPromise 上的 setSuccess() 和 setFailure()方法,可使一个操作状态在 ChannelHandler 方法返回给调用者时即刻被感知到。

 

34、基本的线程池化

l  从池的空闲线程列表中选择一个 Thread,并且指派它去运行一个已提交的任务(一个Runnable的实现)

l  当任务完成时,将该Thread返回给该列表,使其可被重用。

 

35、引导

 引导一个应用程序指 对它进行配置,并使它运行起来的过程。

 

36、IllegalStateException

在引导过程中,调用bind() 或者connect() 方法钱,必须调用 group()、channel()或channelFactory()、handler()   ; 如果没有调用,会导致 IllegalStateException 。对handler() 方法调用很重要,它需要配置好ChannelPipeline。

 

37、Netty应用程序一般准则

尽可能地重用EventLoop,以减少线程创建所带来的开销。

 

38、EventLoopGroup.shutdownGracefully()  关闭

处理任何挂起的事件和任务,并且随后释放所有活动的线程。

 

39、编码器、解码器

编码器:将消息转换为适合于传输的格式(例:字节流)。处理出站数据

解码器:将网络字节流转回应用程序的消息格式。处理入站数据

 

40、ByteToMessageDecoder API

方法

描述

decode(

            ChannelHandlerContext ctx,

            ByteBuf in,

            List<Object> out)

必须实现的唯一抽象方法。

方法被调用时传入一个包含传入数据的ByteBuf,和一个添加解码消息的List。

对方法的调用会重复进行,知道没有新元素被添加到List,或ByteBuf中没有更多可读取的字节。

如果List不为空,它的内容会被传递给ChannelPipeline中的下一个ChannelInboundHandler

decodeLast(

            ChannelHandlerContext ctx,

            ByteBuf in,

            List<Object> out)

简单调用decode()方法,

当Channel状态为非活动时,这个方法会被调用一次。

可以重写该方法已提供特殊处理

 

41、解码器中的引用计数

对于编码器和解码器。一旦消息被编码或解码,它就被ReferenceCountUtil.release(message) 调用自动释放。

如果需要保留,可以调用ReferenceCountUtil.retain(message)。将会增加该引用计数,防止消息被释放。

 

42、MessagetoMessageDecoder API

方法

描述

decode (

          ChannelHandlerContext ctx,

          I msg,

          List<Object> out)

每个需要被解码为另一种格式的入站消息来说,该方法都将被调用。

解码消息随后会传递给 ChannelPipeline中的下一个ChannelInboundHandler

 

43、TooLongFrameException 类

由解码器在帧超出指定的大小限制时抛出。

 

44、MessageToByteEncoder API

方法

描述

encode(

          ChannelHandlerContext ctx,

          I msg,

          ByteBuf out)

唯一抽象方法,被调用时传入该类编码为ByteBuf的出站消息,该消息随后会被转发给ChannelPipeline中的下一个ChannelOutboundHandler

 

45、ByteToMessageCodec API

方法名称

描述

decode(

            ChannelHandlerContext ctx,

             ByteBuf in,

            List<Object>)

只要有字节可以被消费,这个方法就将被调用。它将入站ByteBuf 转换为指定的消息格式,并将其转发给ChannelPipeline 中的下一个ChannelInboundHandler

decodeLast(

            ChannelHandlerContext ctx,

            ByteBuf in,

            List<Object>  out)

这个方法默认实现委托给decode()方法。在Channel状态变为非活动时被调用一次。可以被重写以实现特殊处理。

encode(

            ChannelHandlerContext ctx,

            I msg,

            ByteBuf  out)

对每个将被编码并写入出站ByteBuf的消息来说,这个方法都会被调用。

 

46、MessageToMessageCodec 的方法

方法名称

描述

protected abstract decode(

            ChannelHandlerContext ctx,

            INBOUND_IN msg,

            List<Object> out)

传入INBOUND_IN 类型的消息。并把它解码为OUTBOUND_IN 类型的消息,

消息被转发给ChannelPipeline中的下一个ChannelInboundHandler

protected abstract encode(

            ChannelHandlerContext ctx,

           OUTBOUND_IN msg,

            List<Object> out)

对每个OUTBOUND_IN 类型的消息,该方法都被调用。消息会被编码为INBOUND_IN 类型的消息,

然后转发给ChannelPipeline中的下一个ChannelOutboundHandler

 

47、SshHandler 的方法

方法名称

描述

setHandshakeTimeout (long , TimeUnit)

setHandshakeTimeoutMillis (long)

getHandshakeTimeoutMillis ()

设置和获取超市事件,超时后,握手ChannelFuture 将会被通知失败

setCloseNotifyTimeout (long, TimeUnit)

setCloseNotifyTimeoutMillis (long)

getCloseNotifyTimeoutMillis ()

设置和获取超时时间,超时后,将会触发一个关闭通知并关闭连接。同时会导致通知该ChannelFuture 失败

handshakeFuture()

返回一个在握手完成后将会得到通知的ChannelFuture,如果握手前已经执行过,则返回包含了先前握手结果的ChannelFuture

close()

close(ChannelPromise)

close(ChannelHandlerContext, ChannelPromise)

发送 close_notify 以请求关闭并销毁底层的SslEngine

 

48、用于空闲链接以及超时的ChannelHandler

名称

描述

IdleStateHandler

当链接空闲时间太长,将触发一个IdleStateEvent 事件。然后,可以通过 ChannelInboundHandler中重写userEventTriggered()方法来处理该 IdleStateEvent 事件

ReadTimeoutHandler

如果指定时间间隔内没收到任何入站数据,则抛出一个ReadTimeoutException 并关闭对应Channel。可以重写ChannelHandler中的exceptionCaught()方法检测该事件

WriteTimeoutHandler

如果指定时间间隔内没有任何出站数据写入,则抛出WriteTimeoutExceptoin 并关闭对应Channel。可以重写ChannelHandler 的exceptionCaught()方法检测该事件

 

49、处理基于分隔符的协议和基于长度的协议的解码器

名称

描述

DelimiterBasedFrameDecoder

使用任何由用户提供的分隔符来提取帧的通用解码器

LineasedFrameDecoder

提取由行尾符(\n 或者 \r\n)分割的帧的解码器。这个解码器比DelimiterBaseFrameDecoder 更快

 

名称

描述

FixedLengthFrameDecoder

提取在调用构造函数时指定的定长帧

LengthFieldBaseFrameDecoder

根据编码进帧头部中的长度值提取帧;

该字段的偏移量以及长度在构造函数中指定

 

50、ChunkedWriteHandler

需要将数据从文件系统复制到用户内存中时,使用 ChunkedWriteHandler ,它支持异步写大型数据流,且不会导致大量的内存消耗。

 

51、JDK序列化编解码器

名称

描述

CompatibleObjectDecoder

和使用JDK序列化的 非基于Netty的 远程节点 进行互操作的解码器

CompatibleObjectEncode

和使用JDK序列化的 非基于Netty的 远程节点 进行互操作的编码器

ObjectDecoder

构建于JDK 序列化之上的使用自定义的序列化来解码的解码器;

当没有其他的外部依赖时,它提供了速度上的改进。否则其他序列化更可取

ObjectEncoder

构建于JDK序列化之上的使用自定义的序列化来编码的编码器;

当没有其他的外部依赖时,它提供了速度上的改进。否则其他序列化更可取

 

52、JBoss Marshalling 编解码器

名称

描述

CompatibleMarchallingDecoder

CompatibleMarshallingEncoder

与只使用JDK序列化的远程节点兼容

MarshallingDecoder

MarshallingEncoder

适用于使用JBoss Marshalling 的节点。这些类必须一起使用

 

53、Protobuf 编解码器

名称

描述

ProtobufDecoder

使用 protobuf 对消息进行解码

ProtobufEncoder

使用 protobuf 对消息进行编码

ProtobufVarint32FrameDecoder

根据消息中的Google Protocol Buffer 的 “Base 128 Varints” 整型长度字段值动态地分割所接收到的ByteBuf

ProtobufVarint32LengthFieldPrepender

向ByteBuf 前追加一个Google Protocal Buffer 的“Base 128 Varints” 整型的长度字段值

 

版权声明:本文为wgy1原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wgy1/p/9039884.html