全部评论
大家都在搜:
扣666嗱视频中的完整面试文档,。。
1年前·湖南

0

分享
回复
[赞][赞][赞]
2年前·江苏

0

分享
回复
云霄讲Java(面试突击陪跑)
云霄讲Java(面试突击陪跑)

粉丝12.1万获赞47.7万

智能文稿

Netty核心知识学习笔记

Reactor线程模型

单线程Reactor模型

单线程Reactor模型中,Reactor、Acceptor和Handler均在同一个线程中执行。其缺点是Handler处理逻辑阻塞时,会导致整个业务执行链阻塞,无法接受新请求,造成性能瓶颈。

多线程单Reactor模型

为解决单线程模型的阻塞问题,引入线程池处理业务逻辑,使Reactor和Handler在不同线程执行。但该模型中所有I/O操作仍由单个NIO线程完成,在高并发场景下会出现性能瓶颈,原因包括:

  1. 单个NIO线程需处理成百上千的I/O操作,即使CPU负载达100%也无法支撑海量消息的读取和发送。
  2. NIO线程负载过重会导致处理速度变慢,客户端连接超时后重发请求,进一步加重负载,造成消息积压和超时。

主从Reactor多线程模型

为优化多线程单Reactor模型的瓶颈,引入主从Reactor多线程模型,包含三个主要角色:

  • Main Reactor:负责接受客户端连接请求,并将具体的业务I/O处理请求转发给Sub Reactor(可多个)。
  • Acceptor:接受请求并委托给Main Reactor线程池,起到转发作用。
  • Sub Reactor:负责数据的读写,在NIO操作中需注册通道的读事件(OP_READ)和写事件(OP_WRITE)。

Netty核心组件

Netty核心组件分为三层:网络通信层、事件调度层和服务编排层。

网络通信层

  • Bootstrap:客户端启动组件,负责连接远程Netty服务。
  • ServerBootstrap:服务端启动组件,负责启动监听端口,接受客户端连接。
  • Channel:网络通信的载体,用于数据的读写和传输。

事件调度层

  • EventLoopGroup:本质是线程池,负责接收I/O请求并分配给线程执行处理。
  • EventLoop:相当于线程池中的线程,负责处理绑定Channel的所有I/O事件。

服务编排层

  • ChannelPipeline:负责将多个ChannelHandler连接在一起,形成处理链。
  • ChannelHandler:I/O数据处理器,数据接收后由指定的Handler进行处理(如编解码)。
  • ChannelHandlerContext:保存ChannelHandler的上下文信息,用于Handler之间的交互。

ChannelPipeline工作原理

ChannelPipeline本质是一个双向列表,采用责任链模式。每个Channel对应唯一一个ChannelPipeline,ChannelPipeline维护由ChannelHandlerContext组成的双向列表,列表头为head context,尾为tail context,每个ChannelHandlerContext关联一个ChannelHandler。

初始化时通过调用Channel的pipeline()方法获取Pipeline对象,调用addLast()方法可在Pipeline末端插入ChannelHandlerContext。Handler的添加顺序会影响代码执行顺序,其中从头部往尾部的Handler称为Inbound(用于接收用户请求,如解码),从尾部往头部的Handler称为Outbound(用于给用户响应,如编码)。Netty内置了多种编解码器,也支持自定义ChannelHandler实现特定功能(如自定义通信协议)。

Netty优势分析

相比直接使用Java原生NIO API,Netty具有以下优势:

  1. 统一API:支持多种通信模型(阻塞、非阻塞、EPOLL等)。
  2. 简化开发:少量代码即可实现Reactor多线程模型及主从线程模型。
  3. 内置编解码器:解决TCP拆包/粘包问题。
  4. 协议支持:内置HTTP、WebSocket等多种通信协议。
  5. 高性能:在高吞吐量、低延时、低资源消耗场景下表现优于原生NIO,优化包括零拷贝、无锁化串行机制、内存池管理等。
  6. 成熟稳定:被Tomcat、Dubbo、RocketMQ等经典开源项目采用,经大型场景验证。
  7. 安全性:支持SSL、TLS等安全协议。

Netty零拷贝实现

零拷贝概念

零拷贝并非完全无拷贝,而是减少数据拷贝次数。传统I/O读写涉及4次用户态与内核态切换(上下文切换)及4次数据拷贝(2次CPU拷贝、2次DMA拷贝),导致性能低下。零拷贝通过减少拷贝次数提升性能。

Netty零拷贝的三种方式

  1. 直接内存(DirectByteBuffer):基于系统底层mmap机制,接收和发送数据均使用直接内存,避免字节缓冲区的二次拷贝。
  2. CompositeByteBuf:聚合多个ByteBuf对象,用户可像操作单个ByteBuf一样操作组合缓冲区,避免将多个小ByteBuf合并为大ByteBuf时的内存拷贝。
  3. transferTo方法:利用NIO的sendfile机制,直接将文件缓冲区数据发送到Socket,减少传统I/O中的多次拷贝。

Netty线程池默认大小解析

性能指标与任务类型

提升性能需降低延时(提高CPU处理能力)和提高吞吐量(提高I/O读写效率)。程序分为I/O密集型任务和CPU密集型任务:

  • CPU密集型任务:线程数理论上等于CPU核心数,实际设为CPU核心数+1(应对线程阻塞时的CPU利用率)。
  • I/O密集型任务:线程数与I/O耗时和CPU耗时比例相关,公式为:线程数 = CPU核心数 × (1 + I/O耗时/CPU耗时)。

Netty默认线程池大小

Netty默认线程池大小为CPU核心数的两倍,原因是其默认I/O耗时与CPU耗时比例(I/O ratio参数,默认值50)为1:1,代入I/O密集型任务公式:线程数 = CPU核心数 × (1 + 1) = 2 × CPU核心数。

实际应用建议

  • I/O密集型任务使用Netty默认配置即可。
  • 提高吞吐量还可通过缓存、微服务拆分、优化业务逻辑及算法等方式实现,无需过度关注线程池大小调整。

猜你喜欢

推荐视频

热榜推荐

热门视频