第三十六讲:用好共享内存工具:Slab管理器
? 剛剛我們談到nginx不同的worker進程間需要共享信息的時候,需要通過共享內存;我們也談到了共享內存上可以使用鏈表或者紅黑樹這樣的數據結構;但是每一個紅黑樹上有許多節點;每一個節點你需要分配內存去存放;那么怎么樣把一整塊共享內存切割成一小塊給紅黑樹上的每一個節點使用呢???
? 下面我們來看下Slab內存分配管理是怎么樣應用于共享內存上的;首先我們來看下Slab內存管理是怎么樣的一種形式;
? 它首先會把整塊的共享內存分為很多頁面;那么每個頁面例如4k;會切分為很多slot; 比如32字節是一種slot; 64字節又是一種slot; 128字節又是一種slot; 那么這些slot是以乘2的方式向上增長的; 如果現在有一個51字節需要分配的內存會放到哪里呢?會放于小于它最大的一個slot的一個環節; 比如說64字節;所以上圖中slot就是指向不同大小的塊;所以這樣的一種數據結構呢?它有一個特點;會有內存的浪費的。 就像我們剛剛所說的: 51字節它會用64字節來存放;那么其他的13字節就浪費了;那么最多會有多少消耗呢?還有兩倍: 這種使用的方式叫做Bestfit; Bestfit這種分配內存的方式有什么好處呢? 它適合小對象; 如果我們要分配的對象的內存非常小, 比如小于一個頁面的大小,就非常合適;因為它很少有碎片,那么每分配一塊內存,就會沿著還未分配的空白的地方繼續使用就可以了;當一個頁面使用滿以后,我再拿一個空白的頁面繼續給此類slot大小的內存繼續使用就可以。那么有時候我分配在某段內存上的數據結構它是固定的,甚至需要初始化;那么這樣的話,原先的數據結構都還在;當我重復使用的話,也避免了初始化;Slab內存管理中,我們怎么做數據的監控和統計呢?
? 那么tng上有一個模塊叫做slab_stat; slab_stat可以幫我們看不同的slot:
比如說: 8字節 16字節 ......等等
一共目前分配了多少,使用了多少,有多少個請求在訪問,失敗了多少次,這個對我們來監控Slab是非常有用處的;
?下面我們來看下怎么樣在openresty的場景下去使用tng上的slab_stat這個模塊;
首先我們打開tengine的頁面??http://tengine.taobao.org/document/ngx_slab_stat.html
但是會發現在這個模塊上沒有github的地址;也就是說它沒有作為一個獨立的模塊提供出來;那這個時候該怎么辦呢?
那么tengine怎么下載下來?從download里:
解壓后進入目錄查看多個modules目錄:
modules里有個ngx_slab_stat
再進入查看
可以看到
這是一個標準的nginx第三方模塊;因為每一個nginx第三方模塊會通過一個c文件定義好我們之前所說的ngx_module_t這么一個結構體;
以及處理哪些配置項 ,提供哪些變量;并有一個config來幫助他編譯到我們的目標nginx中 ;現在我們再回到 openresty中,讓openresty編譯的時候,把tengine的slab_stat模塊編譯進去;然后再使用openresty上的share_direct去分配共享內存;再用slab_stat查看我們共享內存的使用情況;
我們執行configure的時候,可以添加一個參數叫 --add-module=;--add-module=這個命令尼 可以將一個目錄下具備config的這樣一個配置項或者目錄添加到我們的nginx中,它的方式尼 也就是將這個模塊的nginx源碼能夠使我們的./configure 識別到;所以這里的configure和我們的官方configure是一樣的,那么我們現在開始編譯openresty;
編譯完成以后開始執行make命令:
如果之前已經安裝了openresty或者(nginx)
執行編譯make 好以后不需要make install
(1). 備份原來的nginx 可執行文件
cd /usr/local/openresty/nginx/sbin
cp nginx nginx.old
(2) 將編譯好的nginx可執行二進制文件復制到原始nginx的sbin目錄
cp /home/web/openresty-1.13.6.2/build/nginx-1.13.6/objs/nginx /usr/local/openresty/nginx/sbin/ -f
(3) 驗證是否成功安裝ngx_slab_stat
cd /usr/local/openresty/nginx/sbin
./nginx -V
現在openresty已經安裝完成了,這個openresty中,已經包含了ngx_slab_stat模塊;
我們以上一節中lua_shared_dict 那段代碼的例子,來講解下slab_stat是怎么使用的?
首先我們用 lua_shared_dict_dogs 10m; 分配了一個10m的共享內存,名字叫dogs;
使用的話,我們有一個set的url下;設置了一個key-value: Jim-8;設置在我們的共享內存下,并返回給用戶一個字符串叫STORED;
當收到get這個url請求時,會從dogs共享內存中取出Jim的值;也就是這里設置的8返回給用戶:
然后我們又增加了一個location,這個location叫做slab_stat,它里面的內容就是tengine中slab_stat提供的slab_stat配置項,這個配置項叫做slab_stat.
它會返回我們slab的所有的統計狀況:
nginx.conf 配置文件代碼:
lua_shared_dict dogs 10m;
??? server {
??????? listen 8080;
??????? server_name? localhost;
??????? #charset koi8-r;
??????? #access_log? logs/host.access.log? main;
??????? location = /slab_stat{
???????? slab_stat;
??????? }
??????? location /set{
??????????????? content_by_lua_block{
??????????????????????? local dogs=ngx.shared.dogs
??????????????????????? dogs:set("Jim",8)
??????????????????????? ngx.say("STORED");
??????????????? }
??????? }
??????? location /get {
??????????????? content_by_lua_block{
??????????????????????? local dogs=ngx.shared.dogs
??????????????????????? ngx.say(dogs:get("Jim"))
??????????????? }
??????? }
??????? location / {
??????????? #proxy_set_header Host?host;?????????????#proxy_set_header?X-Real-IPhost;?????????????#proxy_set_header?X-Real-IPremote_addr;
??????????? #proxy_set_header X-Forwarded-For?proxy_add_x_forwarded_for;?????????????#proxy_cache?my_cache;?????????????#proxy_cache_keyproxy_add_x_forwarded_for;?????????????#proxy_cache?my_cache;?????????????#proxy_cache_keyhosturiuriis_args&args;
??????????? #proxy_cache_valid 200 304 302 1d;
??????????? #proxy_pass http://local;
??????? }
?
配置項寫完,把ngixn啟動看看它的執行效果;
每一個slot及其slot對應的大小;分配了多少個,使用了多少個,失敗了多少個;
所謂分配就是10m是一個非常大的共享內存,它會劃分很多個頁面;對于比較小的比如32字節,一個頁面可以有128個;這里127可用,已經使用了一個;
總結:以上我們介紹了Slab內存的使用方法:slab使用了Bestfit思想,它也是Linux操作系統經常使用的內存分配方式;
那么通常我們在使用共享內存時,都需要使用slab_stat去分配相應的內存給對象,再使用上層的數據結構來維護這些數據對象;
總結
以上是生活随笔為你收集整理的第三十六讲:用好共享内存工具:Slab管理器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记一次糟心的内网靶场实战
- 下一篇: nginx+lua+redis 灰度发布