當(dāng)前位置:首頁 > 公眾號(hào)精選 > 21ic電子網(wǎng)
[導(dǎo)讀]作者:CloudDeveloper 鏈接:https://cizixs.com/2018/01/13/linux-udp-packet-drop-debug/ 最近工作中遇到某個(gè)服務(wù)器應(yīng)用程序 UDP 丟包,在排查過程中查閱了很多資料,我在排查過程中基本都是通過使用 tcpdump 在出現(xiàn)問題的各個(gè)環(huán)節(jié)上進(jìn)行抓包、分析在那個(gè)環(huán)

作者:CloudDeveloper

鏈接:https://cizixs.com/2018/01/13/linux-udp-packet-drop-debug/

最近工作中遇到某個(gè)服務(wù)器應(yīng)用程序 UDP 丟包,在排查過程中查閱了很多資料,我在排查過程中基本都是通過使用 tcpdump 在出現(xiàn)問題的各個(gè)環(huán)節(jié)上進(jìn)行抓包、分析在那個(gè)環(huán)節(jié)出現(xiàn)問題、針對(duì)性去排查解決問題,對(duì)癥下藥,最后終究能夠解決問題。但是這種情況大多是因?yàn)榉?wù)本身的問題,如果是環(huán)境問題、操作系統(tǒng)、甚至硬件的問題,可能從服務(wù)本身出發(fā)不能解決問題,但是這篇文章另辟蹊徑,從外部環(huán)境分析可能丟包的原因,看完之后,很受用,部分章節(jié)對(duì)原文有所修改,下面分享出來供更多人參考。


在開始之前,我們先用一張圖解釋 linux 系統(tǒng)接收網(wǎng)絡(luò)報(bào)文的過程。

  1. 首先網(wǎng)絡(luò)報(bào)文通過物理網(wǎng)線發(fā)送到網(wǎng)卡

  2. 網(wǎng)絡(luò)驅(qū)動(dòng)程序會(huì)把網(wǎng)絡(luò)中的報(bào)文讀出來放到 ring buffer 中,這個(gè)過程使用 DMA(Direct Memory Access),不需要 CPU 參與

  3. 內(nèi)核從 ring buffer 中讀取報(bào)文進(jìn)行處理,執(zhí)行 IP 和 TCP/UDP 層的邏輯,最后把報(bào)文放到應(yīng)用程序的 socket buffer 中

  4. 應(yīng)用程序從 socket buffer 中讀取報(bào)文進(jìn)行處理

如何解決Linux系統(tǒng)UDP丟包問題?辦法都在這里!

在接收 UDP 報(bào)文的過程中,圖中任何一個(gè)過程都可能會(huì)主動(dòng)或者被動(dòng)地把報(bào)文丟棄,因此丟包可能發(fā)生在網(wǎng)卡和驅(qū)動(dòng),也可能發(fā)生在系統(tǒng)和應(yīng)用。

之所以沒有分析發(fā)送數(shù)據(jù)流程,一是因?yàn)榘l(fā)送流程和接收類似,只是方向相反;另外發(fā)送流程報(bào)文丟失的概率比接收小,只有在應(yīng)用程序發(fā)送的報(bào)文速率大于內(nèi)核和網(wǎng)卡處理速率時(shí)才會(huì)發(fā)生。

本篇文章假定機(jī)器只有一個(gè)名字為 eth0 的 interface,如果有多個(gè) interface 或者 interface 的名字不是 eth0,請(qǐng)按照實(shí)際情況進(jìn)行分析。

NOTE:文中出現(xiàn)的 RX(receive) 表示接收?qǐng)?bào)文,TX(transmit) 表示發(fā)送報(bào)文。

確認(rèn)有 UDP 丟包發(fā)生


要查看網(wǎng)卡是否有丟包,可以使用 ethtool -S eth0 查看,在輸出中查找 bad 或者 drop 對(duì)應(yīng)的字段是否有數(shù)據(jù),在正常情況下,這些字段對(duì)應(yīng)的數(shù)字應(yīng)該都是 0。如果看到對(duì)應(yīng)的數(shù)字在不斷增長(zhǎng),就說明網(wǎng)卡有丟包。

另外一個(gè)查看網(wǎng)卡丟包數(shù)據(jù)的命令是 ifconfig,它的輸出中會(huì)有 RX(receive 接收?qǐng)?bào)文)和 TX(transmit 發(fā)送報(bào)文)的統(tǒng)計(jì)數(shù)據(jù):

[root@k8s-master ng]# ifconfig enp1enp2s0f1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 ether 04:b0:e7:fa:75:9d txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device memory 0x92200000-922fffff


