瓜农老梁

一个想分享点干货的家伙,微信公众号「瓜农老梁」

0%

前言

Netty所谓的池化就是先申请了一块大内存,后面需要分配的时候就来我这里分就完了。以堆外直接内存分配为例,Netty以Chunk为单位16M申请了一块连续内存,这么一大块内存是以平衡二叉树的形式组织起来的。分配的时候就从这颗树上找合适的节点。池化内存的分配是Netty的最为核心部分,这块的代码很多位运算,不太容易看懂,读的时候需要边调试边分析。

平衡二叉树

Netty使用平衡二叉树将申请到的Chunk块组织起来,如下图所示,并使用数组将整个树映射进去,见下文构造函数中memoryMap。

阅读全文 »

大家好,我是老梁,一个想跟大伙分享点干货的家伙。

到了一周中最放松的时刻,回来就10点多了,洗洗涮涮就到了11点了。

夜神人静了,喝了点碧螺春,老梁坐在沙发上抱着电脑跟大伙聊聊天。

今天聊聊居转户,申请过程中也是各种查询挺费劲,记录下或许对一些朋友有点用。

阅读全文 »

前言

在前面文章『Netty12# 池化内存框架流程』Netty会将不同的内存尺寸缓存起来,每个线程绑定了专属逻辑内存区域(PoolArena),减少资源竞争。每个线程绑定了缓存PoolThreadCache,内存分配时,先从当前线程绑定的PoolThreadCache缓存分配。下图为涉及到相关类的关系图:

工作过程:

@1 通过引导类传入NioEventLoopGroup,线程工厂创建的线程均为FastThreadLocalThread

@2 FastThreadLocalThread持有InternalThreadLocalMap(内部维护一个对象数组)

@3 当通过PooledByteBufAllocator#newDirectBuffer分配内存时,通过调用PoolThreadLocalCache#get()完成对InternalThreadLocalMap的第一次填充,对象数组下标为线程索引号,其对应的值为PoolThreadCache。

@4 PoolThreadCache是被当前线程缓存的对象

阅读全文 »

前言

资源是有限的,预测是必要的,然而意外也是可能发生的。我们可以看到一些重大生产事故往往是被突发的流量冲跨的,对流量的治理和防护就尤为重要。防患于未然,保障服务高可用,需要引起重视。另外我们也需要对标行业一流治理能力,本文介绍下高可用中另外一个成员,集群限流。

集群流控使用场景

场景一 需要控制调用总量

某些场景下,需要对APP应用某些资源(接口)的调用总量设置限制。例如:该APP由于依赖了第三方提供服务,第三方流量有限制,需要对总量进行管控。部署的节点可能扩缩容,这种单纯通过单机限流措施难以凑效。

阅读全文 »

大家好,我是老梁,一个想跟大伙分享点干货的家伙。

明天请假办点事,夜神人静了,喝了点白开水,到了一周中最放松的时候,老梁确放松不起来。

丢掉幻想,准备战斗!这句常见于官方辞令,老梁觉得用到个人身上也不违和,朗朗上口的,那就拿来用用。

那就最近也发生的事情和想法聊一下。不一定对,各位随便看看。

阅读全文 »


title:Q1# 问题整理20210529
categories:Questions
tags:Questions
date:2021-05-29 11:55:01


业务要发展,功能要增强,基础设施要完善,变更就无法避免,带来新功能的同时也带来了风险。整理下近期碰到的和被问的几个问题。

问题一

​ Zookeeper几乎每年都能听到有公司踩到坑,故事往往是这样:@1 多个业务线共用zk集群,某个新上的功能把zk当缓存用,大量创建zk路径,造成zk不堪重负瘫痪;@2 某个新上的功能往zk集群中写入过大消息,单条消息好几兆,造成zk集群性能下降,甚至带宽、磁盘被打满。

​ 知道可能的坑咱肯定不能再去踩了,重要中间件的独立zk集群彻底隔离,上面的问题基本可以避免。今天的故事却发生在watch的数量上。

现象

​ 从4月中旬左右发现zk的watch水位在翻倍增长,从200多万到400多万一直翻到800多万,一直到五一之后的12000万。watch水位的升高会影响与zk通信的延迟。

原因

​ SDK中有使用一个公共主题用于客户端行为收集,该主题下会被注册临时节点,临时节点会被watch用于一个特定功能。在卡点升级过程中随着服务应用的接入,注册的节点越来越多。例如:3000个临时节点每个节点都会有3000个watch数量,就会有3000的平方个watch数量,就是900万个watch数量

