极客专栏《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 模块
下载 http://tengine.taobao.org/download.html , 该模块路径 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.PNG
add_module 这个命令可以把一个目录下具备 config 这样配置项的目录添加到 nginx 目录中. 让模块的源码让./configure 识别到.
slab_stat 如何使用
image.PNG
location slab_stat 中的 slab_stat 是一个 slab_stat 提供的配置项, 会返回 slab_stat 统计状况.
代码走起
image.PNG
image.PNG
image.PNG
slab 内存分配了 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 含有你需要的全部模块.
来源: http://www.jianshu.com/p/9370ab2c55df