Linux 網絡常見報錯及分析
被來是想将報錯和監控拆開的,但是發現兩者幾乎是耦合的,通過監控項才能發現錯誤,定為錯誤的原因時也要依賴監控項。索性就将兩者合并到了一起。
對于很多的報錯,實際上你即使看到報錯的資訊也不清楚到底是那裡報錯了,或者模棱兩可,甚至是誤導。最好的方式是 “Show me the code” 。
在此,簡單介紹一下與網絡相關的調試、檢視方法,當然也包括了報錯相關的内容。
在此僅介紹 procfs 的相關實作,核心的相關實作在 net/core/net-procfs.c 中,是以如果對 /proc/net 下的檔案内容不熟悉,可以直接檢視核心中的統計項。
網絡丢包會有多種可能,例如,交換機,上連和下連端口的流量跑滿或鍊路有問題,那麼資料包就有可能會被交換機丢掉;負載均衡裝置,包括了硬體裝置以及軟體的負載均衡。
在此,我們僅檢視本機可能導緻的掉包。
有兩種情況,一是網卡發現作業系統處理不過來,丢資料包,可以讀取下面的檔案:
每個網絡接口一行統計資料,第 4 列(errs)是接收出錯的資料包數量,第 5 列(drop)是接收不過來丢棄的數量。
第二部分是傳統非 NAPI 接口實作的網卡驅動,每個 CPU 有一個隊列,當在隊列中緩存的資料包數量超過 net.core.netdev_max_backlog 時,網卡驅動程式會丢掉資料包,這個見下面的檔案:
每個 CPU 有一行統計資料,第二列是對應 CPU 丢棄的資料包數量。
核心中記錄了兩個計數器:
ListenOverflows:當 socket 的 listen queue 已滿,當新增一個連接配接請求時,應用程式來不及處理;
ListenDrops:包含上面的情況,除此之外,當記憶體不夠無法為新的連接配接配置設定 socket 相關的資料結構時,也會加 1,當然還有别的異常情況下會增加 1。
分别對應下面檔案中的第 21 列(ListenOverflows)和第 22 列(ListenDrops),可以通過如下指令檢視:
如果使用 netstat 指令,有丢包時會看到 “times the listen queue of a socket overflowed” 以及 “SYNs to LISTEN sockets ignored” 對應行前面的數字;如果值為 0 則不會輸出對應的行。
直接看代碼,在核心中,對應的代碼如下。
如上所示,出現記憶體不足可能會有兩種情況:
有太多的 orphan sockets,通常對于一些前端的伺服器經常會出現這種情況。
配置設定給 TCP 的記憶體确實較少,進而導緻記憶體不足。
這個比較好排查,隻需要檢視一下實際配置設定給 TCP 多少記憶體,現在時用了多少記憶體即可。需要注意的是,通常的配置項使用的機關是 Bytes,在此用的是 Pages,通常為 4K 。
先檢視下給 TCP 配置設定了多少記憶體。
簡單來說,三個值分别表示進入 無壓力、壓力模式、記憶體上限的值,當到達最後一個值的時候就會報錯。
接下來檢視一下目前使用的記憶體。
其中的 mem 表示使用了多少 Pages,如果相比 tcp_mem 的配置來說還很小,那麼就有可能是由于 orphan sockets 導緻的。
首先介紹一下什麼是 orphan sockets,簡單來說就是該 socket 不與任何一個檔案描述符相關聯。例如,當應用調用 close() 關閉一個連結時,此時該 socket 就成為了 orphan,但是該 sock 仍然會保留一段時間,直到最後根據 TCP 協定結束。
實際上 orphan socket 對于應用來說是無用的,是以核心希望盡可能減小 orphan 的數量。對于像 http 這樣的短請求來說,出現 orphan 的機率會比較大。
對于系統允許的最大 orphan 數量,以及目前的 orphan 數量可以通過如下方式檢視:
你可能會發現,sockstat 中的 orphan 數量要遠小于 tcp_max_orphans 的數目。
實際上,可以從代碼中看到,實際會有個偏移量 shift,該值範圍為 [0, 2] 。
也就是說,在某些場景下會對 orphan 做些懲罰,将 orphan 的數量 2x 甚至 4x,這也就解釋了上述的問題。
如果是這樣,那麼就可以根據具體的情況,将 tcp_max_orphans 值适當調大。
除了可能真正出現記憶體不足的情況之外,還有可能是由于核心的懲罰措施,導緻 orphan 的誤報。
/proc/net/tcp:記錄 TCP 的狀态資訊。
本文轉自 憬薇 51CTO部落格,原文連結:http://blog.51cto.com/welcomeweb/1975357