BIO Blocking IO Listen Accept read write NIO non-blocking IO Reactor利用事件驱动机制 ,注册事件 ,事件发生时调用相应的回调函数 read decode compute encode send Reactor线程模型 Reactor单线程模型 acceptor和handler处理使用一个线程 Reactor多线程模型 accept线程 + handler处理线程池 Acceptor线程用于监听客户端请求 Reactor主从模型 mainReactor + subReactor mainReactor负责监听并Accept连接,然后将建立的socket 分派给subReactor subReactor负责读写网络数据 业务处理 交给worker线程池 int bossThreads = 2; int workerThreads = 8; EventLoopGroup bossGroup = new NioEventLoopGroup(bossThreads); EventLoopGroup workerGroup = new NioEventLoopGroup(workerThreads); ServerBootstrap b = new ServerBootstrap(); b.option(ChannelOption.SO_BACKLOG, 1024); b.group(bossGroup, workerGroup) Netty Accept连接和读写操作可以使用 单一线程 同一线程池 或 不同的线程池处理 JDK NIO bug JDK Epoll空轮询 导致 CPU 100% TCP 粘包/拆包 内置编解码器 LineBasedFrameDecoder DelimiterBasedFrameDecoder FixedLengthFrameDecoder LengthFieldBasedFrameDecoder 服务端 客户端 使用固定长度的解码器 ch.pipeline().addLast(new FixedLengthFrameDecoder(31)) 零拷贝 读取文件 发送数据 传统处理方式 1 File.read(bytes) 2 Socket.send(bytes) 需要四次数据拷贝和四次上下文切换 1. 数据从磁盘读取到内核缓冲区 2. 数据从内核缓冲区拷贝到用户缓冲区 3. 数据从用户缓冲区拷贝到内核的socket buffer 4. 数据从内核的socket buffer拷贝到网卡接口(硬件)的缓冲区 零拷贝实现 第二步和第三步可省略 使用 FileChannel.transferTo 1. 调用transferTo,数据从文件由DMA引擎拷贝到内核read buffer 2. 接着DMA从内核read buffer将数据拷贝到网卡接口buffer 使用 DMA 这两次拷贝不需要 cpu 参数 Netty中的零拷贝 bytebuffer io.netty.buffer.ByteBuf 堆外内存 DirectMemory DirectMemory 可以直接通过DMA发送到网卡接口 Composite Buffers 多个buffer组合 ,避免拷贝 FileChannel.transferTo