設(shè)置
  • 日夜間
    隨系統(tǒng)
    淺色
    深色
  • 主題色

能 Ping 通,TCP 就一定能連通嗎?

小白debug 2022/9/17 10:56:15 責(zé)編:云熙

平時(shí),我們想要知道,自己的機(jī)器到目的機(jī)器之間,網(wǎng)絡(luò)通不通,一般會(huì)執(zhí)行 Ping 命令。

一般對(duì)于狀況良好的網(wǎng)絡(luò)來(lái)說(shuō),你能看到它對(duì)應(yīng)的 loss 丟包率為 0%,也就是所謂的能 Ping 通。如果看到丟包率 100%,也就是 Ping 不通。

Ping 正常

Ping 不通

那么問(wèn)題來(lái)了,假設(shè)我能 Ping 通某臺(tái)機(jī)器,那這時(shí)候如果我改用 TCP 協(xié)議去發(fā)數(shù)據(jù)到目的機(jī)器,也一定能通嗎?

或者換個(gè)問(wèn)法,Ping 和 tcp 協(xié)議走的網(wǎng)絡(luò)路徑是一樣的嗎?

這時(shí)候第一反應(yīng)就是不一定,因?yàn)?Ping 完之后中間鏈路里的某個(gè)路由器可能會(huì)掛了(斷電了),再用 TCP 去連就會(huì)走別的路徑。

也沒(méi)錯(cuò)。但假設(shè),中間鏈路沒(méi)發(fā)生任何變化呢?

我先直接說(shuō)答案。

不一定,走的網(wǎng)絡(luò)路徑還是有可能是不同的。

今天就來(lái)聊聊為什么。

Ping 和 TCP 發(fā)消息的區(qū)別

我們知道網(wǎng)絡(luò)是分層的,每一層都有對(duì)應(yīng)協(xié)議。

五層網(wǎng)絡(luò)協(xié)議對(duì)應(yīng)的消息體變化分析

而這網(wǎng)絡(luò)層就像搭積木一樣,上層協(xié)議都是基于下層協(xié)議搭出來(lái)的。

不管是 Ping(用了 ICMP 協(xié)議)還是 tcp 本質(zhì)上都是基于網(wǎng)絡(luò)層 IP 協(xié)議的數(shù)據(jù)包,而到了物理層,都是二進(jìn)制 01 串,都走網(wǎng)卡發(fā)出去了。

如果網(wǎng)絡(luò)環(huán)境沒(méi)發(fā)生變化,目的地又一樣,那按道理說(shuō)他們走的網(wǎng)絡(luò)路徑應(yīng)該是一樣的,什么情況下會(huì)不同呢?

我們就從路由這個(gè)話題聊起吧。

網(wǎng)絡(luò)路徑

在我們的想象中,當(dāng)我們想在兩臺(tái)機(jī)器之間傳輸數(shù)據(jù)。本機(jī)和目的機(jī)器之間會(huì)建立一條連接,像一條管道一樣,數(shù)據(jù)從這頭到那頭。這條管道其實(shí)是我們?yōu)榱朔奖憷斫舛橄蟪鰜?lái)的概念。

實(shí)際上,我們將數(shù)據(jù)包從本地網(wǎng)卡發(fā)出之后,會(huì)經(jīng)過(guò)各種路由器(或者交換機(jī)),才能到達(dá)目的機(jī)器。

這些路由器數(shù)量眾多,相互之間可以互連,連起來(lái)之后就像是一張大網(wǎng),所以叫 "網(wǎng)絡(luò)" 可以說(shuō)是非常的形象。

路由器構(gòu)成的網(wǎng)絡(luò)

考慮到交換機(jī)有的功能,路由器基本上都支持,所以我們這邊只討論路由器。

那么現(xiàn)在問(wèn)題來(lái)了,路由器收到數(shù)據(jù)后,怎么知道應(yīng)該走哪條路徑,傳給哪個(gè)路由器?

路徑由什么決定?

在上面的那么大一張網(wǎng)絡(luò)中,隨便一個(gè)路由器都有可能走任何一個(gè)路徑,將數(shù)據(jù)發(fā)到另外一個(gè)路由器上,

但路由和路由之間距離,帶寬啥的可能都不同。

