粉丝12.1万获赞47.7万
单线程Reactor模型中,Reactor、Acceptor和Handler均在同一个线程中执行。其缺点是Handler处理逻辑阻塞时,会导致整个业务执行链阻塞,无法接受新请求,造成性能瓶颈。
为解决单线程模型的阻塞问题,引入线程池处理业务逻辑,使Reactor和Handler在不同线程执行。但该模型中所有I/O操作仍由单个NIO线程完成,在高并发场景下会出现性能瓶颈,原因包括:
为优化多线程单Reactor模型的瓶颈,引入主从Reactor多线程模型,包含三个主要角色:
Netty核心组件分为三层:网络通信层、事件调度层和服务编排层。
ChannelPipeline本质是一个双向列表,采用责任链模式。每个Channel对应唯一一个ChannelPipeline,ChannelPipeline维护由ChannelHandlerContext组成的双向列表,列表头为head context,尾为tail context,每个ChannelHandlerContext关联一个ChannelHandler。
初始化时通过调用Channel的pipeline()方法获取Pipeline对象,调用addLast()方法可在Pipeline末端插入ChannelHandlerContext。Handler的添加顺序会影响代码执行顺序,其中从头部往尾部的Handler称为Inbound(用于接收用户请求,如解码),从尾部往头部的Handler称为Outbound(用于给用户响应,如编码)。Netty内置了多种编解码器,也支持自定义ChannelHandler实现特定功能(如自定义通信协议)。
相比直接使用Java原生NIO API,Netty具有以下优势:
零拷贝并非完全无拷贝,而是减少数据拷贝次数。传统I/O读写涉及4次用户态与内核态切换(上下文切换)及4次数据拷贝(2次CPU拷贝、2次DMA拷贝),导致性能低下。零拷贝通过减少拷贝次数提升性能。
提升性能需降低延时(提高CPU处理能力)和提高吞吐量(提高I/O读写效率)。程序分为I/O密集型任务和CPU密集型任务:
Netty默认线程池大小为CPU核心数的两倍,原因是其默认I/O耗时与CPU耗时比例(I/O ratio参数,默认值50)为1:1,代入I/O密集型任务公式:线程数 = CPU核心数 × (1 + 1) = 2 × CPU核心数。
0
0