前言
大家好,我是老馬。很高興遇到你。
我們為 java 開發者實現了 java 版本的 nginx
https://github.com/houbb/nginx4j
如果你想知道 servlet 如何處理的,可以參考我的另一個專案:
手寫從零實現簡易版 tomcat minicat
手寫 nginx 系列
如果你對 nginx 原理感興趣,可以閱讀:
從零手寫實現 nginx-01-為什麼不能有 java 版本的 nginx?
從零手寫實現 nginx-02-nginx 的核心能力
從零手寫實現 nginx-03-nginx 基於 Netty 實現
從零手寫實現 nginx-04-基於 netty http 出入參最佳化處理
從零手寫實現 nginx-05-MIME型別(Multipurpose Internet Mail Extensions,多用途網際網路郵件擴充套件型別)
從零手寫實現 nginx-06-資料夾自動索引
從零手寫實現 nginx-07-大檔案下載
從零手寫實現 nginx-08-範圍查詢
從零手寫實現 nginx-09-檔案壓縮
從零手寫實現 nginx-10-sendfile 零複製
從零手寫實現 nginx-11-file+range 合併
從零手寫實現 nginx-12-keep-alive 連線複用
NGINX 除錯
透過除錯二進位制檔案、除錯日誌和核心轉儲來排除 NGINX 或 NGINX Plus 部署中的問題並追蹤錯誤。
介紹
除錯幫助您在程式程式碼出現問題時識別錯誤。它通常用於開發或測試第三方或實驗性模組。
NGINX 除錯功能包括除錯日誌和建立核心轉儲檔案以及進一步的回溯。
配置 NGINX 二進位制檔案進行除錯
首先,您需要在 NGINX 二進位制檔案中啟用除錯。NGINX Plus 已經為您提供了 nginx-debug 二進位制檔案,而 NGINX Open Source 需要重新編譯。
配置 NGINX Plus 二進位制檔案
從版本 8 開始,NGINX Plus 與標準二進位制檔案一起提供 nginx-debug 二進位制檔案。要在 NGINX Plus 中啟用除錯,您需要從 nginx 切換到 nginx-debug 二進位制檔案。開啟終端並執行以下命令:
service nginx stop && service nginx-debug start
完成後,在配置檔案中啟用除錯日誌。
編譯 NGINX Open Source 二進位制檔案
要在 NGINX Open Source 中啟用除錯,您需要使用 configure 指令碼中指定的 --with-debug 標誌重新編譯它。
要編譯支援除錯的 NGINX Open Source:
- 下載並解壓 NGINX 原始檔,轉到原始檔所在的目錄。參見下載原始碼。
- 獲取 NGINX 配置引數列表。執行命令:
nginx -V 2>&1 | grep arguments
- 將 --with-debug 選項新增到 configure 命令列表中並執行 configure 指令碼:
./configure --with-debug <其他 configure 引數>
- 編譯和安裝 NGINX:
sudo make
sudo make install
- 重新啟動 NGINX。
NGINX 和除錯符號
除錯符號有助於獲取用於除錯的附加資訊,例如函式、變數、資料結構、原始檔和行號資訊。
NGINX 預設使用“-g”標誌編譯,其中包含除錯符號。
但是,如果在執行回溯時出現“沒有可用的符號表資訊”錯誤,則表示缺少除錯符號,您需要重新編譯 NGINX 並支援除錯符號。
確切的編譯器標誌取決於編譯器。例如,對於 GCC 編譯器系統:
- 使用“-g”標誌包含除錯符號
- 使用“-O0”標誌禁用編譯器最佳化,使偵錯程式輸出更易於理解:
./configure --with-debug --with-cc-opt='-O0 -g' ...
在 NGINX 配置中啟用除錯日誌
除錯日誌記錄錯誤和與除錯相關的任何資訊,預設情況下是禁用的。要啟用它,請確保 NGINX 已編譯支援除錯(參見“為除錯配置 NGINX 二進位制檔案”),然後在 NGINX 配置檔案中使用 error_log 指令的 debug 引數啟用它。除錯日誌可以寫入檔案、記憶體中的分配緩衝區、標準錯誤輸出或 syslog。
建議在 NGINX 配置的“main”級別上啟用除錯日誌,以獲得正在進行的完整情況。
將除錯日誌寫入檔案
將除錯日誌寫入檔案可能會在高負載下降低效能。還要注意,檔案可能會變得非常大,快速消耗磁碟空間。為減少負面影響,您可以配置除錯日誌寫入記憶體緩衝區,或為特定 IP 地址設定除錯日誌。有關詳細資訊,請參閱“將除錯日誌寫入記憶體”和“選定 IP 的除錯日誌”。
要啟用將除錯日誌寫入檔案:
-
確保您的 NGINX 配置了 --with-debug 配置選項。執行命令並檢查輸出是否包含 --with-debug 行:
nginx -V 2>&1 | grep -- '--with-debug'
-
開啟 NGINX 配置檔案:
sudo vi /etc/nginx/nginx.conf
-
查詢 error_log 指令,預設情況下位於 main 上下文中,並將日誌級別更改為 debug。如果需要,更改日誌檔案的路徑:
error_log /var/log/nginx/error.log debug;
-
儲存配置並退出配置檔案。
將除錯日誌寫入記憶體
除錯日誌可以使用迴圈緩衝區寫入記憶體。優點是,在高負載下,除錯級別的日誌記錄對效能影響不大。
要啟用將除錯日誌寫入記憶體:
-
確保您的 NGINX 配置了 --with-debug 配置選項。執行命令並檢查輸出是否包含 --with-debug 行:
nginx -V 2>&1 | grep -- '--with-debug'
-
在 NGINX 配置檔案中,使用在 main 上下文中指定的 error_log 指令啟用除錯日誌的記憶體緩衝區:
error_log memory:32m debug; ... http { ... }
從記憶體中提取除錯日誌
可以使用在 GDB 偵錯程式中執行的指令碼從記憶體緩衝區中提取日誌。
要從記憶體中提取除錯日誌:
-
獲取 NGINX 工作程序的 PID:
ps axu |grep nginx
-
啟動 GDB 偵錯程式:
sudo gdb -p <在上一步中獲得的 nginx PID>
-
複製指令碼,將其貼上到 GDB 中並按“Enter”。該指令碼將在當前目錄中的 debug_log.txt 檔案中儲存日誌:
set $log = ngx_cycle->log while $log->writer != ngx_log_memory_writer set $log = $log->next end set $buf = (ngx_log_memory_buf_t *) $log->wdata dump binary memory debug_log.txt $buf->start $buf->end
-
透過按下 CTRL+D 退出 GDB。
-
開啟位於當前目錄中的“debug_log.txt”檔案:
sudo less debug_log.txt
選定 IP 的除錯日誌
可以為特定 IP 地址或 IP 地址範圍啟用除錯日誌。在生產環境中,記錄特定 IP 可能很有用,因為它不會對效能產生負面影響。IP 地址在事件塊中的 debug_connection 指令中指定;該指令可以定義多次:
error_log /path/to/log;
...
events {
debug_connection 192.168.1.1;
debug_connection 192.168.10.0/24;
}
每個虛擬主機的除錯日誌
通常,error_log 指令在主上下文中指定,因此適用於所有其他上下文,包括伺服器和位置。
但是,如果在特定伺服器或位置塊內指定了另一個 error_log 指令,則會覆蓋全域性設定,並且這樣的 error_log 指令將設定自己的日誌檔案路徑和除錯日誌級別。
要為特定虛擬主機設定除錯日誌,請在特定伺服器塊內新增 error_log 指令,並設定新的日誌檔案路徑和除錯日誌級別:
error_log /path1/to/log debug;
...
http {
...
server {
error_log /path2/to/log debug;
...
}
}
要禁用特定虛擬主機的除錯日誌,請在特定伺服器塊內指定 error_log 指令,並僅指定日誌檔案路徑:
error_log /path/to/log debug;
...
http {
...
server {
error_log /path/to/log;
...
}
}
啟用核心轉儲
核心轉儲檔案可以幫助識別和修復導致 NGINX 崩潰的問題。核心轉儲檔案可能包含諸如密碼和私鑰之類的敏感資訊,因此請確保對它們進行安全處理。
為了建立核心轉儲檔案,必須在作業系統和 NGINX 配置檔案中都啟用它們。
在作業系統中啟用核心轉儲
在作業系統中執行以下步驟:
-
指定一個工作目錄,用於儲存核心轉儲檔案,例如“/tmp/cores”:
mkdir /tmp/cores
-
確保該目錄可由 NGINX 工作程序寫入:
sudo chown root:root /tmp/cores sudo chmod 1777 /tmp/cores
-
禁用核心轉儲檔案的最大大小限制:
ulimit -c unlimited
如果操作以“Cannot modify limit: operation not permitted”結束,請執行以下命令:
sudo sh -c "ulimit -c unlimited && exec su $LOGNAME"
-
為 setuid 和 setgid 程序啟用核心轉儲。
- 對於 CentOS 7.0、Debian 8.2、Ubuntu 14.04,請執行以下命令:
echo "/tmp/cores/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern sudo sysctl -w fs.suid_dumpable=2 sysctl -p
- 對於 FreeBSD,請執行以下命令:
sudo sysctl kern.sugid_coredump=1 sudo sysctl kern.corefile=/tmp/cores/%N.core.%P
在 NGINX 配置中啟用核心轉儲
要在 NGINX 配置檔案中啟用核心轉儲:
-
開啟 NGINX 配置檔案:
sudo vi /usr/local/etc/nginx/nginx.conf
-
使用 working_directory 指令定義一個目錄,該目錄將儲存核心轉儲檔案。該指令在主配置級別上指定:
working_directory /tmp/cores/;
-
確保該目錄存在,並由 NGINX 工作程序寫入。在終端中執行以下命令:
sudo chown root:root /tmp/cores sudo chmod 1777 /tmp/cores
-
使用 worker_rlimit_core 指令指定核心轉儲檔案的最大可能大小。該指令也在主配置級別上指定。如果核心轉儲檔案大小超過該值,將不會建立核心轉儲檔案。
worker_rlimit_core 500M;
示例:
worker_processes auto; error_log /var/log/nginx/error.log debug; working_directory /tmp/cores/; worker_rlimit_core 500M; events { ... } http { ... }
透過這些設定,核心轉儲檔案將在“/tmp/cores/”目錄中建立,只有當其大小不超過 500 兆位元組時才會建立。
從核心轉儲檔案中獲取回溯資訊
回溯提供了關於程式崩潰時出錯的資訊。
要從核心轉儲檔案中獲取回溯資訊:
-
使用 GDB 偵錯程式開啟核心轉儲檔案,命令格式為:
sudo gdb <nginx_executable_path> <coredump_file_path>
-
輸入“backtrace”命令以從崩潰時的堆疊中獲取堆疊跟蹤資訊:
(gdb) backtrace
如果“backtrace”命令返回“沒有可用的符號表資訊”訊息,則需要重新編譯 NGINX 二進位制檔案以包含除錯符號。請參閱NGINX和除錯符號。
從執行中的程序中轉儲NGINX配置
您可以從主程序記憶體中提取當前的NGINX配置。當您需要:
- 驗證已載入的配置
- 如果磁碟上的版本被意外刪除或覆蓋,恢復以前的配置
配置轉儲可以透過提供一個GDB指令碼來獲得,只要您的NGINX具有除錯支援。
確保您的NGINX已經構建了除錯支援(在configure引數列表中使用--with-debug選項)。執行命令並檢查輸出是否包含--with-debug行:
nginx -V 2>&1 | grep -- '--with-debug'
獲取NGINX工作程序的PID:
ps axu | grep nginx
啟動GDB偵錯程式:
sudo gdb -p <在上一步中獲取的NGINX PID>
複製並貼上指令碼到GDB中,然後按“Enter”鍵。該指令碼將配置儲存在當前目錄中的nginx_conf.txt檔案中:
set $cd = ngx_cycle->config_dump
set $nelts = $cd.nelts
set $elts = (ngx_conf_dump_t*)($cd.elts)
while ($nelts-- > 0)
set $name = $elts[$nelts]->name.data
printf "Dumping %s to nginx_conf.txt\n", $name
append memory nginx_conf.txt \
$elts[$nelts]->buffer.start $elts[$nelts]->buffer.end
end
按下CTRL+D退出GDB。
開啟位於當前目錄中的nginx_conf.txt檔案:
sudo vi nginx_conf.txt
在請求幫助時
在請求除錯幫助時,請提供以下資訊:
- NGINX版本、編譯器版本和配置引數。執行命令:
nginx -V
-
當前完整的NGINX配置。請參閱從執行程序中轉儲NGINX配置
-
除錯日誌。請參閱在NGINX配置中啟用除錯日誌
-
獲取的回溯。請參閱啟用核心轉儲,獲取回溯資訊。
參考資料
https://docs.nginx.com/nginx/admin-guide/monitoring/debugging/