首页  

netty实战笔记     所属分类 netty 浏览量 133
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 使用