netty实战笔记
所属分类 netty
浏览量 1392
bio线程模型 一个连接一个线程 阻塞IO
nio线程模型 使用selector 非阻塞IO 一个线程可以处理多个连接
异步和事件驱动
Channel
ChannelHandler
事件 回调 Future
Channel Socket
EmbeddedChannel
LocalServerChannel
NioDatagramChannel
NioSctpChannel
NioSocketChannel
EventLoop 控制流、多线程处理、并发
ChannelFuture 异步通知
Channel EventLoop EventLoopGroup
ChannelHandler 和 ChannelPipeline
应用业务逻辑通常在一个或者多个 ChannelInboundHandler 中 实现
ChannelPipeline 提供了 ChannelHandler 链的容器
入站 出站
head 靠近网络层
tail 靠近应用层
发送消息 两种方式
Channel write writeAndFlush
ChannelHandlerContext write writeAndFlush
第一种方式 消息从 ChannelPipeline 尾端开始流动
第二种方式 消息从 ChannelPipeline 中的下一个 ChannelHandler 开始流动
ChannelFuture write(Object msg);
ChannelFuture write(Object msg, ChannelPromise promise);
ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);
ChannelFuture writeAndFlush(Object msg);
channelHandler的应用 编码器和解码器
每个 Channel 都会分配一个 ChannelPipeline 和 ChannelConfig
ChannelConfig 包含了该 Channel 的所有配置,并且支持热更新。
Channel是线程安全的 !!!
数据容器ByteBuf
可以被用户自定义的缓冲区类型扩展
通过内置的复合缓冲区类型实现零拷贝
容量可以按需增长(类似于 JDK 的 StringBuilder)
在读和写这两种模式之间切换不需要调用 ByteBuffer 的 flip()方法
读和写使用了不同的索引
支持方法的链式调用
支持引用计数
支持池化
ByteBuf使用模式
堆缓冲区,支撑数组
直接缓冲区
复合缓冲区
ByteBufHolder 持有ByteBuf引用,可以存储额外信息
ByteBufAllocator 获取池化ByteBuf,可以从Channel或者ChannelHandlerContext获取ByteBufAllocator的引用
Unpooled 获取未池化ByteBuf
ByteBufUtil
引用计数
ReferenceCounted 接口
public class DiscardHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ReferenceCountUtil.release(msg);
}
}
资源管理
通过调用 ChannelInboundHandler.channelRead()或者 ChannelOutboundHandler.write()方法来处理数据时,
需要确保没有任何的资源泄漏 ,除非调用了ChannelHandlerContext.fireChannelRead()交给下一个处理器处理。
ChannelOutboundHandler.write()不仅要释放资源,还要通知ChannelPromise。否则可能会出现 ChannelFutureListener 收不到某个消息已经被处理了的通知的情况。
资源泄露检测类 ResourceLeakDetector
利用了JDK的虚引用,配置参数java -Dio.netty.leakDetectionLevel=ADVANCED
ResourceLeakDetector.Level
DISABLED
SIMPLE
Enables simplistic sampling resource leak detection which reports there is a leak or not,
at the cost of small overhead (default).
1%默认采样率
ADVANCED
Enables advanced sampling resource leak detection which reports where the leaked object was accessed recently at the cost of high overhead.
PARANOID
Enables paranoid resource leak detection which reports where the leaked object was accessed recently,
at the cost of the highest possible overhead (for testing purposes only).
每一次访问都会采样 ,对性能影响很大
ChannelPipeline接口
每一个新建的 Channel 都会分配一个新的 ChannelPipeline ,关联是永久性
ChannelInboundHandler 从头部开始处理
ChannelOutboundHandler从尾部开始处理
ChannelHandlerContext接口
ChannelHandlerContext 有很多方法,其中一些方法也存在于 Channel 和 ChannelPipeline 中。
调用 Channel 或者 ChannelPipeline 上的这些方法,它们将沿着整个 ChannelPipeline 进行传播。
而调 ChannelHandlerContext 上的相同方法,则将从当前所关联的 ChannelHandler 开始,并且只会传播给位于该 ChannelPipeline 中的下一个能够处理该事件的 ChannelHandler。
事件传播
异常处理
通过调用 ChannelPromise 上的 setSuccess()和 setFailure()方法,可以使一个操作的状态在 ChannelHandler 的方法返回给其调用者时便即刻被感知到
EventLoop和线程模型
EventLoopGroup对应多个EventLoop,一个EventLoop对应一个线程,一个EventLoop可对应多个通道
每个通道会分配一个EventLoop(以及相关线程),Channel的IO事件由独立的线程处理。
EventLoop由一个永不改变的线程驱动,任务(Runnable或Callable)可以直接提交给EventLoop ,以便立即执行或有计划地执行。
Netty4 判断执行线程的身份,如果调用的是EventLoop的线程,那么直接执行,否则放入内部队列中
EventExecutor.inEventLoop()
判断执行线程是 EventLoop线程
不要把耗时的任务放在执行队列中 ,这样会阻塞执行线程,阻塞其他通道
耗时任务可使用专用的EventExecutor
Channel.eventLoop().execute(task)
Netty4 开发建议
时间可控的简单业务直接在IO线程上处理
复杂和时间不可控业务建议投递到后端业务线程池统一处理
Netty4 I/O和事件处理
由I/O操作触发的事件流过具有一个或多个ChannelHandler的ChannelPipeline时, 由ChannelHandler拦截处理
所有的I/O操作和事件都由分配给EventLoop的线程处理
Netty3中的I/O处理
仅保证入站事件将在I/O线程中执行,所有出站事件由调用线程处理,需要在ChannelHandlers中仔细同步出站事件
引导
Bootstrap 客户端或无连接协议
ServerBootstrap 服务端
ServerChannel 负责创建 子Channel,子Channel 代表已被接受的连接
bind
accept 接收连接 创建 子Channel
DatagramChannel 无连接
EventLoopGroup.shutdownGracefully()
处理任何挂起的事件和任务,并且随后释放所有活动的线程
编解码器
编码器操作出站数据,解码器处理入站数据。
编解码器中的引用计数会自动处理,ReferenceCountUtil.release(message)
解码器
ByteToMessageDecoder
ReplayingDecoder
MessageToMessageDecoder
TooLongFrameException 防止解码器缓冲的数据耗尽内存
编码器
MessageToByteEncoder
MessageToMessageEncoder
编解码器
ByteToMessageCodec
MessageToMessageCodec
CombinedChannelDuplexHandler
预置的 ChannelHandler 和编解码器
SslHandler
大多数情况,SslHandler是ChannelPipeline中的第一个ChannelHandler
HTTP 解码器、编码器和编解码器
HttpRequestEncoder
HttpResponseEncoder
HttpRequestDecoder
HttpResponseDecoder
HttpObjectAggregator 聚合 HTTP 消息
HttpContentCompressor && HttpContentDecompresso —HTTP 压缩和解压
WebSocketProtocolHandler
空闲的连接和超时
IdleStateHandler 可用来实现心跳
ReadTimeoutHandler
WriteTimeoutHandler
基于分隔符的协议
DelimiterBasedFrameDecoder
LineBasedFrameDecoder
基于长度的协议
FixedLengthFrameDecoder
LengthFieldBasedFrameDecoder
写大型数据
FileRegion
通过支持零拷贝的文件传输Channel 来发送的文件区域
只适用于文件内容的直接传输,不包括应用程序对数据的任何处理
ChunkedWriteHandler
支持将数据从文件系统复制到用户内存中
支持异步写大型数据流,而又不会导致大量的内存消耗
序列化数据
JBoss Marshalling
Protocol Buffers
epoll空轮询bug
FastThreadLocal
EventLoopGroup 分配 EventLoop
上一篇
下一篇
eclipse优化
dubbo配置优先级
dubbo性能相关参数
netty中的future和promise
netty耗时任务处理
netty4 ChannelInboundHandler 使用