于是就很需要知道,兩點(diǎn)之間走哪條路才是最優(yōu)路徑。

于是問(wèn)題就變成了這樣一個(gè)圖狀結(jié)構(gòu)。每條邊都帶有成本或權(quán)重,算這上面任意兩點(diǎn)的最短距離

路由器和 Dijkstra

這時(shí)候想必大家回憶壓不住要上來(lái)了。

這題我熟,這就是大學(xué)時(shí)候刷的 Dijkstra 算法。菊花廠的 OJ 筆試題集里也經(jīng)常出現(xiàn),現(xiàn)在終于明白為什么他們家的筆試題里圖類題目比別的大廠貌似要多一些了吧,因?yàn)榫栈◤S就是搞通信的,做路由器的老玩家了。

路由表的生成

基于 Dijkstra 算法,封裝出了一個(gè)新的協(xié)議,OSPF 協(xié)議Open Shortest Path First, 開(kāi)放最短路徑優(yōu)先)。

有了 OSPF,路由器就得到了網(wǎng)絡(luò)圖里自己到其他點(diǎn)之間的最短距離,于是就知道了數(shù)據(jù)包要到某個(gè)點(diǎn),該走哪條最優(yōu)路徑

將這些信息匯成一張表,也就是我們常說(shuō)的路由表。

路由表里記錄了到什么 IP 需要走什么端口,以及走這條路徑的成本(metric)。

可以通過(guò) route 命令查看到。

route 表

路由表決定數(shù)據(jù)包路徑

數(shù)據(jù)包在發(fā)送的過(guò)程中,會(huì)在網(wǎng)絡(luò)層加入目標(biāo)地址 IP。

路由器會(huì)根據(jù)這個(gè) IP路由表去做匹配。

然后路由表,會(huì)告訴路由器,什么樣的消息該轉(zhuǎn)發(fā)到什么端口。

舉個(gè)例子。

通過(guò)路由表轉(zhuǎn)發(fā)數(shù)據(jù)

假設(shè) A 要發(fā)消息到 D。也就是 192.168.0.105/24 要發(fā)消息到 192.168.1.11/24。

那么 A 會(huì)把消息經(jīng)發(fā)到路由器。

路由器已知目的地 IP192.168.1.11/24 ,去跟路由表做匹配,發(fā)現(xiàn) 192.168.1.0/24, 就在 e2 端口,那么就會(huì)把消息從 e2 端口發(fā)出,(可能還會(huì)經(jīng)過(guò)交換機(jī))最后把消息打到目的機(jī)器。

當(dāng)然,如果路由表里找不到,那就打到默認(rèn)網(wǎng)關(guān)吧,也就是從 e1 口發(fā)出,發(fā)到 IP192.0.2.1。這個(gè)路由器的路由表不知道該去哪,說(shuō)不定其他路由器知道。

路由表的匹配規(guī)則

上面的例子里,是只匹配上了路由表里的一項(xiàng),所以只能是它了。

但是,條條大路通羅馬。實(shí)際上能到目的地的路徑肯定有很多。

如果路由表里有很多項(xiàng)都被匹配上了,會(huì)怎么選?

如果多個(gè)路由項(xiàng)都能到目的地,那就優(yōu)先選匹配長(zhǎng)度更長(zhǎng)的那個(gè)。比如,還是目的地 192.168.1.11,發(fā)現(xiàn)路由表里的 192.168.1.0/24192.168.0.0/16 都能匹配上,但明顯前者匹配長(zhǎng)度更長(zhǎng),所以最后會(huì)走 192.168.1.0/24 對(duì)應(yīng)的轉(zhuǎn)發(fā)端口。

但如果兩個(gè)表項(xiàng)的匹配長(zhǎng)度都一樣呢?

那就會(huì)看生成這個(gè)路由表項(xiàng)的協(xié)議是啥,選優(yōu)先級(jí)高的,優(yōu)先級(jí)越高也就是所謂的管理距離AD,AdministrativeDistance)越小。比如說(shuō)優(yōu)先選手動(dòng)配的靜態(tài)(static)路由,次優(yōu)選 OSPF 動(dòng)態(tài)學(xué)習(xí)過(guò)來(lái)的表項(xiàng)。

