Netty进阶之路:跟着案例学Netty

Netty进阶之路:跟着案例学Netty
作者: 李林锋
出版社: 电子工业
原售价: 79.00
折扣价: 56.10
折扣购买: Netty进阶之路:跟着案例学Netty
ISBN: 9787121352621

作者简介

李林锋 10年J**a NIO通信框架、平台中间件架构设计和开发经验。 目前在华为终端应用市场负责业务微服务化、云化、**化等相关设计和开发工作。 《Netty**指南》和《分布式服务框架原理与实践》作者。

内容简介

3.2.2 Netty内存池工作原理分析 Netty的内存池整体上参照jemalloc实现,主要数据结构如下。 (1)PooledArena:代表内存中一大块连续的区域,PoolArena由多个Chunk组成,每个Chunk由多个Page组成。为了提升并发性能,内存池中包含一组PooledArena。 (2)PoolChunk:用来组织和管理多个Page的内存分配和释放,默认为16MB。 (3)PoolSubpage:对于小于一个Page的内存,Netty在Page中完成分配。每个Page会被切分成大小相等的多个存储块,存储块的大小由**次申请的内存块大小决定。假如一个Page是8字节,如果**次申请的块大小是4字节,那么这个Page就包含两个存储块;如果**次申请的块大小是8字节,那么这个Page就被分成一个存储块。一个Page只能用于分配与**次申请时大小相同的内存,比如,一个4字节的Page,如果**次分配了1字节的内存,那么后面这个Page只能继续分配1字节的内存,如果有一个申请2字节内存的请求,就需要在新的Page中进行分配。 内存池的内存分配从PooledArena开始,一个PooledArena包含多个Chunk(PoolChunk),Chunk具体负责内存的分配和回收。每个Chunk包含多个Page(PoolSubpage),每个Page由大小相等的块(Region)组成,每个Page块大小由**次从Page申请的内存大小决定,某个Page中的块大小是相等的。PoolChunk默认为16MB,包含2048个Page,每个Page为8KB。 内存分配策略:通过PooledByteBufAllocator申请内存时,首先从PoolThreadLocalCache中获取与线程绑定的缓存池PoolThreadCache,如果不存在线程私有缓存池,则轮询分配一个Arean数组中的PooledArena,创建一个新的PoolThreadCache作为缓存池使用。 PooledArena在进行内存分配时对预分配的内存容量做判断,分为如下几种场景: (1)需要分配的内存小于PageSize时,分配tiny或者**all内存。 (2)需要分配的内存介于PageSize和ChunkSize之间时,则分配normal内存。 (3)需要分配的内存大于ChunkSize时,则分配huge内存(非池化内存)。 Netty内存池将内存分为几类:tiny(小于512B)、**all(大于等于512B,小于8KB)、normal(大于等于8KB,小于等于16MB)和huge(大于16MB),系统根据需要申请的内存大小选择合适的MemoryRegionCache。 在PooledArena中创建PoolChunk后,调用PoolChunk的allocate()方法进行真正的内存分配:PoolChunk通过二叉树记录每个PoolSubpage的分配情况,如图3-15所示。 PoolChunk用memoryMap和depthMap来表示二叉树,其中memoryMap存放的是PoolSubpage的分配信息,depthMap存放的是二叉树的深度。depthMap初始化之后就不再变化,而memoryMap则随着PoolSubpage的分配而改变。初始化时,memoryMap和depthMap的取值相同。节点的分配情况有如下三种可能。 (1)memoryMap[id] = depthMap[id]:表示当前节点可分配内存。 (2)memoryMap[id] > depthMap[id]:表示当前节点至少一个子节点已经被分配,无法分配满足该深度的内存,但是可以分配*小一些的内存(通过空闲的子节点)。 (3)memoryMap[id] = *大深度(默认为11) + 1:表示当前节点下的所有子节点都已经分配完,没有可用内存。 假设申请4KB的内存,内存分配过程如图3-16所示。 节点被标记为被占用之后,依次向上遍历*新父节点,直到根节点。将父节点的memoryMap[id]位置信息修改为两个子节点中的较小值,如图3-17所示。 获取到合适的节点之后,根据节点ID计算并获取subpageIdx,通过subpageIdx从PoolSubpage[] subpages中获取可用的PoolSubpage。如果PoolSubpage为空,则新建PoolSubpage对象,并将其加入PoolChunk的PoolSubpage[] subpages中,就可以参与后续的内存分配了。如果PoolSubpage不为空,说明是被使用完之后释放到了内存池中,重新初始化PoolSubpage,并将其加入内存池的双向链表中,参与内存分配。 调用PoolSubpage的allocate方法,返回代表PoolSubpage块存储区域的占用情况结果(long类型:高32位表示subPage中分配的位置,低32位表示二叉树中分配的节点),PoolArena根据上述信息调用PoolChunk的initBuf方法完成PooledByteBuf的内存分配。 Netty是J**a高性能网络编程的明星框架 在阿里等互联网公司Netty是程序员必须掌握的基础组件 现有Netty图书多是讲解其实现及原理的,缺少对实际应用的指导 在实际使用中遇到Netty故障,需要花大量实践摸索、试验解决 本书作者经过多年的积累,将遇到的问题进行分门别类的讲解 连接池资源泄漏、服务端意外退出、高并发性能波动及IoT海量连接等 除了描述问题的前因后果,还讲解了问题定位的各种思路和方法 以及对于Netty关键技术的剖许,再加上作者酣畅淋漓的文风 可以让你快速领悟到Netty专家花大量时间积累的经验 对于提高编程水平及分析解决问题的能力大有帮助