天天看點

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,回車後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

阿裡妹導讀:本文是一個理論過度到實踐的典型案例,借助程式員經常遇到的一個問題——網絡為什麼不通,來具體說明怎麼将書本上的死知識真正變成我們解決問題的能力。

大學學到的基本概念

我相信你腦子裡關于網絡基礎知識的概念都在下面這張圖中。知識内容有點亂,感覺都認識,又都模模糊糊,更談不上将内容轉化成生産力或是用來解決實際問題了。這是因為知識沒有貫通、沒有實踐、沒有組織。

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

上圖中知識點的作用在RFC1180[1]中講得無比通俗易懂了。看第一遍的時候也許你就看懂了,但是一個月後又忘記了。其實這些東西我們在大學也學過,但還是忘了(能夠了解,缺少實操環境和條件),或者碰到問題才發現之前看懂了的東西其實沒懂。

是以接下來我們将示範書本知識到實踐的貫通過程,希望把網絡概念之間的聯系通過實踐來組織起來。

還是從一個問題入手

最近的環境碰到一個網絡ping不通的問題,當時的網絡鍊路是(大概是這樣,略有簡化):

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

現象

  • 從容器1 ping 實體機2 不通;
  • 從實體機1上的 容器2 ping實體機2 通;
  • 同時發現即使是通的,有的容器 ping實體機1隻需要0.1ms,有的容器需要200ms以上(都在同一個實體機上),不合理;
  • 所有容器 ping 其它外網IP(比如百度)反而是通的。

這個問題扯了一周才解決是因為容器的網絡是我們自己配置的,交換機我們沒有權限接觸,由客戶配置。出問題的時候都會覺得自己沒問題對方有問題,另外就是對網絡基本知識認識不夠,是以都覺得自己沒問題而不去找證據。

這個問題的答案在大家看完本文的基礎知識後會總結出來。

解決這個問題前大家先想想,假如有個面試題是:輸入 ping IP 後敲回車,然後發生了什麼?

複習一下大學課本中的知識點

要解決一個問題你首先要有基礎知識,在知識欠缺的情況下就算邏輯再好、思路再清晰、智商再高,也不一定有效。

route 路由表

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

假如你在這台機器上ping 172.17.0.2 ,根據上面的route表得出 172.17.0.2這個IP符合下面這條路由:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

這條路由規則,那麼ping 包會從docker0這張網卡發出去。

但是如果是ping 1.1.4.4 根據路由規則就應該走eth0這張網卡而不是docker0了。接下來就要判斷目标IP是否在同一個子網了。

ifconfig

首先來看看這台機器的網卡情況:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

這裡有三個網卡和三個IP,三個子網路遮罩(netmask)。根據目标路由走哪張網卡,得到這個網卡的子網路遮罩,來計算目标IP是否在這個子網内。

arp協定

網絡包在實體層傳輸的時候依賴的mac 位址而不是上面的IP位址,也就是根據mac位址來決定把包發到哪裡去。

arp協定就是查詢某個IP位址的mac位址是多少,由于這種對應關系一般不太變化,是以每個os都有一份arp緩存(一般15分鐘過期),也可以手工清理,下面是arp緩存的内容:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

進入正題,回車後發生什麼?

有了上面的基礎知識打底,我們來思考一下 ping IP 到底發生了什麼。

首先 OS 的協定棧需要把ping指令封成一個icmp包,要填上標頭(包括src-IP、mac位址),那麼OS先根據目标IP和本機的route規則計算使用哪個interface(網卡),确定了路由也就基本上知道發送包的src-ip和src-mac了。每條路由規則基本都包含目标IP範圍、網關、MAC位址、網卡這樣幾個基本元素。

如果目标IP和本機使用的IP在同一子網

如果目标IP和本機IP是同一個子網(根據本機ifconfig上的每個網卡的netmask來判斷是否是同一個子網——知識點:子網路遮罩的作用),并且本機arp緩存沒有這條IP對應的mac記錄,那麼給整個子網的所有機器廣播發送一個 arp查詢,比如我ping 1.1.3.42,然後tcpdump抓包首先看到的是一個arp請求:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

上面就是本機發送廣播消息,1.1.3.42的mac位址是多少?很快1.1.3.42回複了自己的mac位址。 收到這個回複後,先緩存起來,下個ping包就不需要再次發arp廣播了。 然後将這個mac位址填寫到ping包的標頭的目标Mac(icmp包),然後發出這個icmp request包,按照mac位址,正确到達目标機器,然後對方正确回複icmp reply(對方回複也要查路由規則,arp查發送方的mac,這樣回包才能正确路由回來,略過)。

來看一次完整的ping 1.1.3.43,tcpdump抓包結果:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

我換了個IP位址,接着再ping同一個IP位址,arp有緩存了就看不到arp廣播查詢過程了。

如果目标IP不是同一個子網

