Linux 網(wǎng)絡(luò)訪問慢?使用這個方法快速定位
在 Linux 服務(wù)器中,可以通過內(nèi)核調(diào)優(yōu)、DPDK 以及 XDP 等多種方式提高服務(wù)器的抗攻擊能力,降低 DDoS 對正常服務(wù)的影響。在應(yīng)用程序中,可以使用各級緩存、WAF、CDN 等來緩解 DDoS 對應(yīng)用程序的影響。
但是需要注意的是,如果 DDoS 流量已經(jīng)到達(dá) Linux 服務(wù)器,那么即使應(yīng)用層做了各種優(yōu)化,網(wǎng)絡(luò)服務(wù)延遲一般也會比平時大很多。
因此,在實(shí)際應(yīng)用中,我們通常使用 Linux 服務(wù)器,配合專業(yè)的流量清洗和網(wǎng)絡(luò)防火墻設(shè)備,來緩解這個問題。
除了 DDoS 導(dǎo)致的網(wǎng)絡(luò)延遲增加,我想你一定見過很多其他原因?qū)е碌木W(wǎng)絡(luò)延遲,例如:
- 網(wǎng)絡(luò)傳輸慢導(dǎo)致的延遲。
- Linux 內(nèi)核協(xié)議棧數(shù)據(jù)包處理速度慢導(dǎo)致的延遲。
- 應(yīng)用程序數(shù)據(jù)處理速度慢造成的延遲等。
那么當(dāng)我們遇到這些原因造成的延誤時,我們該怎么辦呢?如何定位網(wǎng)絡(luò)延遲的根本原因?讓我們在本文中討論網(wǎng)絡(luò)延遲。
Linux 網(wǎng)絡(luò)延遲
談到網(wǎng)絡(luò)延遲(Network Latency),人們通常認(rèn)為它是指網(wǎng)絡(luò)數(shù)據(jù)傳輸所需的時間。但是,這里的“時間”是指雙向流量,即數(shù)據(jù)從源發(fā)送到目的地,然后從目的地地址返回響應(yīng)的往返時間:RTT(Round-Trip Time)。
除了網(wǎng)絡(luò)延遲之外,另一個常用的指標(biāo)是應(yīng)用延遲(Application Latency),它是指應(yīng)用接收請求并返回響應(yīng)所需的時間。通常,應(yīng)用延遲也稱為往返延遲,它是網(wǎng)絡(luò)數(shù)據(jù)傳輸時間加上數(shù)據(jù)處理時間的總和。
?通常人們使用 ping 命令來測試網(wǎng)絡(luò)延遲,ping 是基于 ICMP 協(xié)議的,它通過計算 ICMP 發(fā)出的響應(yīng)報文和 ICMP 發(fā)出的請求報文之間的時間差來獲得往返延遲時間。這個過程不需要特殊的認(rèn)證,從而經(jīng)常被很多網(wǎng)絡(luò)攻擊所利用,如,端口掃描工具 nmap、分組工具 hping3 等。
因此,為了避免這些問題,很多網(wǎng)絡(luò)服務(wù)都會禁用 ICMP,這使得我們無法使用 pi?ng 來測試網(wǎng)絡(luò)服務(wù)的可用性和往返延遲。在這種情況下,您可以使用 traceroute 或 hping3 的 TCP 和 UDP 模式來獲取網(wǎng)絡(luò)延遲。
例如:
當(dāng)然,你也可以使用 traceroute:
traceroute 會在路由的每一跳(hop)發(fā)送三個數(shù)據(jù)包,并在收到響應(yīng)后輸出往返延遲。如果沒有響應(yīng)或響應(yīng)超時(默認(rèn) 5s),將輸出一個星號 *。
案例展示
我們需要在此演示中托管 host1 和 host2 兩個主機(jī):
- host1 (192.168.0.30):托管兩個 Nginx Web 應(yīng)用程序(正常和延遲)
- host2 (192.168.0.2):分析主機(jī)
host1 準(zhǔn)備
在 host1 上,讓我們運(yùn)行啟動兩個容器,它們分別是官方 Nginx 和具有延遲版本的 Nginx:
運(yùn)行以下命令以驗證兩個容器都在為流量提供服務(wù):
host2 準(zhǔn)備
現(xiàn)在讓我們用上面提到的 hping3 來測試它們的延遲,看看有什么區(qū)別。在 host2 中,執(zhí)行以下命令分別測試案例機(jī)的 8080 端口和 80 端口的延遲:
80 端口:
8080 端口:
從這個輸出中您可以看到兩個端口的延遲大致相同,均為 7 毫秒。但這僅適用于單個請求。如果換成并發(fā)請求怎么辦?接下來,讓我們用 wrk (https://github.com/wg/wrk) 試試。
80 端口:
8080 端口:
從以上兩個輸出可以看出,官方 Nginx(監(jiān)聽 80 端口)的平均延遲為 9.19ms,而案例 Nginx(監(jiān)聽 8080 端口)的平均延遲為 43.6ms。從延遲分布上來看,官方 Nginx 可以在 9ms 內(nèi)完成 90% 的請求;對于案例 Nginx,50% 的請求已經(jīng)達(dá)到 44ms。
那么這里發(fā)生了什么呢?我們來做一些分析:
在 host1 中,讓我們使用 tcpdump 捕獲一些網(wǎng)絡(luò)數(shù)據(jù)包:
現(xiàn)在,在 host2 上重新運(yùn)行 wrk 命令
當(dāng) wrk 命令完成后,再次切換回 Terminal 1(host1 的終端)并按 Ctrl+C 結(jié)束 tcpdump 命令。然后,用 Wireshark 把抓到的 nginx.pcap 復(fù)制到本機(jī)(如果 VM1(host1 的虛擬機(jī))已經(jīng)有圖形界面,可以跳過復(fù)制步驟),用 Wireshark 打開。
由于網(wǎng)絡(luò)包的數(shù)量很多,我們可以先過濾一下。例如,選中一個包后,可以右鍵選擇 “Follow”->“TCP Stream”,如下圖:
然后,關(guān)閉彈出的對話框并返回 Wireshark 主窗口。這時你會發(fā)現(xiàn) Wireshark 已經(jīng)自動為你設(shè)置了一個過濾表達(dá)式 tcp.stream eq 24。如下圖所示(圖中省略了源 IP 和目的 IP):
從這里,您可以看到從三次握手開始,此 TCP 連接的每個請求和響應(yīng)。當(dāng)然,這可能不夠直觀,可以繼續(xù)點(diǎn)擊菜單欄中的 Statistics -> Flow Graph,選擇 “Limit to display filter”,將 Flow type 設(shè)置為 “TCP Flows”:
請注意,此圖的左側(cè)是客戶端,而右側(cè)是 Nginx 服務(wù)器。從這個圖中可以看出,前三次握手和第一次 HTTP 請求和響應(yīng)都相當(dāng)快,但是第二次 HTTP 請求就比較慢了,尤其是客戶端收到服務(wù)器的第一個數(shù)據(jù)包后,該 ACK 響應(yīng)(圖中的藍(lán)線)在 40ms 后才被發(fā)送。
?看到 40ms 的值,你有沒有想到什么?事實(shí)上,這是 TCP 延遲 ACK 的最小超時。這是 TCP ACK 的一種優(yōu)化機(jī)制,即不是每次請求都發(fā)送一個 ACK,而是等待一段時間(比如 40ms),看看有沒有“搭車”的數(shù)據(jù)包。如果在此期間還有其他數(shù)據(jù)包需要發(fā)送,它們將與 ACK 一起被發(fā)送。當(dāng)然,如果等不及其他數(shù)據(jù)包,超時后會單獨(dú)發(fā)送 ACK。
由于案例中的客戶端發(fā)生了 40ms 延遲,我們有理由懷疑客戶端開啟了延遲確認(rèn)機(jī)制(Delayed Acknowledgment Mechanism)。這里的客戶端其實(shí)就是之前運(yùn)行的 wrk。
根據(jù) TCP 文檔,只有在 TCP 套接字專門設(shè)置了 TCP_QUICKACK 時才會啟用快速確認(rèn)模式(Fast Acknowledgment Mode);否則,默認(rèn)使用延遲確認(rèn)機(jī)制:?
讓我們測試一下我們的質(zhì)疑:
可以看到 wrk 只設(shè)置了 TCP_NODELAY 選項,沒有設(shè)置 TCP_QUICKACK?,F(xiàn)在您可以看到為什么延遲 Nginx(案例 Nginx)響應(yīng)會出現(xiàn)一個延遲。
結(jié)論
在本文中,我將向您展示如何分析增加的網(wǎng)絡(luò)延遲。網(wǎng)絡(luò)延遲是核心網(wǎng)絡(luò)性能指標(biāo)。由于網(wǎng)絡(luò)傳輸、網(wǎng)絡(luò)報文處理等多種因素的影響,網(wǎng)絡(luò)延遲是不可避免的。但過多的網(wǎng)絡(luò)延遲會直接影響用戶體驗。
- 使用 hping3 和 wrk 等工具確認(rèn)單個請求和并發(fā)請求的網(wǎng)絡(luò)延遲是否正常。
- 使用 traceroute,確認(rèn)路由正確,并查看路由中每個網(wǎng)關(guān)跳躍點(diǎn)的延遲。
- 使用 tcpdump 和 Wireshark 確認(rèn)網(wǎng)絡(luò)數(shù)據(jù)包是否正常收發(fā)。
- 使用 strace 等觀察應(yīng)用程序?qū)W(wǎng)絡(luò) socket 的調(diào)用是否正常。