netty 4.1.34 源码浅析1
概述
- 参考
背景知识
- 单线程、多线程、线程池
- 单线程Reactor(Acceptor+IO Handler/性能、安全、可靠都存在问题)
- 多线程Reactor(Acceptor+IO Pool/当Acceptor需要鉴权,认证有很大损耗)
- 主从Reactor(Accept Pool+IO Pool)
- 一个Acceptor接收后,其他Acceptor负责鉴权/认证等,处理后将其注册到IO多路复用器,进行IO的读写
- 时间轮(tickMs/whileSize/Interval/currentTime+分层)
- web协议变更(减少加载时间与增加安全性)
- http1.0/http1.1/https/spdy(speedy)/http2
- ocsp(online certificate status protocol)
- Unix I/O模型
- 阻塞IO(进程被阻塞)
- 非阻塞IO(轮询查内核数据,进程非阻塞)
- IO复用型(通过注册fd到select/epoll系统调用,内核态感知fd准备好,则回调用户态进行数据复制)
- epoll相比与select,fd无限制(select=1024/epoll=>1GB=10万个)
- io效率不会随着fd的增加而线性下降(epoll使用活跃socket的回调,不会像select扫描所有socket列表,但是活跃的socket太多,效率就差不多)
- epoll使用mmap同一块内存共享内核与用户空间,无需消息在两个空间的复制
- epoll的api更简单
- 信号驱动IO模型(通过信号量通知应用,进行数据的内核态到用户态的复制)
- 异步IO(在内核态完成数据复制操作,应用只需处理业务逻辑)
- java IO模型
- BIO(通过线程池策略(伪异步)处理每一个socket,ServerSocket监听/Socket连接)
- NIO(ByteBuffer进行数据缓冲,使用Channel进行数据传输,利用Selector进行通道的轮询与管理,读写均是异步的)
- AIO(NIO的升级版,通过一系列的回调策略(CompletionHandler)完成应用功能,无需借助于Selector,对应于unix的异步IO)
- Netty好处
- api使用简单,二次开发门槛低
- 功能强大,多种预置编解码器
- 定制能力强,通过ChannelHandler进行二次扩展
- 成熟、稳定、性能高、社区活跃
- 零拷贝(堆外直接内存进行Socket读写)
- TCP的粘拆包
- 不同的数据包粘到一起,称之为粘包
- 同一数据包分多次传递,则称之为被拆包
- 可发生在TCP(套接字的缓冲区大小限制)/IP(MaxTUnit)/数据链路层(payload)
- java序列化的劣势
- 无法跨语言
- 序列化后的码流太大
- 序列化性能太低
- 可以选择Google的PB/Apache的Thrift/Jboss的Marshalling
- java内存模型
- 所有变量在主内存和线程的工作内存之间进行数据的传递
- 所有变量在主内存和线程的工作内存之间进行数据的传递
源码阅读问题
- ChannelHandlerContext是如何传递共享参数的?
- 上下文数据通过委托给Channel携带(channel().attr(key)),因为Channel和ChannelHandlerContext都继承了AttributeMap,DelegatingChannelHandlerContext中采用委托方式
- 在解析http协议时,为什么会有HttpRequest/HttpContent/LastHttpContent这几个对象产生?
- 主要是通过HttpObjectDecoder(解析ByteBuf为HttpMessage和HttpContent或者LastHttpContent,取决于内容数据块的长度;如果没有内容,则是createMessage创建HttpMessage的子类;如果有固定长度内容,且小于maxChunkSize,则DefaultLastHttpContent;最后有很多内容的时候,就是DefaultHttpContent、DefaultLastHttpContent)----所以这里有HttpRequest和HttpContent内容需要业务端分开处理
- 同时在上面HttpObjectDecoder解析层的父类,有更进一步的解析,io.netty.handler.codec.ByteToMessageDecoder#fireChannelRead----将解析出来的列表元素循环迭代对后续的处理器,对于理解http的HttpRequest与HttpContent/LastHttpContent至关重要
核心Code
Nio相关与netty相近
- nio相关概念可参看
- Channel(通道IO操作)
- read, write, connect, and bind
- asynchronous/
- ServerSocketChannel/ServerChannel/NioServerSocketChannel
- 上下文数据委托给Channel携带(channel().attr(key))
- Selector(IO多路复用器)
- ByteBuffer/ByteBuf
- ByteBuf为netty封装的缓冲区,主要是(0<=readerIndex<=writerIndex<=capacity)进行数据的读写
- Unsafe
netty特有
- Bootstrap、ServerBootstrap (引导类)
- EventLoop(处理注册Channel相关的io操作)
- NioEventLoop/NioEventLoopGroup(线程池) (线程和任务队列,支持任务运行)
- NioEventLoop管理Channel和Selector
- ChannelHandler(无锁化的串行化设计)/ChannelPipeline(拦截过滤器模式)
- ChannelInboundHandler/ChannelOutboundHandler
- ChannelInboundHandlerAdapter/ChannelOutboundHandlerAdapter/ChannelDuplexHandler
- ChannelHandlerContext(AttributeKey传递管道在多个处理器之间的共享信息)
- ChannelPipeline(Socket.read()---->Channel Chain/Channel Chain---->Socket.write())
- DefaultChannelPipeline
- Future(异步操作的结果)
netty常用编解码
- ChannelInboundHandlerAdapter(通过上下文前向传递到下一个ChannelHandler)
- ChannelInitializer(为Channel的管道添加处理器/channelRegistered/handlerAdded 调用initChannel)
- ByteToMessageDecoder(将ByteBuf转为Message Object)
- LineBasedFrameDecoder(以\n或者\r\n作为分隔符,进行ByteBuf的转化)
- DelimiterBasedFrameDecoder(将ByteBuf以分隔符的方式进行转化)
- FixedLengthFrameDecoder(以frameLength为分隔,进行解析)
- LengthFieldBasedFrameDecoder(以字段长度解析Byte,异常强大)
- lengthFieldOffset/lengthFieldLength----(决定字段长度在哪里)
- lengthAdjustment(内容长度=字段长度+长度调节值/因为字段长度可能只包含内容或者包含头信息或者字段长度的长度,所以长度调节值可正可负)
- initialBytesToStrip(转换出来的内容是否要省略些信息,例如头部信息或者字段长度)
- SnappyFrameDecoder(解码使用Snappy进行传输的ByteBuf)
- ObjectDecoder(利用LengthFieldBasedFrameDecoder进行传递)
- MessageToMessageDecoder(将Message Object转为Message Object/acceptInboundMessage/decode)
- StringDecoder(将ByteBuf转为String)
- Base64Decoder(将ByteBuf以Base64进行解码)
- ProtobufDecoder
- ChannelOutboundHandlerAdapter(通过上下文前向传递到下一个ChannelHandler)
- MessageToMessageEncoder
- LineEncoder
- StringEncoder
- Base64Encoder
- ProtobufEncoder(pb协议转换Message为ByteBuf)
- MessageToByteEncoder
- ObjectEncoder
- Bzip2Encoder(将ByteBuf使用Bzip2进行压缩)
- SnappyFrameEncoder(将ByteBuf使用Snappy格式压缩)
- MessageToMessageEncoder
http协议支持
- HttpObject
- HttpContent(大块对象支持)
- DefaultHttpContent
- LastHttpContent(EMPTY_LAST_CONTENT)
- HttpMessage(HttpRequest/HttpResponse的通用属性支持)
- HttpRequest
- DefaultHttpRequest
- HttpContent(大块对象支持)
- HttpObjectDecoder(解析ByteBuf为HttpMessage和HttpContent或者LastHttpContent,取决于内容数据块的长度;如果没有内容,则是createMessage创建HttpMessage的子类;如果有固定长度内容,且小于maxChunkSize,则DefaultLastHttpContent;最后有很多内容的时候,就是DefaultHttpContent、DefaultLastHttpContent)----所以这里有HttpRequest和HttpContent内容需要业务端分开处理
- HttpRequestDecoder()
- HttpResponseDecoder(解析ByteBuf为HttpResponse/HttpContent)
- HttpObjectEncoder(将HttpMessage或者HttpContent转换成ByteBuf)
- HttpRequestEncoder(HttpRequest/HttpContent转为ByteBuf)
- HttpResponseEncoder(HttpResponse/HttpContent转为ByteBuf)
- io.netty.handler.codec.ByteToMessageDecoder#fireChannelRead----将解析出来的列表元素循环迭代对后续的处理器,对于理解http的HttpRequest与HttpContent/LastHttpContent至关重要