Author: haoransun
Wechat: SHR—97
学习来源:极客时间-Nginx核心知识100讲,本人购买课程后依据视频讲解汇总成个人见解。
前言
Nginx是一个多进程程序,不同的Worker进程间如果想要共享数据,只能通过共享内存来通讯。那么Nginx中的共享内存如何使用的呢?这个问题值得研究。
Nginx进程间通讯方式
信号:前文也提及过。
共享内存:数据同步。所谓的共享内存也就是我们打开了一个内存空间,如10M,那么一整块0-10M内存,多个Worker之间可以同时访问它,包括读取、写入等操作。为了使用好这样一块共享内存,就会引出另外两个问题。
第一个就是锁,多个Worker进程同时操作一块内存,一定会出现竞争关系,不得不加锁。早期是基于信号量的锁,信号量是Linux中比较久远的一种进程同步方式,会导致进程进入休眠状态,即发生了主动切换。而现在大都使用的是自旋锁,当锁的条件没有满足,会一直请求。如:这块内存被Worker1使用,Worker2需要去获取锁时,只要Worker1没有释放锁,Worker2会一直在不停地去请求这把锁。自旋锁要求所有的Nginx模块必须快速的使用共享内存,即快速取锁,快速释放锁。一旦出现有的第三方模块不遵守这样的规则,就可能导致死锁。
一整块共享内存通常是给许多对象同时使用的,如果在模块中手动的去编写、分配内存给到不同的对象,是非常繁琐的,此时引入了Slab内存管理器。
共享内存:跨worker进程通讯
红黑树 :限速、流控场景。(插入、删除快)。
单链表:将共享元素串起来。
Ngx_http_lua_api:Openresty核心模块
共享内存工具-Slab管理器
上文谈到Nginx不同的Worker进程间需要共享信息时,只能通过共享内存。共享内存上可以使用链表、红黑树这样的数据结构,但每一个红黑树上有许多节点,每一个节点都需要分配内存去存放。怎样把一整块共享内存切割成小块给红黑树上的每个节点使用呢?
Slab内存管理
详见 408 操作系统、计算机组成原理-内存管理与分配
Tengine上 ngx_sla_stat:统计Slab使用状态
会发现没有Github地址,即没有作为一个独立模块发布出来,所以只能点击Download下载整个Tengine项目。
解压后,发现tengine中多出一个modules目录,进去查看
在最后发现 ngx_slab_stat模块。
这是一个标准的第三方模块。.c文件是它的说明书。config帮助他编译进目标nginx中。
实践
现在回到Openresty中,让Openresty编译时将Tengine的Slab_Stat模块编译进去,然后使用Openrety下的 share_dict去分配共享内存,再用slab_state查看共享内存的使用情况。
1 | ./configure --add-module=../tengine-2.3.2/modules/ngx_slab_stat/ |
set、get、slab_stat 得到信息