此外,linux 系統(tǒng)也提供了各個(gè)網(wǎng)絡(luò)協(xié)議的丟包信息,可以使用 netstat -s 命令查看,加上 --udp 可以只看 UDP 相關(guān)的報(bào)文數(shù)據(jù):

[root@k8s-master ng]# netstat -s -uIcmpMsg: InType0: 17 InType3: 75 InType8: 77 OutType0: 77 OutType3: 692 OutType8: 249Udp: 5728807 packets received 12 packets to unknown port received. 0 packet receive errors 982710 packets sent 0 receive buffer errors 0 send buffer errorsUdpLite:IpExt: InNoRoutes: 3 InBcastPkts: 497633 InOctets: 1044710406807 OutOctets: 17460621991142 InBcastOctets: 114600482 InNoECTPkts: 2886955071


對(duì)于上面的輸出,關(guān)注下面的信息來查看 UDP 丟包的情況:

  • packet receive errors 不為空,并且在一直增長(zhǎng)說明系統(tǒng)有 UDP 丟包

  • packets to unknown port received 表示系統(tǒng)接收到的 UDP 報(bào)文所在的目標(biāo)端口沒有應(yīng)用在監(jiān)聽,一般是服務(wù)沒有啟動(dòng)導(dǎo)致的,并不會(huì)造成嚴(yán)重的問題

  • receive buffer errors 表示因?yàn)?UDP 的接收緩存太小導(dǎo)致丟包的數(shù)量

NOTE:并不是丟包數(shù)量不為零就有問題,對(duì)于 UDP 來說,如果有少量的丟包很可能是預(yù)期的行為,比如丟包率(丟包數(shù)量/接收?qǐng)?bào)文數(shù)量)在萬分之一甚至更低。

網(wǎng)卡或者驅(qū)動(dòng)丟包

之前講過,如果 ethtool -S eth0 中有 rx_***_errors 那么很可能是網(wǎng)卡有問題,導(dǎo)致系統(tǒng)丟包,需要聯(lián)系服務(wù)器或者網(wǎng)卡供應(yīng)商進(jìn)行處理。

[root@k8s-master ng]# ethtool -S enp1 | grep rx_ | grep errors rx_crc_errors: 0 rx_missed_errors: 0 rx_long_length_errors: 0 rx_short_length_errors: 0 rx_align_errors: 0 rx_errors: 0 rx_length_errors: 0 rx_over_errors: 0 rx_frame_errors: 0 rx_fifo_errors: 0


netstat -i 也會(huì)提供每個(gè)網(wǎng)卡的接發(fā)報(bào)文以及丟包的情況,正常情況下輸出中 error 或者 drop 應(yīng)該為 0。

如果硬件或者驅(qū)動(dòng)沒有問題,一般網(wǎng)卡丟包是因?yàn)樵O(shè)置的緩存區(qū)(ring buffer)太小,可以使用 ethtool 命令查看和設(shè)置網(wǎng)卡的 ring buffer。

ethtool -g 可以查看某個(gè)網(wǎng)卡的 ring buffer,比如下面的例子

[root@k8s-master ng]# ethtool -g enp1Ring parameters for enp2s0f1:Pre-set maximums:RX: 4096RX Mini: 0RX Jumbo: 0TX: 4096Current hardware settings:RX: 256RX Mini: 0RX Jumbo: 0TX: 256


Pre-set 表示網(wǎng)卡最大的 ring buffer 值,可以使用 ethtool -G eth0 rx 8192 設(shè)置它的值。

Linux 系統(tǒng)丟包

linux 系統(tǒng)丟包的原因很多,常見的有:UDP 報(bào)文錯(cuò)誤、防火墻、UDP buffer size 不足、系統(tǒng)負(fù)載過高等,這里對(duì)這些丟包原因進(jìn)行分析。

UDP 報(bào)文錯(cuò)誤

如果在傳輸過程中UDP 報(bào)文被修改,會(huì)導(dǎo)致 checksum 錯(cuò)誤,或者長(zhǎng)度錯(cuò)誤,linux 在接收到 UDP 報(bào)文時(shí)會(huì)對(duì)此進(jìn)行校驗(yàn),一旦發(fā)明錯(cuò)誤會(huì)把報(bào)文丟棄。

如果希望 UDP 報(bào)文 checksum 及時(shí)有錯(cuò)也要發(fā)送給應(yīng)用程序,可以在通過 socket 參數(shù)禁用 UDP checksum 檢查。

防火墻

如果系統(tǒng)防火墻丟包,表現(xiàn)的行為一般是所有的 UDP 報(bào)文都無法正常接收,當(dāng)然不排除防火墻只 drop 一部分報(bào)文的可能性。