如果還是相同,就看度量值 metrics,其實(shí)也就是路徑成本 cost,成本越小,越容易被選中。

路由器能選的路線有很多,但按道理,最優(yōu)的只有 "一條",所以到這里為止,我們都可以認(rèn)為,對(duì)于同一個(gè)目的地,Ping 和 TCP 走的路徑是相同的。

但是。

如果連路徑成本都一樣呢?也就是說(shuō)有多條最優(yōu)路徑呢。

那就都用。

這也就是所謂的等價(jià)多路徑,ECMPEqual Cost MultiPath)。

我們可以通過(guò) traceroute 看下鏈路是否存在等價(jià)多路徑的情況。

可以看到,中間某幾行,有好幾個(gè) IP,也就是說(shuō)這一跳里同時(shí)可以選好幾個(gè)目的機(jī)器,說(shuō)明這段路徑支持 ECMP。

ECMP 有什么用

利用等價(jià)多路徑,我們可以增加鏈路帶寬。

舉個(gè)例子。

沒(méi)有 ECMP 時(shí)只能選擇某一條路徑

從 A 點(diǎn)到 B 點(diǎn),如果這兩條路徑成本不同,帶寬都是 1 千兆。那數(shù)據(jù)包肯定就選成本低的那條路了,如果這條路出故障了,就走下面那條路。但不管怎么樣,同一時(shí)間,只用到了一條路徑。另外一條閑置就有些浪費(fèi)了,有沒(méi)有辦法可以利用起來(lái)呢?

有,將它們兩條路徑的成本設(shè)置成一樣,那它們就成了等價(jià)路由,然后中間的路由器開(kāi)啟 ECMP 特性,就可以同時(shí)利用這兩條鏈路了。帶寬就從原來(lái)的 1 千兆變成了 2 千兆。數(shù)據(jù)就可以在兩條路徑中隨意選擇了。

利用 ECMP 可以同時(shí)使用兩條鏈路

但這也帶來(lái)了另外一個(gè)問(wèn)題。加劇了數(shù)據(jù)包亂序。

原來(lái)我只使用一條網(wǎng)絡(luò)路徑,數(shù)據(jù)依次發(fā)出,如無(wú)意外,也是依次到達(dá)。

現(xiàn)在兩個(gè)數(shù)據(jù)包走兩條路徑,先發(fā)的數(shù)據(jù)包可能后到。這就亂序了。

那么問(wèn)題又又來(lái)了。

亂序會(huì)有什么問(wèn)題?

對(duì)于我們最最最常使用的 TCP 協(xié)議來(lái)說(shuō),它是個(gè)可靠性網(wǎng)絡(luò)的協(xié)議,這里提到的可靠,不僅是保證數(shù)據(jù)要能送到目的地,還要保證數(shù)據(jù)順序要跟原來(lái)發(fā)送端的一樣。

實(shí)現(xiàn)也很簡(jiǎn)單,TCP 為每個(gè)數(shù)據(jù)包(segment)做上編號(hào)。數(shù)據(jù)到了接收端后,根據(jù)數(shù)據(jù)包編號(hào)發(fā)現(xiàn)是亂序數(shù)據(jù)包,就會(huì)扔到亂序隊(duì)列中對(duì)數(shù)據(jù)包進(jìn)行排序。如果前面的數(shù)據(jù)包還沒(méi)到,哪怕后面的數(shù)據(jù)包先到了,也得在亂序隊(duì)列中一直等,到齊后才能被上層拿到。

舉個(gè)例子,發(fā)送端發(fā)出三個(gè)數(shù)據(jù)包,編號(hào) 1,2,3,假設(shè)在傳輸層 2 和 3 先到了,1 還沒(méi)到。那此時(shí)應(yīng)用層是沒(méi)辦法拿到 2 和 3 的數(shù)據(jù)包的,必須得等 1 來(lái)了之后,應(yīng)用層才能一次性拿到這三個(gè)包。因?yàn)檫@三個(gè)包原來(lái)可能表示的是一個(gè)完整的消息,少了 1, 那么消息就不完整,應(yīng)用層拿到了也毫無(wú)意義。

