nginx系列基础架构(5)---nginx内存问题
nginx内存池
在ngx_connection的结构体中有一个ngx_pool_t成员变量,这个变量对应了当前连接使用的内存池。内存池可以通过connection_pool_size的配置项类配置
- 连接内存池:每当我们有一个TCP连接的时候,这个TCP连接可能会运行很多个HTTP请求,连接没有关闭执行完一条请求后还去执行其它的请求。有一些内存为连接分配一次就够了,比如我去读取每个请求的前1K字节,在连接内存池上分配一次,只要连接不关闭我就不释放,当连接关闭的时候在释放内存。
connection_pool_size
的配置项控制。 - 请求内存池:每个HTTP请求当开始的时候并不知道分配多大的内存,通常会分配4K的内存,我们的URL或header往往需要分配这么多。
request_pool_size
的配置项控制
nginx中的共享内存
nginx的进程通讯主要有两种,一种是信号,就是前边说的进程的信号,要做数据的同步就需要使用到共享内存了
共享内存就是,我们打开了一部分内存,所有的worker进程都可以通过这块内存进行读写操作。要写使用好共享内存就必须注意两个问题一个是锁另个一是Slab内存管理器
锁:多个worker进程同时操作一块内存,一定会出现竞争关系,所以我们需要加锁。在nginx中的锁中,在早期使用的是基于信号量的锁,它会导致进程进入休眠状态。现在nginx使用的锁都是自选锁:当这个锁的条件没有满足,也就是说这块内存被1号worker进程使用,2号worker需要去获取锁的时候;只要1号进程没有释放锁,那么2号进程就会一直请求这把锁。
nginx中主要使用共享内存的模块:主要的是rbtree(红黑树)、单链表、ngx_http_lua_api
Slab内存管理器
slab首先会把内存分配成几个页面,每个页面会切非为多个slot,比如32字节、64字节、128字节的slot;slot是以乘2的方式向上增长的。
使用ngx_slab_stat模块统计slab使用状态
ngx_slab_stat是 tengine开发的模块,并且没有在github上管理,需要我们下载tengine的源码,从tengine源码包中去安装。
https://tengine.taobao.org/document/ngx_slab_stat.html
# 下载tengine源码
cd /usr/local/src
wget https://tengine.taobao.org/download/tengine-2.3.3.tar.gz
tar xf tengine-2.3.3.tar.gz
# 查看源码下面的ngx_slab_stat模块源码
ll
总用量 44
-rw-rw-r--. 1 root root 204 3月 29 2021 config
-rw-rw-r--. 1 root root 6627 3月 29 2021 ngx_http_slab_stat_module.c
-rw-rw-r--. 1 root root 3465 3月 29 2021 README.cn
-rw-rw-r--. 1 root root 3501 3月 29 2021 README.md
-rw-rw-r--. 1 root root 21430 3月 29 2021 slab_stat.patch
drwxrwxr-x. 2 root root 20 3月 29 2021 t
# 标准的第三方模块的结构
# 安装openresty
# 下载源码包
wget https://openresty.org/download/openresty-1.19.3.2.tar.gz --no-check-certificate
tar xf openresty-1.19.3.2.tar.gz
cd openresty-1.19.3.2
# configure
# --add-module=../tengine-2.3.3/modules/ngx_slab_stat/ 添加ngx_slab_stat模块
cd openresty-1.19.3.2
./configure --add-module=../tengine-2.3.3/modules/ngx_slab_stat/
# 编译安装
gmake && gmake install
# 进入目录
cd /usr/local/openresty/nginx/conf
vim nginx.conf
- 设置slab_stat
lua_shared_dict test 10m; # 分配10M的共享内存,叫test
server {
listen 8080;
server_name localhost;
location = /slab_stat {
slab_stat;
}
location /set {
content_by_lua_block {
local test = ngx.shared.test
test:set("fengling", 10) # 将fengling设置到共享内存
ngx.say("stored success")
}
}
location /get {
content_by_lua_block {
local test = ngx.shared.test
ngx.say(test:get("fengling"))
}
}
}
# 设置值
curl http://localhost:8080/set
stored success
# 获取值
curl http://localhost:8080/get
10
# slab_stat 统计结果
curl http://localhost:8080/slab_stat
* shared memory: test
total: 10240(KB) free: 10168(KB) size: 4(KB)
pages: 10168(KB) start:00007F7CE0C1C000 end:00007F7CE160C000
slot: 8(Bytes) total: 0 used: 0 reqs: 0 fails: 0
slot: 16(Bytes) total: 0 used: 0 reqs: 0 fails: 0
slot: 32(Bytes) total: 127 used: 1 reqs: 1 fails: 0
slot: 64(Bytes) total: 0 used: 0 reqs: 0 fails: 0
slot: 128(Bytes) total: 32 used: 3 reqs: 3 fails: 0
slot: 256(Bytes) total: 0 used: 0 reqs: 0 fails: 0
slot: 512(Bytes) total: 0 used: 0 reqs: 0 fails: 0
slot: 1024(Bytes) total: 0 used: 0 reqs: 0 fails: 0
slot: 2048(Bytes) total: 0 used: 0 reqs: 0 fails: 0