- 目前已经有 **1000+** 位球友加入…
- 进度:已经完成 **60+** 篇,预计总共 70+ 篇,完成度 **90%** 。
- 调试环境搭建
- 《精尽 Netty 源码分析 —— 调试环境搭建》
- 《精尽 Netty 源码分析 —— NIO 基础(一)之简介》
- 《精尽 Netty 源码分析 —— NIO 基础(二)之 Channel》
- 《精尽 Netty 源码分析 —— NIO 基础(三)之 Buffer》
- 《精尽 Netty 源码分析 —— NIO 基础(四)之 Selector》
- 《精尽 Netty 源码分析 —— NIO 基础(五)之示例》
- 《精尽 Netty 源码分析 —— Netty 简介(一)之项目结构》
- 《精尽 Netty 源码分析 —— Netty 简介(二)之核心组件》
- 《精尽 Netty 源码分析 —— 启动(一)之服务端启动》
- 《精尽 Netty 源码分析 —— 启动(二)之客户端启动》
- 《精尽 Netty 源码解析 —— EventLoop(一)之 Reactor 模型》
- 《精尽 Netty 源码解析 —— EventLoop(二)之 EventLoopGroup》
- 《精尽 Netty 源码解析 —— EventLoop(三)之 EventLoop 初始化》
- 《精尽 Netty 源码解析 —— EventLoop(四)之 EventLoop 运行》
- 《精尽 Netty 源码解析 —— EventLoop(五)之 EventLoop 处理 IO 事件》
- 《精尽 Netty 源码解析 —— EventLoop(六)之 EventLoop 处理普通任务》
- 《精尽 Netty 源码解析 —— EventLoop(七)之 EventLoop 处理定时任务》
- 《精尽 Netty 源码解析 —— EventLoop(八)之 EventLoop 优雅关闭》
- 《精尽 Netty 源码解析 —— ChannelPipeline(一)之初始化》
- 《精尽 Netty 源码解析 —— ChannelPipeline(二)之添加 ChannelHandler》
- 《精尽 Netty 源码解析 —— ChannelPipeline(三)之删除 ChannelHandler》
- 《精尽 Netty 源码解析 —— ChannelPipeline(四)之 OutBound 事件的传播》
- 《精尽 Netty 源码解析 —— ChannelPipeline(五)之 Inbound 事件的传播》
- 《精尽 Netty 源码解析 —— ChannelPipeline(六)之异常的传播》
- 《精尽 Netty 源码解析 —— ChannelPipeline(一)之简介》
- 《精尽 Netty 源码解析 —— ChannelPipeline(二)之 accept 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(三)之 read 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(四)之 write 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(五)之 flush 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(六)之 writeAndFlush 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(七)之 close 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(八)之 disconnect 操作》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuf(一)简介》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(二)核心子类》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(三)内存泄露检测》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(四)其它子类》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(一)简介》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(二)UnpooledByteBufAllocator》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(三)PooledByteBufAllocator》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(一)简介》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(二)PoolChunk》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(三)PoolSubpage》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(四)PoolChunkList》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(五)PoolArena》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(六)PoolThreadCache》
- 《精尽 Netty 源码解析 —— ChannelHandler(一)之简介》
- 《精尽 Netty 源码解析 —— ChannelHandler(二)之 ChannelInitializer》
- 《精尽 Netty 源码解析 —— ChannelHandler(三)之 SimpleChannelInboundHandler》
- 《精尽 Netty 源码解析 —— ChannelHandler(四)之 LoggingHandler》
- 《精尽 Netty 源码解析 —— ChannelHandler(五)之 IdleStateHandler》
- 《精尽 Netty 源码解析 —— ChannelHandler(六)之 AbstractTrafficShapingHandler》
- 《精尽 Netty 源码解析 —— Codec 之 ByteToMessageDecoder(一)Cumulator》
- 《精尽 Netty 源码解析 —— Codec 之 ByteToMessageDecoder(二)FrameDecoder》
- 《精尽 Netty 源码解析 —— Codec 之 MessageToByteEncoder》
- 《精尽 Netty 源码解析 —— Codec 之 ByteToMessageCodec》
- 《精尽 Netty 源码解析 —— Codec 之 MessageToMessageCodec》
- 《精尽 Netty 源码解析 —— Util 之 Future》
- 《精尽 Netty 源码解析 —— Util 之 FastThreadLocal》
- 《精尽 Netty 源码解析 —— Util 之 Recycler》
- 《精尽 Netty 源码解析 —— Util 之 HashedWheelTimer》
- 《精尽 Netty 源码解析 —— Util 之 MpscUnboundedArrayQueue》
- 通过读《Netty 实现原理浅析》,对 Netty 原理有基本的认知。
- 通过读《精尽 Netty 源码解析》,对 Netty 原理有深入的理解。
- 《精尽 Netty 源码分析 —— Netty 简介(一)之项目结构》
- 《精尽 Netty 源码分析 —— Netty 简介(二)之核心组件》
- 《精尽 Netty 源码解析 —— EventLoop(一)之 Reactor 模型》
- 《精尽 Netty 源码解析 —— EventLoop(二)之 EventLoopGroup》
- 《精尽 Netty 源码解析 —— EventLoop(三)之 EventLoop 初始化》
- 《精尽 Netty 源码解析 —— EventLoop(四)之 EventLoop 运行》
- 《精尽 Netty 源码解析 —— EventLoop(五)之 EventLoop 处理 IO 事件》
- 《精尽 Netty 源码解析 —— EventLoop(六)之 EventLoop 处理普通任务》
- 《精尽 Netty 源码解析 —— EventLoop(七)之 EventLoop 处理定时任务》
- 《精尽 Netty 源码解析 —— EventLoop(八)之 EventLoop 优雅关闭》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuf(一)简介》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(二)核心子类》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(三)内存泄露检测》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(四)其它子类》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(一)简介》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(二)UnpooledByteBufAllocator》
- 《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(三)PooledByteBufAllocator》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(一)简介》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(二)PoolChunk》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(三)PoolSubpage》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(四)PoolChunkList》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(五)PoolArena》
- 《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(六)PoolThreadCache》
- 《精尽 Netty 源码解析 —— ChannelPipeline(一)之简介》
- 《精尽 Netty 源码解析 —— ChannelPipeline(二)之 accept 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(三)之 read 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(四)之 write 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(五)之 flush 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(六)之 writeAndFlush 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(七)之 close 操作》
- 《精尽 Netty 源码解析 —— ChannelPipeline(八)之 disconnect 操作》
- 《精尽 Netty 源码解析 —— ChannelHandler(一)之简介》
- 《精尽 Netty 源码解析 —— ChannelHandler(二)之 ChannelInitializer》
- 《精尽 Netty 源码解析 —— ChannelHandler(三)之 SimpleChannelInboundHandler》
- 《精尽 Netty 源码解析 —— ChannelHandler(四)之 LoggingHandler》
- 《精尽 Netty 源码解析 —— ChannelHandler(五)之 IdleStateHandler》
- 《精尽 Netty 源码解析 —— ChannelHandler(六)之 AbstractTrafficShapingHandler》
目前已经有 1000+ 位球友加入…
对应 Netty 版本号:4.1.26.Final
1.1 目录
《精尽 Netty 源码分析 —— 调试环境搭建》
NIO 基础
《精尽 Netty 源码分析 —— NIO 基础(二)之 Channel》
《精尽 Netty 源码分析 —— NIO 基础(四)之 Selector》
Netty 简介
《精尽 Netty 源码分析 —— Netty 简介(二)之核心组件》
启动
《精尽 Netty 源码分析 —— 启动(二)之客户端启动》
EventLoop
《精尽 Netty 源码解析 —— EventLoop(二)之 EventLoopGroup》
《精尽 Netty 源码解析 —— EventLoop(四)之 EventLoop 运行》
《精尽 Netty 源码解析 —— EventLoop(六)之 EventLoop 处理普通任务》
《精尽 Netty 源码解析 —— EventLoop(八)之 EventLoop 优雅关闭》
ChannelPipeline
《精尽 Netty 源码解析 —— ChannelPipeline(二)之添加 ChannelHandler》
《精尽 Netty 源码解析 —— ChannelPipeline(四)之 OutBound 事件的传播》
《精尽 Netty 源码解析 —— ChannelPipeline(六)之异常的传播》
Channel
《精尽 Netty 源码解析 —— ChannelPipeline(二)之 accept 操作》
《精尽 Netty 源码解析 —— ChannelPipeline(四)之 write 操作》
《精尽 Netty 源码解析 —— ChannelPipeline(六)之 writeAndFlush 操作》
《精尽 Netty 源码解析 —— ChannelPipeline(八)之 disconnect 操作》
Bytebuf
《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(二)核心子类》
《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(四)其它子类》
《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(二)UnpooledByteBufAllocator》
《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(一)简介》
《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(三)PoolSubpage》
《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(五)PoolArena》
ChannelHandler
《精尽 Netty 源码解析 —— ChannelHandler(二)之 ChannelInitializer》
《精尽 Netty 源码解析 —— ChannelHandler(四)之 LoggingHandler》
《精尽 Netty 源码解析 —— ChannelHandler(六)之 AbstractTrafficShapingHandler》
Codec
《精尽 Netty 源码解析 —— Codec 之 ByteToMessageDecoder(二)FrameDecoder》
《精尽 Netty 源码解析 —— Codec 之 ByteToMessageCodec》
Util
《精尽 Netty 源码解析 —— Util 之 FastThreadLocal》
《精尽 Netty 源码解析 —— Util 之 HashedWheelTimer》
1.2 Netty 实现原理浅析
本小节基于 《Netty 实现原理浅析》 重新整理。
Netty 是 JBoss 出品的高效的 Java NIO 开发框架,关于其使用,可参考我的另一篇文章 《netty 使用初步》 。
本文将主要分析 Netty 实现方面的东西,由于精力有限,本人并没有对其源码做了极细致的研究。如果下面的内容有错误或不严谨的地方,也请指正和谅解。对于 Netty 使用者来说,Netty 提供了几个典型的 example ,并有详尽的 API doc 和 guide doc ,本文的一些内容及图示也来自于 Netty 的文档,特此致谢。
1.2.1 总体结构
先放上一张漂亮的 Netty 总体结构图,下面的内容也主要围绕该图上的一些核心功能做分析,但对如 Container Integration 及 Security Support 等高级可选功能,本文不予分析。
对应源码解析文章:
《精尽 Netty 源码分析 —— Netty 简介(二)之核心组件》
1.2.2 网络模型
Netty 是典型的 Reactor 模型结构,关于 Reactor 的详尽阐释,可参考 POSA2 ,这里不做概念性的解释。而应用 Java NIO 构建 Reactor 模式,Doug Lea(就是那位让人无限景仰的大爷)在 “Scalable IO in Java” 中给了很好的阐述。这里截取其 PPT 中经典的图例说明 Reactor 模式的典型实现:
1、这是最简单的单 Reactor 单线程模型。Reactor 线程是个多面手,负责多路分离套接字,Accept 新连接,并分派请求到处理器链中。该模型 适用于处理器链中业务处理组件能快速完成的场景。不过,这种单线程模型不能充分利用多核资源,所以实际使用的不多。
对应源码解析文章:
《精尽 Netty 源码解析 —— EventLoop(二)之 EventLoopGroup》
《精尽 Netty 源码解析 —— EventLoop(四)之 EventLoop 运行》
《精尽 Netty 源码解析 —— EventLoop(六)之 EventLoop 处理普通任务》
《精尽 Netty 源码解析 —— EventLoop(八)之 EventLoop 优雅关闭》
1.2.3 buffer
org.jboss.netty.buffer
包的接口及类的结构图如下:
对应源码解析文章:
《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(二)核心子类》
《精尽 Netty 源码解析 —— Buffer 之 ByteBuff(四)其它子类》
《精尽 Netty 源码解析 —— Buffer 之 ByteBufAllocator(二)UnpooledByteBufAllocator》
《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(一)简介》
《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(三)PoolSubpage》
《精尽 Netty 源码解析 —— Buffer 之 Jemalloc(五)PoolArena》
1.2.4 Channel
和Channel相关的接口及类结构图如下:
从该结构图也可以看到,Channel主要提供的功能如下:1)当前Channel的状态信息,比如是打开还是关闭等。 2)通过ChannelConfig可以得到的Channel配置信息。 3)Channel所支持的如read、write、bind、connect等IO操作。 4)得到处理该Channel的ChannelPipeline,既而可以调用其做和请求相关的IO操作。
在Channel实现方面,以通常使用的 nio socket来说,Netty中的NioServerSocketChannel和NioSocketChannel分别封装了 `java.nio` 中包含的 ServerSocketChannel和SocketChannel的功能。对应源码解析文章:
《精尽 Netty 源码解析 —— ChannelPipeline(二)之 accept 操作》
《精尽 Netty 源码解析 —— ChannelPipeline(四)之 write 操作》
《精尽 Netty 源码解析 —— ChannelPipeline(六)之 writeAndFlush 操作》
《精尽 Netty 源码解析 —— ChannelPipeline(八)之 disconnect 操作》
1.2.5 ChannelEvent
如前所述,Netty是事件驱动的,其通过 ChannelEvent 来确定事件流的方向。一个ChannelEvent是依附于Channel的 ChannelPipeline来处理,并由ChannelPipeline调用ChannelHandler来做具体的处理。下面是和 ChannelEvent相关的接口及类图:
对于使用者来说,在ChannelHandler实现类中会使用继承于ChannelEvent的MessageEvent,调用其 getMessage()方法来获得读到的ChannelBuffer或被转化的对象。对应源码解析文章:
《精尽 Netty 源码解析 —— ChannelHandler(二)之 ChannelInitializer》
《精尽 Netty 源码解析 —— ChannelHandler(四)之 LoggingHandler》
《精尽 Netty 源码解析 —— ChannelHandler(六)之 AbstractTrafficShapingHandler》
1.2.6 ChannelPipeline
Netty 在事件处理上,是通过ChannelPipeline来控制事件流,通过调用注册其上的一系列ChannelHandler来处理事件,这也是典型的拦截 器模式。下面是和ChannelPipeline相关的接口及类图:
事件流有两种,upstream事件和downstream事件。在ChannelPipeline中,其可被注册的ChannelHandler既可以 是 ChannelUpstreamHandler 也可以是ChannelDownstreamHandler ,但事件在ChannelPipeline传递过程中只会调用匹配流的ChannelHandler。在事件流的过滤器链 中,ChannelUpstreamHandler或ChannelDownstreamHandler既可以终止流程,也可以通过调用 ChannelHandlerContext.sendUpstream(ChannelEvent)或 ChannelHandlerContext.sendDownstream(ChannelEvent)将事件传递下去。下面是事件流处理的图示: 从上图可见,upstream event是被Upstream Handler们自底向上逐个处理,downstream event是被Downstream Handler们自顶向下逐个处理,这里的上下关系就是向ChannelPipeline里添加Handler的先后顺序关系。简单的理 解,upstream event是处理来自外部的请求的过程,而downstream event是处理向外发送请求的过程。 服务端处 理请求的过程通常就是解码请求、业务逻辑处理、编码响应,构建的ChannelPipeline也就类似下面的代码片断:ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder());
pipeline.addLast("handler", new MyBusinessLogicHandler());
其中,MyProtocolDecoder是ChannelUpstreamHandler类型,MyProtocolEncoder是 ChannelDownstreamHandler类型,MyBusinessLogicHandler既可以是 ChannelUpstreamHandler类型,也可兼ChannelDownstreamHandler类型,视其是服务端程序还是客户端程序以及 应用需要而定。
补充一点,Netty对抽象和实现做了很好的解耦。像org.jboss.netty.channel.socket包, 定义了一些和socket处理相关的接口,而org.jboss.netty.channel.socket.nio、 org.jboss.netty.channel.socket.oio等包,则是和协议相关的实现。
对应源码解析文章:
《精尽 Netty 源码解析 —— ChannelPipeline(二)之添加 ChannelHandler》
《精尽 Netty 源码解析 —— ChannelPipeline(四)之 OutBound 事件的传播》
《精尽 Netty 源码解析 —— ChannelPipeline(六)之异常的传播》
1.2.7 Codec Framework
对于请求协议的编码解码,当然是可以按照协议格式自己操作ChannelBuffer中的字节数据。另一方面,Netty也做了几个很实用的codec helper,这里给出简单的介绍。
1)FrameDecoder:FrameDecoder内部维护了一个 DynamicChannelBuffer成员来存储接收到的数据,它就像个抽象模板,把整个解码过程模板写好了,其子类只需实现decode函数即可。 FrameDecoder的直接实现类有两个:(1)DelimiterBasedFrameDecoder是基于分割符 (比如rn)的解码器,可在构造函数中指定分割符。(2)LengthFieldBasedFrameDecoder是基于长度字段的解码器。如果协 议 格式类似“内容长度”+内容、“固定头”+“内容长度”+动态内容这样的格式,就可以使用该解码器,其使用方法在API DOC上详尽的解释。 2)ReplayingDecoder: 它是FrameDecoder的一个变种子类,它相对于FrameDecoder是非阻塞解码。也就是说,使用 FrameDecoder时需要考虑到读到的数据有可能是不完整的,而使用ReplayingDecoder就可以假定读到了全部的数据。 3)ObjectEncoder 和ObjectDecoder:编码解码序列化的Java对象。 4)HttpRequestEncoder和 HttpRequestDecoder:http协议处理。
下面来看使用FrameDecoder和ReplayingDecoder的两个例子:public class IntegerHeaderFrameDecoder extends FrameDecoder {
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buf) throws Exception {
if (buf.readableBytes() < 4) {
return null;
}
buf.markReaderIndex();
int length = buf.readInt();
if (buf.readableBytes() < length) {
buf.resetReaderIndex();
return null;
}
return buf.readBytes(length);
}
}
而使用ReplayingDecoder的解码片断类似下面的,相对来说会简化很多。
public class IntegerHeaderFrameDecoder2 extends ReplayingDecoder {
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buf, VoidEnum state) throws Exception {
return buf.readBytes(buf.readInt());
}
}
就实现来说,当在ReplayingDecoder子类的decode函数中调用ChannelBuffer读数据时,如果读失败,那么 ReplayingDecoder就会catch住其抛出的Error,然后ReplayingDecoder接手控制权,等待下一次读到后续的数据后继 续decode。
public class IntegerHeaderFrameDecoder2 extends ReplayingDecoder {
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buf, VoidEnum state) throws Exception {
return buf.readBytes(buf.readInt());
}
}
对应源码解析文章:
《精尽 Netty 源码解析 —— Codec 之 ByteToMessageDecoder(二)FrameDecoder》
《精尽 Netty 源码解析 —— Codec 之 ByteToMessageCodec》
1.2.8 小结
尽管该文行至此处将止,但该文显然没有将Netty实现原理深入浅出的说全说透。当我打算写这篇文章时,也是一边看Netty的代码,一边总结些可写的东 西,但前后断断续续,到最后都没了多少兴致。我还是爱做一些源码分析的事情,但精力终究有限,并且倘不能把源码分析的结果有条理的托出来,不能产生有意义 的心得,这分析也没什么价值和趣味。而就分析Netty代码的感受来说,Netty的代码很漂亮,结构上层次上很清晰,不过这种面向接口及抽象层次对代码 跟踪很是个问题,因为跟踪代码经常遇到接口和抽象类,只能借助于工厂类和API DOC,反复对照接口和实现类的对应关系。就像几乎任何优秀的Java开源项目都会用上一系列优秀的设计模式,也完全可以从模式这一点单独拿出一篇分析文 章来,尽管我目前没有这样的想法。而在此文完成之后,我也没什么兴趣再看Netty的代码了。
另外,Netty 中,提供了大量为了提升性能的工具类:
《精尽 Netty 源码解析 —— Util 之 FastThreadLocal》
《精尽 Netty 源码解析 —— Util 之 HashedWheelTimer》
1.3 精尽 Netty 面试题
正在整理 ing…
如果胖友对 NIO 不了解,可以看看如下入门的内容:
《精尽 Netty 源码分析 —— NIO 基础(二)之 Channel》
《精尽 Netty 源码分析 —— NIO 基础(四)之 Selector》