寫在前面
最近都在折騰 Nginx 服務器的學習和測試,前幾天稍微溫習了一下計算機網絡方面的知識(一方面是興趣,一方面是這次學習過程中因爲這些計算機基礎遺忘,有很多細節問題讓人很懵逼),也在 Linux 上試了一下 tcpdump
命令,通過抓包來驗證自己之前的各種猜想(因爲不懂所以瞎猜),分析數據包依舊是用的 Wireshark
之前一直以爲只要使用 Http1.1 協議就可以複用連接,節省反覆握手揮手的時間消耗,但抓包後才發現,"簡簡單單"的長連接使用,還真是涉及了 Nginx 、 JMeter 、 Tomcat 裏的很多配置啊
- JMeter 雖然在 Http 請求的配置中默認勾選了使用 KeepAlive,但是實際使用中並沒有生效
- Nginx 涉及到與客戶端的配置
keepalive_timeout
和keepalive_requests
,與後端服務器的配置keepalive
(1.15.3之後,upstream 模塊也新增了keepalive_timeout
和keepalive_requests
,本篇暫不涉及) - Tomcat 默認也有一個
keepAliveTimeout
配置
知道了這些相關配置後,一方面想實戰下 tcpdump
和 Wireshark 的使用,一方面也想用數據驗證下 Nginx 的這三個配置,所以就有了接下來的內容
環境說明
- Nginx 1.14.0
- Linux 2.6.32
- JMeter 5.0
- Wireshark 2.6.4
- JMeter 所在主機 IP 172.16.40.199
- Tomcat 所在主機 IP 172.16.40.201
- Nginx 所在主機 IP 172.16.40.224
0. 和客戶端的長連接超時時間
指令說明
語法: keepalive_timeout timeout [header_timeout];默認值: keepalive_timeout 75s;
上下文: http, server, location
第一個參數設置客戶端的長連接在服務器端保持的最長時間(在此時間客戶端未發起新請求,則長連接關閉)。 第二個參數爲可選項,設置“Keep-Alive: timeout=time”響應頭的值。 可以爲這兩個參數設置不同的值。
“Keep-Alive: timeout=time”響應頭可以被 Mozilla 和 Konqueror 瀏覽器識別和處理。 MSIE 瀏覽器在大約60秒後會關閉長連接。
測試計劃
keepalive_timeout = 1
客戶端持續發起 http 請求,且不主動關閉連接,觀察連接的釋放時間
測試過程
用 JMeter 測試時發現不能維持長連接,在請求結束時都由 JMeter 自己發起連接關閉,按官方 wiki 說明修改 jmeter.properties 和 user.properties 中的相關配置,測試一下沒看到生效,最後還是用 Apache 的 HttpClient 自己寫了點代碼才做了這個測試
代碼中循環啓動多個線程,每個線程啓動後不間斷髮起10次請求,且執行後沒有主動關閉 client 和 response
測試結果
結果說明
如上所述,測試客戶端發起數次請求,請求結束時沒有關閉連接(這裏有個小問題,連接沒有複用,可能是需要配置 client 連接池,我暫時沒去折騰)
1秒(超時)後,由 Nginx 服務器發起關閉請求
1. 和客戶端的長連接請求次數
指令說明
語法: keepalive_requests number默認值: keepalive_requests 100
上下文: http, server, location
這個指令出現在版本 0.8.0
設置通過一個長連接可以處理的最大請求數。 請求數超過此值,長連接將關閉。
測試計劃
keepalive_requests = 5
使用 curl
命令,發送8次(多於 keepalive_requests 個數的)請求,觀察請求5次後連接是否斷開
測試過程
最初使用 for 循環執行 curl
命令,發現命令執行完就立刻釋放了連接,在網上查了下,可以在一個命令裏訪問多次,例如:
curl http://172.16.40.224:6066/NginxTest/hi http://172.16.40.224:6066/NginxTest/hi http://172.16.40.224:6066/NginxTest/hi http://172.16.40.224:6066/NginxTest/hi http://172.16.40.224:6066/NginxTest/hi http://172.16.40.224:6066/NginxTest/hi http://172.16.40.224:6066/NginxTest/hi http://172.16.40.224:6066/NginxTest/hi
這樣的話,就會等8次請求都結束,才關閉連接
測試結果
結果說明
可以看出第一個 TCP 連接共發起了5次 Http 請求,緊接着由 Nginx 發起了關閉
第二個 TCP 連接發起了剩餘的3次 Http 請求,緊接着由客戶端發起了關閉
2. 和後端服務器的長連接個數
指令說明
語法: keepalive connections默認值: —
上下文: upstream
這個指令出現在版本 1.1.4
connections 參數設置每個 worker 進程與後端服務器保持連接的最大數量。這些保持的連接會被放入緩存。 如果連接數大於這個值時,最久未使用的連接會被關閉。
測試計劃
keepalive = 10
用 JMeter 啓動多於 keepalive 個數的測試進程,觀察測試結束後的連接關閉情況
測試過程
使用 JMeter 的 GUI 客戶端編輯一個測試腳本開啓50個進程,循環測試120秒
測試結果
結果說明
可以看出截至118秒(JMeter 逐漸停止發起測試請求),都在逐個關閉 TCP 連接,截圖部分大都是後端服務器響應的 FIN 包,稍微往前一點能看到都是由 Nginx 主動發起的關閉請求
從138秒開始(後端 Tomcat 服務器的長連接超時時間默認20秒),剩餘的10個長連接被後端服務器發起了關閉請求
最後
測試過程涉及到的 tcpdump
命令是
sudo tcpdump -i eth0 host 172.16.40.xxx -w dumplog.pcap
-i 指定網卡
host 指定抓取和哪個 IP 之間的數據包
-w 將抓取結果保存到 pcap 文件,用於使用 Wireshark 查看
通過上面的三個測試,理解和驗證了 Nginx 分別在面向客戶端和麪向後端服務器時的長連接使用情況
打個廣告
文章首發於個人博客《驗證Nginx的長連接(keepalive)配置》