像這種,由于前面的數(shù)據(jù)丟失導(dǎo)致后面的數(shù)據(jù)沒(méi)辦法及時(shí)給到應(yīng)用層的現(xiàn)象,就是我們常說(shuō)的 TCP 隊(duì)頭阻塞。

亂序隊(duì)列等待數(shù)據(jù)包的到來(lái)

亂序發(fā)生時(shí) 2 和 3 需要待在亂序隊(duì)列中,而亂序隊(duì)列其實(shí)用的也是接收緩沖區(qū)的內(nèi)存,而接收緩沖區(qū)是有大小限制的。通過(guò)下面的命令可以看到接收緩沖區(qū)的大小。

# 查看接收緩沖區(qū)
$ sysctl net.ipv4.tcp_rmem
net.ipv4.tcp_rmem = 4096(min)    87380(default)  6291456(max)
# 緩沖區(qū)會(huì)在min和max之間動(dòng)態(tài)調(diào)整

亂序的情況越多,接收緩沖區(qū)的內(nèi)存就被占用的越多,對(duì)應(yīng)的接收窗口就會(huì)變小,那正常能收的數(shù)據(jù)就變少了,網(wǎng)絡(luò)吞吐就變差了,也就是性能變差了。

因此,我們需要盡量保證所有同一個(gè) TCP 連接下的所有 TCP 包都走相同路徑,這樣才能最大程度避免丟包

ECMP 的路徑選擇策略

當(dāng)初開(kāi)啟 ECMP 就是為了提升性能,現(xiàn)在反而加重了亂序,降低了 TCP 傳輸性能。

這怎么能忍。

為了解決這個(gè)問(wèn)題,我們需要有一個(gè)合理的路徑選擇策略。為了避免同一個(gè)連接里的數(shù)據(jù)包亂序,我們需要保證同一個(gè)連接里的數(shù)據(jù)包,都走同樣的路徑。

這好辦。我們可以通過(guò)連接的五元組(發(fā)送方的 IP端口,接收方的 IP端口,以及通信協(xié)議)信息定位到唯一一條連接。

五元組

然后對(duì)五元組信息生成哈希鍵,讓同一個(gè)哈希鍵的數(shù)據(jù)走同一條路徑,問(wèn)題就完美解決了。

五元組映射成 hash 鍵

根據(jù)五元組選擇 ECMP 路徑

TCP 和 Ping 走的網(wǎng)絡(luò)路徑一樣嗎

現(xiàn)在我們回到文章開(kāi)頭的問(wèn)題。

對(duì)于同樣的發(fā)送端和接收端,TCP 和 Ping 走的網(wǎng)絡(luò)路徑一樣嗎?

不一定一樣,因?yàn)?strong>五元組里的信息里有一項(xiàng)是通信協(xié)議。Ping 用的是 ICMP 協(xié)議,跟 TCP 協(xié)議不同,并且 Ping 不需要用到端口,所以五元組不同,生成的哈希鍵不同,通過(guò) ECMP 選擇到的路徑也可能不同。

TCP 和 Ping 的五元組差異

同樣都用 TCP 協(xié)議,數(shù)據(jù)包走的網(wǎng)絡(luò)路徑一樣嗎

還是同樣的發(fā)送端和接收端,同樣是 TCP 協(xié)議,不同 TCP 連接走的網(wǎng)絡(luò)路徑是一樣的嗎?

跟上面的問(wèn)題一樣,其實(shí)還是五元組的問(wèn)題,同樣都是 TCP 協(xié)議,對(duì)于同樣的發(fā)送端和接收端,他們的 IP 和接收端的端口肯定是一樣的,但發(fā)送方的端口是可以隨時(shí)變化的,因此通過(guò) ECMP 走的路徑也可能不同。

不同 TCP 連接的五元組差異

但問(wèn)題又來(lái)了。

我知道這個(gè)有什么用呢?我做業(yè)務(wù)開(kāi)發(fā),又沒(méi)有設(shè)置網(wǎng)絡(luò)路由的權(quán)限。

利用這個(gè)知識(shí)點(diǎn)排查問(wèn)題

對(duì)于業(yè)務(wù)開(kāi)發(fā),這絕對(duì)不是個(gè)沒(méi)用的知識(shí)點(diǎn)。

