首頁 > 軟體

一次nginx崩潰事件的實戰記錄

2023-02-03 18:04:23

一、事件描述

2023年春節復工第一天,專案組同事反饋說業務系統中影象處理代理Nginx服務於1月23日發生崩潰,完成了重啟操作,檢查nginx的紀錄檔有如下報錯:

2023/01/23 11:07:07 [crit] 3237#3237: *2253009 pwritev() "/var/cache/nginx/client_temp/0000743846" 
failed (28: No space left on device), 
client: 10.14.32.3, server: localhost, 
request: "POST /Test HTTP/1.1", host: "10.14.32.2:5500"

二、檢查分析

1)檢查當前檔案系統使用情況,未出現分割區使用超限情況,應該是nginx重啟後快取釋放了;

2)檢查nginx組態檔,為對快取進行額外設定,在編譯時設定了快取目錄,如下:

nginx version: nginx/1.16.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
built with OpenSSL 1.1.1k 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-openssl=/home/software/openssl-1.1.1k --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt=‘-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC’ --with-ld-opt=‘-Wl,-z,relro -Wl,-z,now -pie’

設定項說明:執行對應模組時nginx所保留的臨時檔案
–http-client-body-temp-path=/var/cache/nginx/client_temp
–http-proxy-temp-path=/var/cache/nginx/proxy_temp
–http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp
–http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
–http-scgi-temp-path=/var/cache/nginx/scgi_temp

3) 設定Nginx靜態檔案快取

##代理cache##
proxy_connect_timeout 500;
#跟後端伺服器連線的超時時間_發起握手等候響應超時時間
proxy_read_timeout 600;
#連線成功後_等候後端伺服器響應的時間_即已經進入後端的排隊之中等候處理的過程時間
proxy_send_timeout 500;
#後端伺服器資料回傳時間_即在規定時間內後端伺服器必須傳完所有資料的時長
proxy_buffer_size 128k;
#代理請求快取區_這個快取區間會儲存使用者的頭資訊以供Nginx進行規則處理_一般只要能儲存下頭資訊即可
proxy_buffers 4 128k;
#同上 告訴Nginx儲存單個使用者的幾個Buffer最大用多大空間
proxy_busy_buffers_size 256k;
#如果系統很忙的時候可以申請更大的proxy_buffers 官方推薦*2
proxy_temp_file_write_size 128k;
#proxy快取臨時檔案的大小
proxy_temp_path /usr/local/nginx/temp;
#用於指定本地目錄用來緩衝較大的代理請求的目錄,如果編譯設定了--http-proxy-temp-path,也可以採取預設
proxy_cache_path /usr/local/nginx/cache levels=1:2 keys_zone=cache_proxy:200m inactive=1d max_size=30g;
#設定web快取區名為cache_proxy,記憶體快取空間大小為200M,自動清除超過1天沒有被存取過的快取資料,硬碟快取空間大小30g;levels=1:2定義目錄深度,並且第一層目錄為1個字元,第二層目錄為2個字元
#這裡設定的需要快取的靜態資源字尾名
location ~* 「.(jpg|jpeg|png|gif|html|css|js|woff2|woff|map)?$」 {
proxy_pass http://fdfs;
proxy_cache cache_proxy;
proxy_cache_valid 200 24h; #200狀態快取24小時
proxy_cache_valid 302 10m; #302狀態快取10分鐘
proxy_set_header Host $host;
expires -1;
add_header X-Cache-Status $upstream_cache_status; #在http頭部增加一個字>段顯示是否命中快取
}
#reload後,當出現cache manager process程序時表明快取已經建立成功

三、處理

1)針對本次場景,最簡單就是遷移目錄到儲存空間更大的儲存上;

2)設定定期清除快取,nginx快取雖然可帶來吞吐量和效能的提升,但有時候快取過期後並不會釋放,這時我們可藉助nginx + ngx_cache_purge 模組,手動清除快取;

wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
tar -zxvf ngx_cache_purge-2.3.tar.gz
cp /sbin/nginx /sbin/nginx.back
nginx -V
./configure --prefix=/etc/nginx (略) --add-module=/root/app/ngx_cache_purge-2.3 
make -j2 #是 make 編譯, 不是 make install ,make install 會覆蓋原來已經安裝好的內容。編譯必須沒有錯誤
objs/nginx -V  //驗證編譯完成後,複製到sbin目錄下
/sbin/nginx -s reload
#清除快取設定
location ~ /clear_cache(.*) {
     #proxy_cache_purge imooc_cache $host$1$is_args$args;
     #刪除指定快取區域cache_one的特定快取檔案$1$is_args$args
     proxy_cache_purge cache_one $1$is_args$args;
     #執行本機和10.0.16.0/24;網段的機器存取,拒絕其它所有
     allow           127.0.0.1;
     allow           10.0.16.0/24;
     deny          all;
}
#這樣清理某個快取檔案的時候地址前面加上 /clear_cache 即可,比如瀏覽器存取:
http://10.0.16.12:5500/clear_cache//api/index.php

沒有快取返回結果如下:

#範例2:控制滿足條件不快取
server
{
    ……
    location /api/ {
       set $a 0; #設定初始值
       if ( $request_uri ~ /api/noapi/(.*) ){
           set $a 1; #如果滿足不快取 設定為1
       }

       proxy_no_cache $a;
     ……
    }
    location ~ /clear_cache(.*) {
         allow   all;
         proxy_cache_purge imooc_cache $host$1$is_args$args;
    }
}

#範例3:
add_header      Nginx-Cache     "$upstream_cache_status";
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;

set $nocache 0;
# 以 aaa,bbb,ccc 開頭的不快取
if ($request_uri ~ ^/(aaa|bbb|ccc)) {
    set $nocache 1;
}
proxy_cache_bypass $nocache;

# cookie 裡面設定了nocache,或者 引數傳值裡有aaa,bbb 的不快取,滿足一個即可

proxy_no_cache $cookie_nocache $arg_aaa $arg_bbb;

#client_body模組設定, nginx對使用者端請求緩衝區大小有個預設限制,如果超過了該值(比如在上傳大檔案時),會報500錯誤。
client_body_buffer_size SIZE // 指定使用者端請求體緩衝區大小,如果請求大於該值,會報「500 Internal Server Error」錯誤。
client_body_temp_path	 /var/tmp/nginx DIR  [l1][lve2][lve3] //指定請求體臨時檔案的存放目錄,可有多級。
client_max_body_size  SIZE //允許使用者端請求的最大單檔案位元組數,如果請求體大於該值,會報「413 Request Entity Too Large」錯誤。

3)也可以藉助 tmpwatch命令加入定時任務來清理,其實,系統/tmp目錄,預設情況下每日會處理一次,原理就是使用了tmpwatch。該命令會在/etc/cron.daily/目錄下生成一個tmpwatch檔案

yum  install -y tmpwatch
cat /etc/cron.daily/tmpwatch
#! /bin/sh
flags=-umc
/usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix 
	-x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 
	-X '/tmp/hsperfdata_*' 10d /tmp   #tmp目錄會刪除240小時未存取過的檔案,它可從指定的目錄中遞迴地搜尋並刪除指定的目錄中一段時間未存取的檔案。
/usr/sbin/tmpwatch "$flags" 30d /var/tmp  #刪除30天前的檔案
for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do
    if [ -d "$d" ]; then
	/usr/sbin/tmpwatch "$flags" -f 30d "$d"
    fi
done
#
/usr/sbin/tmpwatch -afv 3 /tmp //清除/tmp下三小時以內沒有使用的檔案,並將結果輸出。

四、附錄

參考1:https://cloud.tencent.com/developer/article/2048035

參考2:https://www.cnblogs.com/backups/p/nginx4.html

參考3:http://t.zoukankan.com/ecalf-p-4887382.html

總結

到此這篇關於一次nginx崩潰事件的文章就介紹到這了,更多相關nginx崩潰事件內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com