arp隻是同一子網廣播查詢,如果目标IP不是同一子網的話就要經過本IP網關進行轉發(知識點:網關的作用)。如果本機沒有緩存網關mac(一般肯定緩存了),那麼先發送一次arp查詢網關的mac,然後流程跟上面一樣,隻是這個icmp包發到網關上去了(mac位址填寫的是網關的mac)。

從本機1.1.3.33 ping 11.239.161.60的過程,因為不是同一子網按照路由規則比對,根據route表應該走1.1.15.254這個網關,如下截圖:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

首先是目标IP 11.239.161.60 符合最上面紅框中的路由規則,又不是同一子網,是以查找路由規則中的網關1.1.15.254的Mac位址,arp cache中有,于是将 0c:da:41:6e:23:00 填入標頭,那麼這個icmp request包就發到1.1.15.254上了,雖然標頭的mac是 0c:da:41:6e:23:00,但是IP還是 11.239.161.60。

看看目标IP 11.239.161.60 真正的mac資訊(跟ping包標頭的Mac是不同的):

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

這個包根據Mac位址路由到了網關上。

網關接下來怎麼辦?

為了簡化問題,假設兩個網關直連

網關收到這個包後(因為mac位址是它的),打開一看IP位址是 11.239.161.60,不是自己的,于是繼續查自己的route和arp緩存,發現11.239.161.60這個IP的網關是11.239.163.247,于是把包的目的mac位址改成11.239.163.247的mac繼續發出去。

11.239.163.247這個網關收到包後,一看 11.239.161.60是自己同一子網的IP,于是該arp廣播找mac就廣播,cache有就拿cache的,然後這個包才最終到達目的11.239.161.60上。

整個過程中目标mac位址每一跳都在變,IP位址不變,每經過一次MAC變化可以簡單了解成一跳。

實際上可能要經過多個網關多次跳躍才能真正到達目标機器。

目标機器收到這個icmp包後的回複過程一樣,略過。

arp廣播風暴和arp欺騙

廣播風暴:如果一個子網非常大,機器非常多,每次arp查詢都是廣播的話,也容易因為N*N的問題導緻廣播風暴。

arp欺騙:同樣如果一個子網中的某台機器冒充網關或者其他機器,當收到arp廣播查詢的時候總是把自己的mac冒充目标機器的mac發給你,然後你的包先走到他,再轉發給真正的網關或者目标機器,是以在裡面動點什麼手腳,看看你發送的内容都還是很容易的。

講完基礎知識再來看開篇問題的答案

讀完上面的基礎知識相信現在我們已經能夠回答 ping IP 後發生了什麼。這些已經足夠解決99%的程式員日常網絡中網絡為什麼不通的問題了。但是前面的問題比這個要稍微複雜一點,還是依靠這些基礎知識就能解決——這是基礎知識的威力。

現場網絡同學所做的一些其它測試:

懷疑不通的IP所使用的mac位址沖突,在交換機上清理了交換機的arp緩存,沒有幫助,還是不通;

新拿出一台實體機配置上不通的容器的IP,這是通的,是以負責網絡的同學堅持是容器網絡的配置導緻了問題。

對于1能通,我認為這個測試不嚴格,新實體機所用的mac不一樣,并且所接的交換機口也不一樣,影響了測試結果。

祭出萬能手段——抓包

抓包在網絡問題中是萬能的,但是第一次容易被tcpdump抓包指令的衆多參數吓暈,不去操作你永遠上不了手,差距也就拉開了,你看差距有時候隻是你對一條指令的執行。

在實體機2上抓包:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結
從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

這個抓包能看到核心證據,ping包有到達實體機2,同時實體機2也正确回複了(mac、ip都對)。

同時在實體機1上抓包(抓包截圖略掉)隻能看到ping包出去,回包沒有到實體機1(是以回包肯定不會回到容器裡了)。

到這裡問題的核心在交換機沒有正确地把實體機2的回包送到實體機1上面,同時觀察到的不正常延時都在網關那一跳:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

最終的原因

最後在交換機上分析包沒正确發到實體機1上的原因跟客戶交換機使用了HSRP(熱備份路由器協定,就是多個交換機HA高可用,也就是同一子網可以有多個網關的IP),停掉HSRP後所有IP容器都能通了,并且前面的某些容器延時也恢複正常了。

通俗點說就是HSRP把回包拐跑了,有些回包拐跑了又送回來了(延時200ms那些)

至于HSRP為什麼會這麼做,要廠家出來解釋了。這裡關鍵在于能讓客戶認同問題出現在交換機上還是前面的抓包證據充分,無可辯駁。實際中我們都習慣不給證據就說:我的程式沒問題,就是你的問題。這樣表述沒有一點意義,我們是要拿着證據這麼說,對方也好就着證據來反駁,這叫優雅地甩鍋。

網絡到底通不通是個複雜的問題嗎?