解决

​ 止血方案: 删除公共主题下的临时节点,watch数量水位恢复正常

​ 根除方案:剔除SDK中对注册节点的watch,例如:curator中用NodeCacheListener替代TreeCacheListener,同时移除关联节点的wath功能,或者对公共主题进行过滤,不再注册节点

阅读全文 »

前言

PooledByteBufAllocator作为池化内存分配的入口,提供了众多的配置参数和便捷方法。这篇主要撸下他们大体都啥含义、干啥用的。为后面池化内存其他组件做铺垫。

成员变量说明

下面的成员变量基本都提供了默认值,可以通过参数去自定义,下面表格给出具体说明。

成员变量 说明
DEFAULT_NUM_HEAP_ARENA PoolAreana(堆内存)个数,默认为核数的2倍,可以由参数-Dio.netty.allocator.numHeapArenas指定
DEFAULT_NUM_DIRECT_ARENA PoolAreana(堆外内存)个数默认为核数的2倍,堆外内存,可以通过-Dio.netty.allocator.numDirectArenas指定
DEFAULT_PAGE_SIZE 默认pageSize=8K,可以通过-Dio.netty.allocator.pageSize,需大于4096且为2的倍数
DEFAULT_MAX_ORDER 二叉树最高层数,取值范围为0~14,默认为11,可以通过-Dio.netty.allocator.maxOrder参数指定
DEFAULT_TINY_CACHE_SIZE 默认tiny类型缓存池大小512,可以通过-Dio.netty.allocator.tinyCacheSize指定
DEFAULT_SMALL_CACHE_SIZE 默认small类型缓存池大小为256,可以通过-Dio.netty.allocator.smallCacheSize指定
DEFAULT_NORMAL_CACHE_SIZE 默认normal类型缓存池大小为64,可以通过-Dio.netty.allocator.normalCacheSize指定
DEFAULT_MAX_CACHED_BUFFER_CAPACITY 默认为32KB,用于限制normal缓存数组的长度,可以通过-Dio.netty.allocator.maxCachedBufferCapacity指定
DEFAULT_CACHE_TRIM_INTERVAL 默认8192,分配次数阈值,超过后释放内存池,可以通过-Dio.netty.allocator.cacheTrimInterval指定
DEFAULT_CACHE_TRIM_INTERVAL_MILLIS 默认0不开启,定时释放内存池,可以通过-Dio.netty.allocator.cacheTrimIntervalMillis指定
DEFAULT_USE_CACHE_FOR_ALL_THREADS 默认true,使用线程缓存,可以通过-Dio.netty.allocator.useCacheForAllThread制定
DEFAULT_DIRECT_MEMORY_CACHE_ALIGNMENT 直接内存的校准对齐参数,分配内存时按位与(&)校准。默认0不校准,可以通过-Dio.netty.allocator.directMemoryCacheAlignment指定
DEFAULT_MAX_CACHED_BYTEBUFFERS_PER_CHUNK 默认1023,指定PoolChunk缓存ByteBuffer对象的最大数量,可以通过-Dio.netty.allocator.maxCachedByteBuffersPerChunk指定
MIN_PAGE_SIZE 校验用的,PageSize不能小于4KB
MAX_CHUNK_SIZE 校验用的,Chunk的边界值,(((long) Integer.MAX_VALUE + 1) / 2)
heapArenas Arena数组,元素为HeapArena
directArenas Arena数组,元素为DirectArena
PooledByteBufAllocatorMetric metric 暴露统计指标,例如:用了多少堆内存、用了多少堆外直接内存等
阅读全文 »

前言

本文简要梳理为什么使用池化内存?Netty使用池化内存从哪些方面提升了效率?梳理了池化内存的核心组件大体含义以及内存分配流程,勾勒池化内存的整体框架。后面文章会详细拆解每个点是如何实现的。

阅读全文 »

前言

非池化内存的分配由UnpooledByteBufAllocator负责,本文梳理下由其负责分配的堆内存和堆外内存如何实现的 。

Netty在非池化堆内存分配上Java9与Java8以下版本有啥不同呢?Netty堆外内存回收默认机制使用JDK提供的Cleaner吗?

阅读全文 »

前言

非池化/池化内存如何分配的?该撸这块了,奈何到处都在调用PlatformDependent类的方法,要不各种判断,要不分配堆外内存。反正到处都能看到它,得,索性先把这个撸一把。PlatformDependent又依赖了PlatformDependent0,那就一层一层剥好了。

嗯,有点碎,大伙随便看看。

阅读全文 »