如果遇到丟包比率非常大的情況,請(qǐng)先檢查防火墻規(guī)則,保證防火墻沒有主動(dòng) drop UDP 報(bào)文。

UDP buffer size 不足

linux 系統(tǒng)在接收?qǐng)?bào)文之后,會(huì)把報(bào)文保存到緩存區(qū)中。因?yàn)榫彺鎱^(qū)的大小是有限的,如果出現(xiàn) UDP 報(bào)文過大(超過緩存區(qū)大小或者 MTU 大?。⒔邮盏綀?bào)文的速率太快,都可能導(dǎo)致 linux 因?yàn)榫彺鏉M而直接丟包的情況。

在系統(tǒng)層面,linux 設(shè)置了 receive buffer 可以配置的最大值,可以在下面的文件中查看,一般是 linux 在啟動(dòng)的時(shí)候會(huì)根據(jù)內(nèi)存大小設(shè)置一個(gè)初始值。

  • /proc/sys/net/core/rmem_max:允許設(shè)置的 receive buffer 最大值

  • /proc/sys/net/core/rmem_default:默認(rèn)使用的 receive buffer 值

  • /proc/sys/net/core/wmem_max:允許設(shè)置的 send buffer 最大值

  • /proc/sys/net/core/wmem_dafault:默認(rèn)使用的 send buffer 最大值

但是這些初始值并不是為了應(yīng)對(duì)大流量的 UDP 報(bào)文,如果應(yīng)用程序接收和發(fā)送 UDP 報(bào)文非常多,需要講這個(gè)值調(diào)大??梢允褂?nbsp;sysctl 命令讓它立即生效:

[root@k8s-master ~]# sysctl -w net.core.rmem_max=26214400 # 設(shè)置為 25Mnet.core.rmem_max = 26214400


也可以修改 /etc/sysctl.conf 中對(duì)應(yīng)的參數(shù)在下次啟動(dòng)時(shí)讓參數(shù)保持生效。

如果報(bào)文報(bào)文過大,可以在發(fā)送方對(duì)數(shù)據(jù)進(jìn)行分割,保證每個(gè)報(bào)文的大小在 MTU 內(nèi)。

另外一個(gè)可以配置的參數(shù)是 netdev_max_backlog,它表示 linux 內(nèi)核從網(wǎng)卡驅(qū)動(dòng)中讀取報(bào)文后可以緩存的報(bào)文數(shù)量,默認(rèn)是 1000,可以調(diào)大這個(gè)值,比如設(shè)置成 2000:

[root@k8s-master ~]# sudo sysctl -w net.core.netdev_max_backlog=2000net.core.netdev_max_backlog = 2000[root@k8s-master ~]#



系統(tǒng)負(fù)載過高

系統(tǒng) CPU、memory、IO 負(fù)載過高都有可能導(dǎo)致網(wǎng)絡(luò)丟包,比如 CPU 如果負(fù)載過高,系統(tǒng)沒有時(shí)間進(jìn)行報(bào)文的 checksum 計(jì)算、復(fù)制內(nèi)存等操作,從而導(dǎo)致網(wǎng)卡或者 socket buffer 出丟包;memory 負(fù)載過高,會(huì)應(yīng)用程序處理過慢,無法及時(shí)處理報(bào)文;IO 負(fù)載過高,CPU 都用來響應(yīng) IO wait,沒有時(shí)間處理緩存中的 UDP 報(bào)文。

linux 系統(tǒng)本身就是相互關(guān)聯(lián)的系統(tǒng),任何一個(gè)組件出現(xiàn)問題都有可能影響到其他組件的正常運(yùn)行。對(duì)于系統(tǒng)負(fù)載過高,要么是應(yīng)用程序有問題,要么是系統(tǒng)不足。對(duì)于前者需要及時(shí)發(fā)現(xiàn),debug 和修復(fù);對(duì)于后者,也要及時(shí)發(fā)現(xiàn)并擴(kuò)容。

應(yīng)用丟包

上面提到系統(tǒng)的 UDP buffer size,調(diào)節(jié)的 sysctl 參數(shù)只是系統(tǒng)允許的最大值,每個(gè)應(yīng)用程序在創(chuàng)建 socket 時(shí)需要設(shè)置自己 socket buffer size 的值。

linux 系統(tǒng)會(huì)把接受到的報(bào)文放到 socket 的 buffer 中,應(yīng)用程序從 buffer 中不斷地讀取報(bào)文。所以這里有兩個(gè)和應(yīng)用有關(guān)的因素會(huì)影響是否會(huì)丟包:socket buffer size 大小以及應(yīng)用程序讀取報(bào)文的速度。