講這個過程的核心目的是除了真正的網絡不通,有些是服務不可用了也怪網絡。很多現場的同學根本講不清自己的服務(比如80端口上的tomcat服務)還在不在,網絡通不通,是網絡不通呢還是服務出了問題。一看到SocketTimeoutException 就想把網絡同學抓過來羞辱兩句:網絡不通了,網絡抖動導緻我的程式異常了(網絡抖動是個萬能的扛包俠)。

實際這裡涉及到四個節點(以兩個網關直連為例),srcIP -> src網關 -> dest網關 -> destIP。如果ping不通(也有特殊的防火牆限制ping包不讓過的),那麼在這四段中分段ping(二分查找程式員應該最熟悉了)。 比如前面的例子就是網關沒有把包轉發回來。

抓包看ping包有沒有出去,對方抓包看有沒有收到,收到後有沒有回複。

ping自己網關能不能通,ping對方網關能不能通。

接下來說點跟程式員日常相關的

如果網絡能ping通,服務無法通路

那麼嘗試telnet IP port 看看你的服務是否還在監聽端口,在的話再看看服務程序是否能正常響應新的請求。有時候是程序死掉了,端口也沒人監聽了;有時候是程序還在但是假死了,是以端口也不響應新的請求了,還有的是TCP連接配接隊列滿了不能響應新的連接配接。

如果端口還在也是正常的話,telnet應該是好的:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

假如我故意換成一個不存在的端口,目标機器上的OS直接就拒絕了這個

連接配接(抓包的話一般是看到reset辨別):

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

一個SocketTimeoutException,程式員首先懷疑網絡丢包的Case

當時的回報應用代碼抛SocketTimeoutException,懷疑網絡問題:

  1. 業務應用連接配接Server 偶爾會出現逾時異常;
  2. 業務很多這樣的異常日志:[Server SocketTimeoutException]

檢查一下當時的網絡狀态非常好,出問題時間段的網卡的量資訊也非常正常:

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

上圖是通過sar監控到的9号 v24d9e0f23d40 這個網卡的流量,看起來也是正常,流量沒有出現明顯的波動。

為了監控網絡到底有沒有問題,接着在出問題的兩個容器上各啟動一個http server,然後在對方每1秒鐘互相發一次發http get請求通路這個http server,基本認識告訴我們如果網絡丢包、卡頓嚴重,那麼我這個http server的監控日志時間戳也會跳躍,如果應用是因為網絡出現異常那麼我啟動的http服務也會出現異常——甯願寫個工具都不背鍋(主要是背了鍋也不一定能解決掉問題)。

從實際監控來看,應用出現異常的時候我的http服務是正常的(寫了腳本判斷日志的連續性):

從計算機知識到落地能力,你欠缺了什麼?大學學到的基本概念還是從一個問題入手現象複習一下大學課本中的知識點route 路由表ifconfigarp協定進入正題,輸入後發生什麼?網關接下來怎麼辦?講完基礎知識再來看開篇問題的答案網絡到底通不通是個複雜的問題嗎?接下來說點跟程式員日常相關的總結

這也強有力地證明了網絡沒問題,是以寫業務代碼的同學一門心思集中火力檢視應用的問題。後來的實際調查發現是應用假死掉了(内部線程太多,卡死了),服務端口不響應請求了。

如果基礎知識缺乏一點那麼甩過來的這個鍋網絡是扛不動的,同時也阻礙了問題的真正發現。

TCP協定通訊過程跟前面ping一樣,隻是把ping的icmp協定換成TCP協定,也是要先根據route,然後arp。

總結

網絡丢包、卡頓、抖動很容易做扛包俠,隻有找到真正的原因解決問題才會更快,否則在錯誤的方向上怎麼發力都不對。準确的方向要靠好的基礎知識和正确的邏輯以及證據來支撐,而不是猜測。

  • 基礎知識是決定你能否幹到退休的關鍵因素;
  • 有了基礎知識不代表你能真正轉化成生産力;
  • 越是基礎,越是幾十年不變的基礎越是重要;
  • 知識到靈活運用要靠實踐,同時才能把知識之間的聯系建立起來;
  • 簡而言之缺的是融會貫通和運用;
  • 做一個有禮有節的甩包俠;
  • 在别人不給證據愚昧甩包的情況下你的機會就來了。

留幾個小問題:

  1. server回複client的時候是如何确定回複包中的src-ip和dest-mac的?一定是請求包中的dest-ip當成src-ip嗎?
  2. 上面問題中如果是TCP或者UDP協定,他們回複包中的src-ip和dest-mac擷取會不一樣嗎?
  3. 既然區域網路中都是依賴Mac位址來定位,那麼IP的作用又是什麼呢?

原文釋出時間為:2018-08-07

本文作者:蟄劍

本文來自雲栖社群合作夥伴“

阿裡技術

”,了解相關資訊可以關注“

繼續閱讀