開發或者測試互聯網產品的過程中,同學們一定遇到過connection timed out 和 socket read timed out兩種和網絡相關的異常。今天我們并不分析引起這些異常的原因,也不談發生異常以后的解決辦法,我們來說說如何制造這類異常,從而模擬對應的異常場景。
了解tcp協議就知道connection即建立連接的過程,其實和socket read即傳輸數據的過程并沒有太大的差別,兩者都是請求應答模式,而只是前者的請求數據量很小而已。要使兩者超時,我們可以采用相同的方法即限制網絡傳輸的帶寬來達到目的。
Tc即traffic control就是這樣一款能夠限制網絡流量的工具。Tc中主要的概念包括類class和過濾器filter。
我們可以用class把網絡設備的帶寬劃分成不同的區間:
tc class add dev $DEV parent 1:classid 1:11 htb rate 90mbps ceil 100mbps
tc class add dev $DEV parent 1:classid 1:12 htb rate 90bps ceil 100bps
如上,11這個class對應的帶寬 為 90到 100mbps,12這個 class對應的帶寬只有90到100bps。劃分好了class,我們就可以用filter把符合特定條件的數據包歸入不同的class中
tc filter add dev $DEV protocol ip parent1:0 prio 1 u32 match ip sport $PORT 0xffff match ip dst $IP flowid 1:12
如上就把源端口是$PORT,目的地址是$IP的數據包歸入12這個class中了,這樣就把符合該條件的數據流量限制到了90到100bps。在正在運行的系統中開啟上述tc限制,即把特定數據流限制到一個極小值,我們就能模擬出connection timed out異常了。
那么socket read timed out異常又該如何模擬呢,我們怎么才能區分建立連接和數據傳輸這2個過程,tc工具還能滿足我們的需求嗎?在尋找問題答案的過程中,另一個linux內核組件iptables進入了我們的視野。
Iptables是linux系統中常用的防火墻組件,功能十分強大,網上有十分豐富的資料。由于其能夠識別數據包中的syn、ack等標志位,故能把建立連接和后續的數據傳輸過程區分開來。
iptables-A INPUT-p tcp--src $IP--dport $PORT !--syn-jDROP
如上,在目的機器上加入該條iptables規則,可以實現將未設置syn標志位的數據包丟棄的功能,這樣連接能夠建立完成但后續的數據傳輸將無響應。
另外,Iptables具有一種連接跟蹤機制,即能夠記錄連接的狀態。這些狀態分別是 NEW、ESTABLISHED、RELATED 和INVALID。我們可以利用該特性實現相同的效果。
iptables-A INPUT-p tcp-m state--state ESTABLISHED-s $IP--dport $PORT-jDROP
如上,在目的機器上加入該條iptables規則,當匹配了ip和端口,并且數據包所對應的連接狀態是ESTABLISHED 時將其丟棄。
至此read timed out異常也能輕松模擬了。Tc和Iptables是linux網絡模塊中強有力的工具,除了能夠利用它們開發功能,也能夠在網絡異常測試中發揮關鍵的作用。