怎麼檢查網路丟包(網路丟包怎麼檢查是哪的問題)
要明白一個知識點,首先要快速的對這個知識點建立一個概念模型,有了概念模型之後,再在這個模型上不斷的去填充一些細節的東西,會有助於我們把握知識的本質。
頻寬是什麼?
頻寬是網路被髮送的能力,它會受到網絡卡複製網路包到核心緩衝區或者搬運核心緩衝區的網路包到網絡卡緩衝區能力的影響,也會受到接收視窗或擁塞視窗的影響,也就是說如果對端接收能力變小,那麼頻寬是不能提升上去的。
當整個網路的鏈路變長以後,網路的情況是很複雜的。網路包有可能會經過多個路由器或者不同運營商之間的線路去進行資料交換,而不同代理商之間的網路流量是極其龐大的,它會導致你的網路包產生丟包或者重發的狀況,針對於這種情況,平時在部署服務節點時候,如果有能力在設計鏈路的時候最好能夠避免這種不同代理商之間的網路交換,優化整個網路傳輸的鏈路選擇能力,這也是cdn提供全域性加速的一個原理。
cdn原理是能夠在世界各地部署很多個節點,然後每個節點之間的一個鏈路選擇是通過服務運營商精心編排過的,它能夠保證你的整個網路的鏈路是經過優化的,能夠讓你的網路包更少的產生丟包或者是重發的狀況。
網路包的收發過程
我們得明白一個網路包是如何經過應用程式的,
一般應用程式發起一個網路請求,這個網路請求的資料會寫到核心的套接字緩衝區當中,然後核心會對這個套接字緩衝區的資料去加上tcp頭或udp頭,然後又經由ip層,再加上一個ip頭,中間會經過防火牆的一系列規則對這個網路包進行過濾,看是丟棄還是繼續往網絡卡上面去傳送,最終到達鏈路層之後,這個網路包會經由鏈路層去發到網絡卡上的環形緩衝區上,最後由網絡卡傳送到整個網路當中,其中每一環都是有可能會發生丟包的。
理解了網路包的收發過程,建立起了這樣一種概念模型之後,會有助於我們對丟包問題的排查。
如何去衡量網路情況的好壞
對應用服務進行監控的時候,如何去衡量網路情況的好壞,一般也用來衡量硬體資源的好壞。
一個通用套路,一般我們會先看一下,在系統層面上網路指標的一個表現,再看下具體是哪個程序造成這種表現的異常,再去定位到問題程式碼。
具體對網路而言,如何從系統的層面或者是我們要使用哪些工具去看這個網路的好壞?
從系統層面看網路有幾個重要的指標,MBS 代表網絡卡每秒傳送多少或者是接收多少個M位元組,Mbps是每秒多少M位元位。通常說的頻寬的單位就是Mbps,一般100M頻寬的話換算成MBS等於Mbps除以8。
平時選擇伺服器節點的時候,除了頻寬,還有pps就是每秒傳送、接收包的數量,它也是有限制的。
當我們在遇到網路效能問題的時候,首先可以去觀察你的機器節點上這兩個指標是否是已經達到了一個瓶頸的狀態。如果頻寬只有100Mbps,然後通過工具檢視機器上面的節點頻寬,馬上就要超過這個值的時候,很有可能這個時候頻寬已經成為瓶頸,可能要對機器的配額去進行升級。
sar
# 使用sar每一秒統計一次網路介面的活動狀況,連續顯示5次 sar -n DEV 1 5
- IFACE是網絡卡介面名稱
- rxpck/s、txpck/s 每秒收或發的資料包數量
- rxkB/s、txkB/s 每秒收或發的位元組數,以kB/s為單位
- rxcmp/s、txcmp/s 每秒收或發的壓縮過的資料包數量
- rxmcst/s 每秒收到的多播(多播是一點對多點的通訊)資料包
看完了整個系統層面的網路情況,可以再精細點的從程序的角度去看這個問題。
iftop
# https://www.tecmint.com/iftop-linux-network-bandwidth-monitoring-tool/ yum -y install libpcap libpcap-devel ncurses ncurses-devel yum install epel-release yum install -y iftop iftop -P
能夠列出這個系統裡面每一條連結的一個Mbps,能夠找出哪個ip消耗流量最多。更多的時候其實不是系統網路達到瓶頸,而是程序處理網路包的能力跟不上。
nethogs
yum install nethogs # 檢視程序佔用頻寬的情況 nethogs ens33
列出每個程序的收發流量的資料,找出哪個程序是最消耗流量的,能夠更方便的讓我們去定位哪個程序出的問題。
go trace這個工具能夠去分析出網路排程帶來的延遲問題,其實也能夠從側面去反饋出你的程式在某一塊程式碼上面可能是在進行頻繁的網路排程,有可能是進行頻繁排程之後,比較消耗頻寬,從而可能間接的反映出延遲會略有提高,go trace也能夠從讓我們在網路效能問題當中能夠比較間接去找出一塊問題的程式碼。
網路效能當中比較重要的一個點就是如何查詢你的一個丟包問題,對於上面的圖[網路包傳輸過程],從上到下依次分析,先看應用層,通過listen這個方法去監聽套接字的時候,在三次握手的時候,會有兩個佇列,首先伺服器接收到客戶端的syn包的時候,會建立一個半連線佇列 ,這個半連線佇列會將那些還沒有完成三次握手但是卻傳送了一個syn包的這種連線放到裡面,會回覆客戶端一個syn ack,客戶端收到了這個ack和syn包之後,會回覆給服務端一個ack,這個時候核心就會將這個連線放到全連線佇列,當伺服器呼叫accept方法的時候,會將這條連線從全連線佇列裡取出來,所以這個時候涉及了兩個佇列,如果這兩個佇列滿了的話,就會可能會產生丟包的行為。
首先來看一下半連線佇列,它是由核心引數決定的,這個也是可以調整的。通過三次握手,才能夠去建立連線,但是由於這種佇列的機制很有可能在併發量大的時候,會產生佇列滿了,然後丟包的行為,所以核心提供了一個tcp_syncookies引數,它能夠去啟用tcp_syncookies這個機制,當半連線佇列溢位的時候,它能夠讓核心不直接去丟棄這個新包,而是回覆帶有syncookie的包,這個時候客戶端再去向伺服器進行請求的時候,它會去驗證這個syncookie,這樣能夠防止半連線佇列溢位的時候造成服務不可用的一個情況。
如何去確定是由於半連線佇列溢位導致的丟包?
通過dmesg去日誌裡面去搜尋tcp drop,是能夠發現丟包的情況,dmesg是一個核心的日誌記錄,我們能夠從裡面去找出一些核心的行為,
dmesg|grep "TCP: drop open erquest form"
然後看下全連線佇列該怎麼看,通過ss命令的話,能夠去看到你的服務在listen的時候,全連線佇列的大小
ss -lnt # -l 顯示正在監聽 # -n 不解析服務名稱 # -t 只顯示 tcp socket
對於你的那個監聽服務而言,它的一個Send-Q,就是代表當前全連線佇列長度,也就是當前已完成三次握手並等待服務端 accept() 的 TCP 連線。Recv-Q是指當前全連線佇列的大小,上面的輸出結果說明監聽 9000 埠的 TCP 服務,最大全連線長度為 128。Recv-Q一般都是為0,如果存在一種大於0的情況並且會持續一個較長時間的話,就說明你的服務處理連線的能力比較慢了,會導致全連線佇列過滿或者丟棄,這個時候應該會加快你的服務處理連線的能力。
ss命令對於狀態為ESTAB的連線,它看的不是你這個監聽服務,而是去看一條已經建立好的連線相關指標,Recv-Q是代表收到但未被應用程式讀取的一個位元組數,Send-Q已傳送但未收到確認的位元組數,通過這兩個指標,能夠去看到是應用程式對一個資料的處理能力慢,還是說是客戶端對接收的資料處理的比較慢的情況,一般這兩個值也都是為0,如果有其中一個不為0 ,你可能要去排查一下是客戶端的問題還是伺服器的問題。
當全連線佇列滿了之後,核心預設會將包丟棄,但是也已可指定核心的一個其他行為,如果是將tcp_abort_on_overflow這個值設為1的話,那會直接發一個reset的包給客戶端,直接將這個連線斷開掉,表示廢掉這個握手過程和這個連線。
經過應用層之後,網路包會到達到傳輸層,傳輸層會有防火牆的存在,如果防火牆開啟的話,那和防火牆有關的連線跟蹤表:nf_conntrack這個是linux為每個經過核心網路棧的資料包,會生成一個連線的記錄項,當伺服器處理過多時,這個連線記錄項所在的連線跟蹤表就會被打滿,然後伺服器就會丟棄新建連線的資料包,所以有時候丟包有可能是防火牆的連線跟蹤表設計的太小了。
那如何去看連線跟蹤表的大小呢
# 檢視nf_conntrack表最大連線數 cat /proc/sys/net/netfilter/nf_conntrack_max # 檢視nf_conntrack表當前連線數 cat /proc/sys/net/netfilter/nf_conntrack_count
通過這個檔案看連線跟蹤表的一個最大連線數nf_conntrack_max,所以在丟包的時候,可以對這一部分去進行排查,看下連線跟蹤表是不是被打滿了。
網路包經過傳輸層之後,再來看網路層和物理層,提到網路層和物理層,就要看網絡卡了,通過netstat命令,能夠去看整個機器上面網絡卡的丟包和收包的情況。
RX-DRP這個指標資料,如果它大於0,說明這個網絡卡是有丟包情況,這裡記錄的是從開機到目前為止的資料情況,所以在分析的時候,隔一定的時間去看這個指標是否有上漲。
RX-OVR指標說明這個網絡卡的環形緩衝區滿了之後產生的丟棄行為。
通過netstat能夠分析網絡卡丟包的情況,
# netstat可以統計網路丟包以及環形緩衝區溢位 netstat -i
netstat還能夠統計網路協議層的丟包情況,
MTU
應用層的網路包通過網路層的時候會根據資料包的大小去進行分包傳送。
當tcp資料包的大小傳送網路層之後,網路層發現這個包會大於它的mtu值,這個資料包會進行一個分包的操作。在進行網絡卡設定的時候,會設定為你的傳輸層包,如果大於了mtu這個值,那就可以直接將這個網路包丟棄,這也是在現實生活中經常會碰到的一個丟包問題。
所以你在檢查鏈路的時候,通常鏈路長了可能不太好排查,鏈路短一點,可能會很容易看到整條鏈路當中mtu的情況,看一下是不是每條鏈路上對應的每個網絡卡的mtu指標是不一樣的,如果不一樣的話,有可能會造成你的丟包問題,因為一個包的轉發跟網路上面設定的mtu值大小有關係,比如設定為大於mtu之後會把這個包給丟棄掉。如果傳送的mtu包的大小超過網絡卡規定的大小,並且網絡卡不允許分片,那麼則會產生丟包。