對(duì)于第一個(gè)問題,可以在應(yīng)用程序初始化 socket 的時(shí)候設(shè)置 socket receive buffer 的大小,比如下面的代碼把 socket buffer 設(shè)置為 20MB:

uint64_t receive_buf_size = 20*1024*1024; //20 MBsetsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &receive_buf_size, sizeof(receive_buf_size));


如果不是自己編寫和維護(hù)的程序,修改應(yīng)用代碼是件不好甚至不太可能的事情。很多應(yīng)用程序會(huì)提供配置參數(shù)來調(diào)節(jié)這個(gè)值,請(qǐng)參考對(duì)應(yīng)的官方文檔;如果沒有可用的配置參數(shù),只能給程序的開發(fā)者提 issue 了。

很明顯,增加應(yīng)用的 receive buffer 會(huì)減少丟包的可能性,但同時(shí)會(huì)導(dǎo)致應(yīng)用使用更多的內(nèi)存,所以需要謹(jǐn)慎使用。

另外一個(gè)因素是應(yīng)用讀取 buffer 中報(bào)文的速度,對(duì)于應(yīng)用程序來說,處理報(bào)文應(yīng)該采取異步的方式

包丟在什么地方

想要詳細(xì)了解 linux 系統(tǒng)在執(zhí)行哪個(gè)函數(shù)時(shí)丟包的話,可以使用 dropwatch 工具,它監(jiān)聽系統(tǒng)丟包信息,并打印出丟包發(fā)生的函數(shù)地址:

# dropwatch -l kasInitalizing kallsyms dbdropwatch> startEnabling monitoring...Kernel monitoring activated.Issue Ctrl-C to stop monitoring
1 drops at tcp_v4_do_rcv+cd (0xffffffff81799bad)10 drops at tcp_v4_rcv+80 (0xffffffff8179a620)1 drops at sk_stream_kill_queues+57 (0xffffffff81729ca7)4 drops at unix_release_sock+20e (0xffffffff817dc94e)1 drops at igmp_rcv+e1 (0xffffffff817b4c41)1 drops at igmp_rcv+e1 (0xffffffff817b4c41)


通過這些信息,找到對(duì)應(yīng)的內(nèi)核代碼處,就能知道內(nèi)核在哪個(gè)步驟中把報(bào)文丟棄,以及大致的丟包原因。本人在排查這個(gè)問題過程中更傾向于在各個(gè)機(jī)器抓包,這個(gè)方法更適合追蹤自身業(yè)務(wù)出現(xiàn)問題導(dǎo)致丟包,如下所示:


tcpdump -i 網(wǎng)絡(luò)接口名稱 udp port 2020 -s0 -XX -nn


此外,還可以使用 linux perf 工具監(jiān)聽 kfree_skb(把網(wǎng)絡(luò)報(bào)文丟棄時(shí)會(huì)調(diào)用該函數(shù)) 事件的發(fā)生:


sudo perf record -g -a -e skb:kfree_skbsudo perf script



關(guān)于 perf 命令的使用和解讀,網(wǎng)上有很多文章可以參考。



總結(jié)

  • UDP 本身就是無連接不可靠的協(xié)議,適用于報(bào)文偶爾丟失也不影響程序狀態(tài)的場(chǎng)景,比如視頻、音頻、游戲、監(jiān)控等。對(duì)報(bào)文可靠性要求比較高的應(yīng)用不要使用 UDP,推薦直接使用 TCP。當(dāng)然,也可以在應(yīng)用層做重試、去重保證可靠性

  • 如果發(fā)現(xiàn)服務(wù)器丟包,首先通過監(jiān)控查看系統(tǒng)負(fù)載是否過高,先想辦法把負(fù)載降低再看丟包問題是否消失

  • 如果系統(tǒng)負(fù)載過高,UDP 丟包是沒有有效解決方案的。如果是應(yīng)用異常導(dǎo)致 CPU、memory、IO 過高,請(qǐng)及時(shí)定位異常應(yīng)用并修復(fù);如果是資源不夠,監(jiān)控應(yīng)該能及時(shí)發(fā)現(xiàn)并快速擴(kuò)容

  • 對(duì)于系統(tǒng)大量接收或者發(fā)送 UDP 報(bào)文的,可以通過調(diào)節(jié)系統(tǒng)和程序的 socket buffer size 來降低丟包的概率

  • 應(yīng)用程序在處理 UDP 報(bào)文時(shí),要采用異步方式,在兩次接收?qǐng)?bào)文之間不要有太多的處理邏輯

--END--


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

21ic電子網(wǎng)

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