不知道Netty,面试只能凉凉......

一、标准的netty线程模型
双池合璧:

不知道Netty,面试只能凉凉......

文章插图
 
1、连接线程池:连接线程池专门负责监听客户端连接请求,并完成连接的建立(包括诸如握手、安全认证等过程) 。
连接的建立本身是一个极其复杂、损耗性能的过程,此处使用线程池,能够极大的增加处理客户端连接的能力 。
2、I/O线程池:连接线程池会将成功建立的连接注册到后端I/O线程池,由I/O线程池负责对相应连接的网络数据进行读写、编解码处理 。
在实际应用中,我们通常会定义相应的业务消息协议,并选择合适的序列化机制,netty I/O线程池部分根据预设的规则进行数据的编解码 。
二、延伸的业务线程池
不知道Netty,面试只能凉凉......

文章插图
 
 
其实我们这里说的业务线程池不在网络层处理逻辑里 。处理到I/O线程池部分,所需要的请求数据已经处理完毕,涉及具体的业务处理逻辑,比较复杂的,或者时间、性能消耗特别大的,通常我们会单独设置相应的线程池来处理 。
三、netty的极致性能设计1、无锁化设计I/O线程的内部串行化:
不知道Netty,面试只能凉凉......

文章插图
 
局部无锁化串行处理,避免多线程切换带来的复杂性及性能损耗(锁竞争、CPU资源分配) 。至于对于处理能力的考虑,可以通过调整I/O线程池容量来平衡 。
尽量避免I/O线程和业务线程混淆及切换 。
2、直接内存使用TCP接收和发送使用直接内存代替堆内存,避免了数据在堆内存和主内存之间的复制消耗,提升了I/O读取和写入的性能 。
不知道Netty,面试只能凉凉......

文章插图
 
3、transferTo依赖于操作系统零拷贝特性直接将缓冲区数据发送到相应的通道 。
不知道Netty,面试只能凉凉......

文章插图
 
传统的方式,先将源文件拷贝到内存,然后由内存写到目的文件 。
netty 利用 NIO FileChannel transferTo方法,通道对通道写数据 。
4、CompositeByteBuf组合缓存使用可以像操作单个缓存一样操作多个缓存,避免了传统的操作方式带来的内存复制性能消耗 。
不知道Netty,面试只能凉凉......

文章插图
 
5、内存池使用netty支持通过内存池的方式循环利用ByteBuf,避免了频繁的创建,销毁ByteBuf带来的资源及性能损耗 。
ByteBuf byte数据缓冲区,是NIO编程的主要对象 。高负载情景下,ByteBuf内存池使用,可以有效降低GC频率 。
PoolArena netty的内存池实现类 。PoolArena 是由多个Chunk组成的大块内存区域,每个Chunk由一个多个Page组成 。
Chunk:组织管理Page的内存分配和释放,Page被构建为二叉树形式:
不知道Netty,面试只能凉凉......

文章插图
 
PoolSubpage:对于小于Page的内存使用,直接在Page中完成分配,每个Page切分为大小相同的多个存储块儿,存储块儿的大小由第一次申请的内存块儿大小决定 。
回收:netty使用状态位标识Chunk及Page内存可用性,Chunk标识二叉树Page节点使用状态;Page标识内部内存块儿的使用状态 。
6、线程安全优化合理的使用线程安全容器、原子类等,提升系统的并发处理能力,
7、引用计数器通过引用计数器及时的申请释放不再引用的对象,细粒度的内存管理降低了GC的频率,减少GC带来的时延增大和CPU损耗 。
Netty 4中 ByteBuf 和 ByteBufHolder 引入引用计数器功能(实现ReferenceCounted接口),在特定的对象上跟踪引用的数目 。
引用计数器初始为1 。如果对象活动的引用计数器大于0,则不会被释放 。当引用计数减少到0,实例将会被释放 。这也是 PooledByteBufAllocator 内存池应用的核心特性 。
作者:WindWant
来源:https://www.cnblogs.com/niejunlei/p/13070107.html

【不知道Netty,面试只能凉凉......】


    推荐阅读