mmap 報錯解決
今天修改了一下測試環境的Nginx的nginx.conf,然后做檢測的時候報了一個錯誤
/usr/local/bin/nginx -c /usr/local/etc/openresty/conf/nginx.conf -t
nginx: [alert] mmap(MAP_ANON|MAP_SHARED, 314572800) failed (12: Cannot allocate memory)
nginx: configuration file /usr/local/etc/openresty/conf/nginx.conf test failed
報錯提示很清楚,不能分配內存了。為什么不能分配內存了?基本上就是物理內存不夠使用了,先查了下內存
free -m
total used free shared buff/cache available
Mem: 990 568 75 54 347 224
Swap: 0 0 0
可以看到,真正可以被使用的內存大概就是224M。那就是Nginx此次檢查的配置需要使用大於224M的內存。按理說,Nginx自身不需要多少內存。我們系統中大量使用openresty,首先懷疑可能openresty的某個引用申請內存過多了,然后查找了下配置,果然發現openresty的共享內存的使用。
lua_shared_dict xxx 300m;
lua_shared_dict yyy 100m;
總共需要400M內存,這兩個共享內存該小點應該就可以了。改為
lua_shared_dict xxx 100m;
lua_shared_dict yyy 30m;
然后檢查通過
/usr/local/bin/nginx -c /usr/local/etc/openresty/conf/nginx.conf -t
nginx: the configuration file /usr/local/etc/openresty/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/openresty/conf/nginx.conf test is successful
檢測是成功,reload Nginx成功生效。
Nginx 申請內存的模塊
可能有的不一定是openresty共享內存的鍋。Nginx配置需要配置內存的地方其實不多,一個個排查就可以做到。
openresty lua_shared_dict
lua_shared_dict 定義在http模塊。
聲明共享內存區,共享內存區始終由當前Nginx服務器實例中的所有Nginx進程共享。
參數接受大小單位,比如K 和M 等等。
http {
lua_shared_dict dogs 10m;
...
}
proxy_cache_path
proxy_cache_path path [levels=levels] keys_zone=name:size
path 設置緩存的路徑
levels 設置緩存文件的層級,當levels=1:2時,表示是兩級目錄,1和2表示用1位和2位16進制來命名目錄名稱。
keys_zone 設置共享內存的名稱和大小,keys_zone=one:10m,表示共享內存名稱是one,大小是10M,這里設置內存過高,就會出現開頭的報警,mmap(MAP_ANON|MAP_SHARED, 314572800)
配置設置成這樣
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
路徑和層級就是下面的
/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
limit_req_zone
limit_req_zone key zone=name:size rate=rate
設置共享內存的限流參數
主要看下應用
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
使用客戶端的IP作為限流的key,共享內存分配了10M,共享內存的名稱是one,速度是每個客戶端IP每秒1個請求,超過1個請求可能會延遲或者直接拒絕,要看limit_req的配置。
$binary_remote_addr變量的大小為4個字節。在64位平台上始終占據128字節。 一個1M的區域可以保留約約8000個客戶端IP。所以10M大概可以准確存儲8萬個客戶端IP。如果限流的客戶端IP超過了8萬個,就應該擴大共享內存。
limit_conn_zone
limit_conn_zone key zone=name:size;
設置連接數限流的參數
limit_conn_zone $binary_remote_addr zone=addr:10m;
連接數限流的參數跟請求數參數類似。
使用客戶端的IP作為限流的key,共享內存分配了10M,共享內存的名稱是addr。10M可以存儲8萬個客戶端IP。限流的具體數量限制是由limit_conn配置
比如
limit_conn addr 1;
就表示每個客戶端IP同時只能有一個連接存在。
總結Nginx mmap
所以,如果以后遇到關於Nginx mmap(MAP_ANON|MAP_SHARED, 314572800)報錯,首先應該檢查可能分配大內存的配置,首要檢查的就是這兩個
lua_shared_dict
proxy_cache_path
修改這兩個參數就可以解決問題。
一般
limit_req_zone
limit_conn_zone
分配的內存很小,至多幾十M,不會直接導致系統沒有內存可分配。