极客专栏《Nginx核心知识100讲》38小节的笔记
nginx 不同的worker之间需要共享信息的时候,只能通过共享内存。共享内存会使用链表,红黑树这样的数据结构。但是每个红黑树上有很多节点,每个节点上都需要分配内存去存放。怎样把一整块共享内存切割成一小块给红黑树上面的每一个节点使用呢?
slab内存管理
image.png image.png首先,会把共享内存分为很多页面,每个页面4k,会切成很多slot。比如32字节是一种slot,64字节是一种slot,128字节也是一种slot。这些slot是以乘2的方式向上增长的。如果现在有一个51字节需要分配的内存会放到哪里呢?会放在小于它最大的slot的环节比如64字节。这样的数据结构有个缺点,就是内存浪费。比如:51字节用64字节存放,其他13字节浪费了。最多有多少内存消耗呢?两倍。这种使用的方式叫做Bestfit,这种分配方式的好处是适合小对象。如果我们分配的内存非常小,比如小于一个页面的大小就非常合适,很少有碎片。 每分配一块内存就是沿着还没使用的空白内存继续使用。当一个页面使用满以后,再拿一个空闲页面给slab slot大小的内存继续使用。
有时候分配在一段内存上的数据结构是固定的,需要初始化,用Bestfit这种方式原先的数据结构都还在。当重复使用的时候,避免了初始化。
slab内存,应用在Openresty的 lua_shared_dict 以及limit request 、limit connection。
ngx_slab_stat:统计Slab 使用状态
数据监控,数据统计。
image.png可以看不同的slot,分配了多少,使用了多少,有多少请求在访问,失败了多少次。
Openresty如何使用ngx_slab_stat模块
下载tengine,该模块路径tengine-2.2.3/modules/ngx_slab_stat
。这是一个标准的nginx第三模块,每个第三方模块会通过C文件定义好nginx_module_t这样的结构体、以及处理哪些配置项、提供哪些变量、并有一个config来帮助它编译到目标nginx中。
Openresty编译的把ngx_slab_stat模块编译进去。然后使用lua_shared_dict 分配内存,再用slab_stat去查看共享内存的使用情况。
image.pngadd_module 这个命令可以把一个目录下具备config这样配置项的目录添加到nginx目录中。让模块的源码让./configure 识别到。
slab_stat 如何使用
image.pnglocation slab_stat中的slab_stat是一个slab_stat提供的配置项,会返回slab_stat统计状况。
代码走起
image.png image.png image.pngslab 内存分配了Bestfit思想,也是linux操作系统经常使用的内存分配方式。通常我们使用共享内存时都需要使用slab 分配给相应的内存给对象,再使用上层的数据结构维护这个对象。
留言问题
- 我编译之后将代码写进conf文件,提示nginx: [emerg] unknown directive "slab_stat",是不是还缺少什么东西。nginx -V 是否可以查看到slab是否已经编译进去,我发现nginx -V 没有显示slab模块。
2018-12-20
作者回复
你是不是没有把编译生成的新版本nginx,替换到安装sbin目录下?
2.我在使用 --add-module 新增slab模块的时,是不是要设置 --prefix 指定我之前安装的目录,然后再替换make编译后的 nginx二进制文件,才能使用新增模块呢?如果要替换nginx二进制文件,是不是都得全部重新编译一遍呢?
作者回复
prefix不建议变化,这样简单点。
要替换nginx文件,需要确保编译出的新nginx含有你需要的全部模块。
网友评论