如果某天,你發(fā)現(xiàn),你能 Ping 通目的機(jī)器,但用 TCP 去連,卻偶爾連不上目的機(jī)器。而且兩端機(jī)器都挺空閑,沒(méi)什么性能上的瓶頸。實(shí)在走投無(wú)路了。

你就可以想想,會(huì)不會(huì)是網(wǎng)絡(luò)中用到了 ECMP,其中一條鏈路有問(wèn)題導(dǎo)致的。

Ping 能成功但部分 TCP 連接失敗

排查方法也很簡(jiǎn)單。

你是知道本機(jī)的 IP 以及目的機(jī)器的 IP 和端口號(hào)的,也知道自己用的是 TCP 連接。

只要你在報(bào)錯(cuò)的時(shí)候打印下錯(cuò)誤信息,你就知道了發(fā)送端的端口號(hào)了。

這樣五元組是啥你就知道了。

下一步就是指定發(fā)送端的端口號(hào)重新發(fā)起 TCP 請(qǐng)求,同樣的五元組,走同樣的路徑,按理說(shuō)如果鏈路有問(wèn)題,就肯定會(huì)復(fù)現(xiàn)。

如果不想改自己的代碼,你可以用 nc 命令指定客戶端端口看下能不能正常建立 TCP 連接。

nc -p 6666 baidu.com 80

-p 6666 是指定發(fā)出請(qǐng)求的客戶端端口是 6666,后面跟著的是連接的域名80 端口

通過(guò) nc 成功建立 tcp 連接

假設(shè)用了 6666 端口的五元組去連接總是失敗,改用 6667 或其他端口卻能成功,你可以帶著這個(gè)信息去找找負(fù)責(zé)網(wǎng)絡(luò)的同事。

總結(jié)

路由器可以通過(guò) OSPF 協(xié)議生成路由表,利用數(shù)據(jù)包里的 IP 地址去跟路由表做匹配,選擇最優(yōu)路徑后進(jìn)行轉(zhuǎn)發(fā)。

當(dāng)路由表一個(gè)都匹配不上時(shí)會(huì)走默認(rèn)網(wǎng)關(guān)。當(dāng)匹配上多個(gè)的時(shí)候,會(huì)先看匹配長(zhǎng)度,如果一樣就看管理距離,還一樣就看路徑成本。如果連路徑成本都一樣,那等價(jià)路徑。如果路由開(kāi)啟了 ECMP,那就可以同時(shí)利用這幾條路徑做傳輸。

ECMP 可以提高鏈路帶寬,同時(shí)利用五元組做哈希鍵進(jìn)行路徑選擇,保證了同一條連接的數(shù)據(jù)包走同一條路徑,減少了亂序的情況。

可以通過(guò) traceroute 命令查看到鏈路上是否有用到 ECMP 的情況。

開(kāi)啟了 ECMP 的網(wǎng)絡(luò)鏈路中,TCP 和 Ping 命令可能走的路徑不同,甚至同樣是 TCP,不同連接之間,走的路徑也不同,因此出現(xiàn)了連接時(shí)好時(shí)壞的問(wèn)題,實(shí)在是走投無(wú)路了,可以考慮下是不是跟 ECMP 有關(guān)。

當(dāng)然,遇到問(wèn)題多懷疑自己,要相信絕大部分時(shí)候真的跟 ECMP 無(wú)關(guān)

參考資料

《網(wǎng)絡(luò)排查案例課》 —— 極客時(shí)間

本文來(lái)自微信公眾號(hào):小白 debug (ID:xiaobaidebug),作者:小白

廣告聲明:文內(nèi)含有的對(duì)外跳轉(zhuǎn)鏈接(包括不限于超鏈接、二維碼、口令等形式),用于傳遞更多信息,節(jié)省甄選時(shí)間,結(jié)果僅供參考,IT之家所有文章均包含本聲明。

軟媒旗下網(wǎng)站: IT之家 最會(huì)買 - 返利返現(xiàn)優(yōu)惠券 iPhone之家 Win7之家 Win10之家 Win11之家

軟媒旗下軟件: 軟媒手機(jī)APP應(yīng)用 魔方 最會(huì)買 要知