
能Ping通 TCP就一定能連通嗎?
平時,我們想要知道,自己的機器到目的機器之間,網(wǎng)絡(luò)通不通,一般會執(zhí)行?Ping 命令。
一般對于狀況良好的網(wǎng)絡(luò)來說,你能看到它對應(yīng)的 loss 丟包率為 0%,也就是所謂的能 Ping 通。如果看到丟包率 100%,也就是?Ping 不通。
Ping 正常
Ping 不通
那么問題來了,假設(shè)我能?Ping?通某臺機器,那這時候如果我改用?TCP 協(xié)議去發(fā)數(shù)據(jù)到目的機器,也一定能通嗎?
或者換個問法,Ping 和 tcp 協(xié)議走的網(wǎng)絡(luò)路徑是一樣的嗎?
這時候第一反應(yīng)就是不一定,因為 Ping 完之后中間鏈路里的某個路由器可能會掛了(斷電了),再用 TCP 去連就會走別的路徑。
也沒錯。但假設(shè),中間鏈路沒發(fā)生任何變化呢?
我先直接說答案。
不一定,走的網(wǎng)絡(luò)路徑還是有可能是不同的。
今天就來聊聊為什么。
Ping 和 TCP 發(fā)消息的區(qū)別
我們知道網(wǎng)絡(luò)是分層的,每一層都有對應(yīng)協(xié)議。
五層網(wǎng)絡(luò)協(xié)議對應(yīng)的消息體變化分析
而這網(wǎng)絡(luò)層就像搭積木一樣,上層協(xié)議都是基于下層協(xié)議搭出來的。
不管是 Ping(用了 ICMP 協(xié)議)還是 tcp 本質(zhì)上都是基于網(wǎng)絡(luò)層 IP 協(xié)議的數(shù)據(jù)包,而到了物理層,都是二進制 01 串,都走網(wǎng)卡發(fā)出去了。
如果網(wǎng)絡(luò)環(huán)境沒發(fā)生變化,目的地又一樣,那按道理說他們走的網(wǎng)絡(luò)路徑應(yīng)該是一樣的,什么情況下會不同呢?
我們就從路由這個話題聊起吧。
網(wǎng)絡(luò)路徑
在我們的想象中,當(dāng)我們想在兩臺機器之間傳輸數(shù)據(jù)。本機和目的機器之間會建立一條連接,像一條管道一樣,數(shù)據(jù)從這頭到那頭。這條管道其實是我們?yōu)榱朔奖憷斫舛橄蟪鰜淼母拍睢?/p>
實際上,我們將數(shù)據(jù)包從本地網(wǎng)卡發(fā)出之后,會經(jīng)過各種路由器(或者交換機),才能到達目的機器。
這些路由器數(shù)量眾多,相互之間可以互連,連起來之后就像是一張大網(wǎng),所以叫?"網(wǎng)絡(luò)"?可以說是非常的形象。
路由器構(gòu)成的網(wǎng)絡(luò)
考慮到交換機有的功能,路由器基本上都支持,所以我們這邊只討論路由器。
那么現(xiàn)在問題來了,路由器收到數(shù)據(jù)后,怎么知道應(yīng)該走哪條路徑,傳給哪個路由器?
路徑由什么決定?
在上面的那么大一張網(wǎng)絡(luò)中,隨便一個路由器都有可能走任何一個路徑,將數(shù)據(jù)發(fā)到另外一個路由器上,
但路由和路由之間距離,帶寬啥的可能都不同。
于是就很需要知道,兩點之間走哪條路才是最優(yōu)路徑。
于是問題就變成了這樣一個圖狀結(jié)構(gòu)。每條邊都帶有成本或權(quán)重,算這上面任意兩點的最短距離。
路由器和 Dijkstra
這時候想必大家回憶壓不住要上來了。
這題我熟,這就是大學(xué)時候刷的?Dijkstra 算法。菊花廠的 OJ 筆試題集里也經(jīng)常出現(xiàn),現(xiàn)在終于明白為什么他們家的筆試題里圖類題目比別的大廠貌似要多一些了吧,因為菊花廠就是搞通信的,做路由器的老玩家了。
路由表的生成
基于?Dijkstra 算法,封裝出了一個新的協(xié)議,OSPF 協(xié)議(Open?Shortest?Path?First, 開放最短路徑優(yōu)先)。
有了 OSPF,路由器就得到了網(wǎng)絡(luò)圖里自己到其他點之間的最短距離,于是就知道了數(shù)據(jù)包要到某個點,該走哪條最優(yōu)路徑。
將這些信息匯成一張表,也就是我們常說的路由表。
路由表里記錄了到什么 IP 需要走什么端口,以及走這條路徑的成本(metric)。
可以通過 route 命令查看到。
route 表
路由表決定數(shù)據(jù)包路徑
數(shù)據(jù)包在發(fā)送的過程中,會在網(wǎng)絡(luò)層加入目標(biāo)地址 IP。
路由器會根據(jù)這個?IP?跟路由表去做匹配。
然后路由表,會告訴路由器,什么樣的消息該轉(zhuǎn)發(fā)到什么端口。
舉個例子。
通過路由表轉(zhuǎn)發(fā)數(shù)據(jù)
假設(shè) A 要發(fā)消息到 D。也就是 192.168.0.105/24 要發(fā)消息到 192.168.1.11/24。
那么 A 會把消息經(jīng)發(fā)到路由器。
路由器已知目的地 IP192.168.1.11/24 ,去跟路由表做匹配,發(fā)現(xiàn) 192.168.1.0/24, 就在 e2 端口,那么就會把消息從 e2 端口發(fā)出,(可能還會經(jīng)過交換機)最后把消息打到目的機器。
當(dāng)然,如果路由表里找不到,那就打到默認網(wǎng)關(guān)吧,也就是從 e1 口發(fā)出,發(fā)到 IP192.0.2.1。這個路由器的路由表不知道該去哪,說不定其他路由器知道。
路由表的匹配規(guī)則
上面的例子里,是只匹配上了路由表里的一項,所以只能是它了。
但是,條條大路通羅馬。實際上能到目的地的路徑肯定有很多。
如果路由表里有很多項都被匹配上了,會怎么選?
如果多個路由項都能到目的地,那就優(yōu)先選匹配長度更長的那個。比如,還是目的地 192.168.1.11,發(fā)現(xiàn)路由表里的?192.168.1.0/24?和?192.168.0.0/16?都能匹配上,但明顯前者匹配長度更長,所以最后會走?192.168.1.0/24?對應(yīng)的轉(zhuǎn)發(fā)端口。
但如果兩個表項的匹配長度都一樣呢?
那就會看生成這個路由表項的協(xié)議是啥,選優(yōu)先級高的,優(yōu)先級越高也就是所謂的管理距離(AD,AdministrativeDistance)越小。比如說優(yōu)先選手動配的靜態(tài)(static)路由,次優(yōu)選?OSPF?動態(tài)學(xué)習(xí)過來的表項。
如果還是相同,就看度量值 metrics,其實也就是路徑成本 cost,成本越小,越容易被選中。
路由器能選的路線有很多,但按道理,最優(yōu)的只有 "一條",所以到這里為止,我們都可以認為,對于同一個目的地,Ping 和 TCP 走的路徑是相同的。
但是。
如果連路徑成本都一樣呢?也就是說有多條最優(yōu)路徑呢。
那就都用。
這也就是所謂的等價多路徑,ECMP(Equal?Cost?MultiPath)。
我們可以通過 traceroute 看下鏈路是否存在等價多路徑的情況。
可以看到,中間某幾行,有好幾個 IP,也就是說這一跳里同時可以選好幾個目的機器,說明這段路徑支持 ECMP。
ECMP 有什么用
利用等價多路徑,我們可以增加鏈路帶寬。
舉個例子。
沒有 ECMP 時只能選擇某一條路徑
從 A 點到 B 點,如果這兩條路徑成本不同,帶寬都是 1 千兆。那數(shù)據(jù)包肯定就選成本低的那條路了,如果這條路出故障了,就走下面那條路。但不管怎么樣,同一時間,只用到了一條路徑。另外一條閑置就有些浪費了,有沒有辦法可以利用起來呢?
有,將它們兩條路徑的成本設(shè)置成一樣,那它們就成了等價路由,然后中間的路由器開啟?ECMP?特性,就可以同時利用這兩條鏈路了。帶寬就從原來的 1 千兆變成了 2 千兆。數(shù)據(jù)就可以在兩條路徑中隨意選擇了。
利用 ECMP 可以同時使用兩條鏈路
但這也帶來了另外一個問題。加劇了數(shù)據(jù)包亂序。
原來我只使用一條網(wǎng)絡(luò)路徑,數(shù)據(jù)依次發(fā)出,如無意外,也是依次到達。
現(xiàn)在兩個數(shù)據(jù)包走兩條路徑,先發(fā)的數(shù)據(jù)包可能后到。這就亂序了。
那么問題又又來了。
亂序會有什么問題?
對于我們最最最常使用的 TCP 協(xié)議來說,它是個可靠性網(wǎng)絡(luò)的協(xié)議,這里提到的可靠,不僅是保證數(shù)據(jù)要能送到目的地,還要保證數(shù)據(jù)順序要跟原來發(fā)送端的一樣。
實現(xiàn)也很簡單,TCP 為每個數(shù)據(jù)包(segment)做上編號。數(shù)據(jù)到了接收端后,根據(jù)數(shù)據(jù)包編號發(fā)現(xiàn)是亂序數(shù)據(jù)包,就會扔到亂序隊列中對數(shù)據(jù)包進行排序。如果前面的數(shù)據(jù)包還沒到,哪怕后面的數(shù)據(jù)包先到了,也得在亂序隊列中一直等,到齊后才能被上層拿到。
舉個例子,發(fā)送端發(fā)出三個數(shù)據(jù)包,編號 1,2,3,假設(shè)在傳輸層?2 和 3 先到了,1 還沒到。那此時應(yīng)用層是沒辦法拿到 2 和 3 的數(shù)據(jù)包的,必須得等 1 來了之后,應(yīng)用層才能一次性拿到這三個包。因為這三個包原來可能表示的是一個完整的消息,少了 1, 那么消息就不完整,應(yīng)用層拿到了也毫無意義。
像這種,由于前面的數(shù)據(jù)丟失導(dǎo)致后面的數(shù)據(jù)沒辦法及時給到應(yīng)用層的現(xiàn)象,就是我們常說的?TCP 隊頭阻塞。
亂序隊列等待數(shù)據(jù)包的到來
亂序發(fā)生時 2 和 3 需要待在亂序隊列中,而亂序隊列其實用的也是接收緩沖區(qū)的內(nèi)存,而接收緩沖區(qū)是有大小限制的。通過下面的命令可以看到接收緩沖區(qū)的大小。
#?查看接收緩沖區(qū)$?sysctl?net.ipv4.tcp_rmemnet.ipv4.tcp_rmem?=?4096(min)????87380(default)??6291456(max)#?緩沖區(qū)會在min和max之間動態(tài)調(diào)整
亂序的情況越多,接收緩沖區(qū)的內(nèi)存就被占用的越多,對應(yīng)的接收窗口就會變小,那正常能收的數(shù)據(jù)就變少了,網(wǎng)絡(luò)吞吐就變差了,也就是性能變差了。
因此,我們需要盡量保證所有同一個 TCP 連接下的所有 TCP 包都走相同路徑,這樣才能最大程度避免丟包。
ECMP 的路徑選擇策略
當(dāng)初開啟 ECMP 就是為了提升性能,現(xiàn)在反而加重了亂序,降低了 TCP 傳輸性能。
這怎么能忍。
為了解決這個問題,我們需要有一個合理的路徑選擇策略。為了避免同一個連接里的數(shù)據(jù)包亂序,我們需要保證同一個連接里的數(shù)據(jù)包,都走同樣的路徑。
這好辦。我們可以通過連接的五元組(發(fā)送方的?IP?和端口,接收方的?IP?和端口,以及通信協(xié)議)信息定位到唯一一條連接。
五元組
然后對五元組信息生成哈希鍵,讓同一個哈希鍵的數(shù)據(jù)走同一條路徑,問題就完美解決了。
五元組映射成 hash 鍵
根據(jù)五元組選擇 ECMP 路徑
TCP 和 Ping 走的網(wǎng)絡(luò)路徑一樣嗎
現(xiàn)在我們回到文章開頭的問題。
對于同樣的發(fā)送端和接收端,TCP 和 Ping 走的網(wǎng)絡(luò)路徑一樣嗎?
不一定一樣,因為五元組里的信息里有一項是通信協(xié)議。Ping 用的是?ICMP 協(xié)議,跟?TCP 協(xié)議不同,并且 Ping 不需要用到端口,所以五元組不同,生成的哈希鍵不同,通過 ECMP 選擇到的路徑也可能不同。
TCP 和 Ping 的五元組差異
同樣都用 TCP 協(xié)議,數(shù)據(jù)包走的網(wǎng)絡(luò)路徑一樣嗎
還是同樣的發(fā)送端和接收端,同樣是 TCP 協(xié)議,不同 TCP 連接走的網(wǎng)絡(luò)路徑是一樣的嗎?
跟上面的問題一樣,其實還是五元組的問題,同樣都是 TCP 協(xié)議,對于同樣的發(fā)送端和接收端,他們的 IP 和接收端的端口肯定是一樣的,但發(fā)送方的端口是可以隨時變化的,因此通過 ECMP 走的路徑也可能不同。
不同 TCP 連接的五元組差異
但問題又來了。
我知道這個有什么用呢?我做業(yè)務(wù)開發(fā),又沒有設(shè)置網(wǎng)絡(luò)路由的權(quán)限。
利用這個知識點排查問題
對于業(yè)務(wù)開發(fā),這絕對不是個沒用的知識點。
如果某天,你發(fā)現(xiàn),你能 Ping 通目的機器,但用 TCP 去連,卻偶爾連不上目的機器。而且兩端機器都挺空閑,沒什么性能上的瓶頸。實在走投無路了。
你就可以想想,會不會是網(wǎng)絡(luò)中用到了 ECMP,其中一條鏈路有問題導(dǎo)致的。
Ping 能成功但部分 TCP 連接失敗
排查方法也很簡單。
你是知道本機的 IP 以及目的機器的 IP 和端口號的,也知道自己用的是 TCP 連接。
只要你在報錯的時候打印下錯誤信息,你就知道了發(fā)送端的端口號了。
這樣五元組是啥你就知道了。
下一步就是指定發(fā)送端的端口號重新發(fā)起 TCP 請求,同樣的五元組,走同樣的路徑,按理說如果鏈路有問題,就肯定會復(fù)現(xiàn)。
如果不想改自己的代碼,你可以用?nc 命令指定客戶端端口看下能不能正常建立 TCP 連接。
nc?-p?6666?baidu.com?80
-p 6666 是指定發(fā)出請求的客戶端端口是 6666,后面跟著的是連接的域名和?80 端口。
通過 nc 成功建立 tcp 連接
假設(shè)用了 6666 端口的五元組去連接總是失敗,改用 6667 或其他端口卻能成功,你可以帶著這個信息去找找負責(zé)網(wǎng)絡(luò)的同事。
總結(jié)
路由器可以通過 OSPF 協(xié)議生成路由表,利用數(shù)據(jù)包里的 IP 地址去跟路由表做匹配,選擇最優(yōu)路徑后進行轉(zhuǎn)發(fā)。
當(dāng)路由表一個都匹配不上時會走默認網(wǎng)關(guān)。當(dāng)匹配上多個的時候,會先看匹配長度,如果一樣就看管理距離,還一樣就看路徑成本。如果連路徑成本都一樣,那等價路徑。如果路由開啟了 ECMP,那就可以同時利用這幾條路徑做傳輸。
ECMP 可以提高鏈路帶寬,同時利用五元組做哈希鍵進行路徑選擇,保證了同一條連接的數(shù)據(jù)包走同一條路徑,減少了亂序的情況。
可以通過 traceroute 命令查看到鏈路上是否有用到 ECMP 的情況。
開啟了 ECMP 的網(wǎng)絡(luò)鏈路中,TCP 和 Ping 命令可能走的路徑不同,甚至同樣是 TCP,不同連接之間,走的路徑也不同,因此出現(xiàn)了連接時好時壞的問題,實在是走投無路了,可以考慮下是不是跟 ECMP 有關(guān)。
當(dāng)然,遇到問題多懷疑自己,要相信絕大部分時候真的跟 ECMP 無關(guān)。
參考資料
《網(wǎng)絡(luò)排查案例課》 —— 極客時間
本文來自微信公眾號:小白 debug?(ID:xiaobaidebug),作者:小白
[超站]友情鏈接:
四季很好,只要有你,文娛排行榜:https://www.yaopaiming.com/
關(guān)注數(shù)據(jù)與安全,洞悉企業(yè)級服務(wù)市場:https://www.ijiandao.com/

隨時掌握互聯(lián)網(wǎng)精彩
- 1 這一天致青年 我們?nèi)绾钨s續(xù)與傳承 7903995
- 2 “第一天出去旅游的人已老實” 7809182
- 3 男子送老人過馬路 3次敬禮全網(wǎng)刷屏 7713223
- 4 中國假期吸引世界流量 7616680
- 5 張嘉益《人民日報》撰文 7522029
- 6 90后美女副教授走紅 北航回應(yīng) 7428859
- 7 網(wǎng)警提醒:國慶歡樂游 安全別松懈 7330524
- 8 走失小狗在服務(wù)區(qū)苦等主人8小時 7233792
- 9 “課本上的傳奇”珍·古道爾逝世 7143036
- 10 多省發(fā)文補貼社保個人繳費額的25% 7043109