nginx的檔案描述符的學習之二

济南小老虎發表於2024-06-12

nginx的檔案描述符的學習之二


背景

雖然整理了下nginx的檔案描述符與啟動相關的內容
但是感覺自己學習的還不是很精細
想著繼續學習下

服務啟動之後的情況

master: 
0 -> /dev/null
1 -> /dev/null
2 -> /data/nginx/logs/error.log
3 -> 'socket:[18736914]'=
4 -> /data/nginx/logs/access.log
5 -> /data/nginx/logs/error.log
6 -> 'socket:[18750198]'=
7 -> 'socket:[18750199]'=
8 -> 'socket:[18736915]'=

worker
0 -> /dev/null
1 -> /dev/null
2 -> /data/nginx/logs/error.log
3 -> 'socket:[18734060]'=
4 -> /data/nginx/logs/access.log
5 -> /data/nginx/logs/error.log
6 -> 'socket:[18750198]'=
7 -> 'socket:[18750199]'=
8 -> 'socket:[18736915]'=
9 -> 'anon_inode:[eventpoll]'
10 -> 'anon_inode:[eventfd]'

然後可以lsof -i:443 進行一下檢視
DEVICE: 18750198
lsof -i:80 對應的是:
DEVICE: 18750199

Worker 其實多監聽了 epool. 
需要說明 nginx 使用的是 SO_REUSEPORT的方式多個程序監聽相同埠
SO_REUSEPORT支援多個程序或者執行緒繫結到同一埠,
提高伺服器程式的效能,解決的問題:

允許多個套接字 bind()/listen() 同一個TCP/UDP埠
每一個執行緒擁有自己的伺服器套接字
在伺服器套接字上沒有了鎖的競爭
核心層面實現負載均衡
安全層面,監聽同一個埠的套接字只能位於同一個使用者下面

其核心的實現主要有三點:
擴充套件 socket option,增加 SO_REUSEPORT 選項,用來設定 reuseport。
修改 bind 系統呼叫實現,以便支援可以繫結到相同的 IP 和埠
修改處理新建連線的實現,查詢 listener 的時候,
能夠支援在監聽相同 IP 和埠的多個 sock 之間均衡選擇。

所以可以設定多個 worker 可以提高Nginx的效能. 

開啟登入首頁後的情況

master 不會發生變化.
worker 會增加兩個連線:
 12 -> 'socket:[18757450]'=
 13 -> 'socket:[18757451]'=

如果不做任何操作,大約30s左右, 連結就會消失.
如果是第一次開啟 作為proxy nginx 是需要開啟兩個連線的:
1. 針對Chrome客戶端開啟一個連結.
2. 針對後端應用伺服器開啟一個連結.
並且兩者都會很快的因為超時而關閉. 

執行登入後的情況

14 -> 'socket:[18780175]'=
15 -> 'socket:[18780176]'=
16 -> 'socket:[18780177]'=
17 -> 'socket:[18780178]'=
18 -> 'socket:[18780198]'=
19 -> 'socket:[18776316]'=
20 -> 'socket:[18776311]'=
21 -> 'socket:[18776318]'=
22 -> 'socket:[18776313]'=
23 -> 'socket:[18776319]'=
24 -> 'socket:[18776320]'=
25 -> 'socket:[18776321]'=
26 -> 'socket:[18776325]'=
27 -> 'socket:[18768580]'=
28 -> 'socket:[18768581]'=

開啟登入頁, 以及執行完登入, 增加了如上的連結. 
然後我也可以透過 lsof -i 進行一下檢視
發現對端的 5000 應用埠有一個 socket :
COMMAND     PID   USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
nginx   3194027 nobody   28u  IPv4 18768581      0t0  TCP xxx:5000 (ESTABLISHED)

然後可以看到 443相關的資訊為:
COMMAND     PID   USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
nginx   3194026   root    7u  IPv4 18750199      0t0  TCP *:https (LISTEN)
nginx   3194027 nobody    3u  IPv4 18757073      0t0  TCP xxxx:55914 (ESTABLISHED)
nginx   3194027 nobody    7u  IPv4 18750199      0t0  TCP *:https (LISTEN)
nginx   3194027 nobody   11u  IPv4 18768545      0t0  TCP xxxx:36409 (ESTABLISHED)
nginx   3194027 nobody   12u  IPv4 18778113      0t0  TCP xxxx:36321 (ESTABLISHED)
nginx   3194027 nobody   13u  IPv4 18780174      0t0  TCP xxxx:36383 (ESTABLISHED)
nginx   3194027 nobody   14u  IPv4 18780175      0t0  TCP xxxx:36382 (ESTABLISHED)
nginx   3194027 nobody   15u  IPv4 18780176      0t0  TCP xxxx:36381 (ESTABLISHED)
nginx   3194027 nobody   16u  IPv4 18780177      0t0  TCP xxxx:36380 (ESTABLISHED)
nginx   3194027 nobody   17u  IPv4 18780178      0t0  TCP xxxx:36384 (ESTABLISHED)
nginx   3194027 nobody   18u  IPv4 18780198      0t0  TCP xxxx:36385 (ESTABLISHED)
nginx   3194027 nobody   27u  IPv4 18768580      0t0  TCP xxxx:36412 (ESTABLISHED)

然後經過一些列的簡單對照:
Chrome 會一個瀏覽器的tab頁面 產生 6個TCP連結. 
所以nginx 會一個正在進行登入操作的使用者產生至少 7個 fd的操作.
6個針對chrome的連結, 和一個針對後端的連結. 
因為有登入頁面和登入後頁面的區別.
登入頁面的 6個 檔案描述符應該很快就會消失.
所以如果在併發, 一個併發使用者, 至少需要 7個檔案描述符. 

關於引數配置的處理

1. 懷疑LR或者是jmeter 進行模擬測試時 只會產生一個 檔案描述符. 
    並且TCP的使用. 可能也會只有一個. 
    但是chrome 直接操作時會有六個TCP連結和六個nginx檔案描述符.
    所以理論上高併發情況下 線上使用者的壓力和壓力測試工具產生的壓力是不一樣的. 

2. 建議還是增加對應的引數配置, 並且經常觀察一下nginx的不同worker的壓力負載情況
    雖然是核心層進行負載均衡, 但是也不排除不同的nginx worker的壓力差距比較大
    此時可能需要使用nginx 繫結核心, 以及設定 Worker執行緒數量進行最佳化. 
    最大檔案開啟數不建議太小, 但是也不能太大, 太大的檔案描述符數可能會引起系統資源耗盡. 

3. 關於引數最佳化, 還是需要定期檢查的. 檔案描述符的監控和innode的監控比較相仿.
    很多人都會忽略這一部分的監控, 實際上這一塊產生問題往往比較難以發現和解決. 

相關文章