Netty之UDP丟包解決


程序背景

程序是Java編寫,基於Netty框架寫的客戶端及服務端。

現象

客戶端大數據量持續發UDP數據,作為UDP服務器出現了部分數據頻繁丟失觸發程序自身重傳邏輯。
通過GC日志對比發現丟包的時間點偶有處於Full GC,說明Java程序接收間歇性stop world的不是根因。

觀察Udp的dump

通過watch -n 1 -d 'cat /proc/net/udp >> /usr/udpDump.txt'在發送數據的過程中持續觀察Udp緩沖區的狀況

  • /proc/net/udp是瞬時的Udp socket dump,另有/proc/net/udp6用於監控IPv6
  • dump輸出里的tx_queue是發送緩沖區,rx_queue是接收緩沖區,單位都是byte
  • 如果應用層收發效率足夠好,正常情況下tx_queuerx_queue兩者永遠是0
  • 發送數據過程中頻現rx_queue>0,說明Udp緩沖區有堆積現象
  • 輸出解釋見How to monitor Linux UDP buffer available space?Meaning of fields in /proc/net/udp

觀察Udp的stats

通過watch -n 1 -d 'netstat -su >> /usr/udpStats.txt'持續觀察Udp的stats輸出

  • 輸出里packets received的值指應用層從讀入緩沖區里取走的包
  • 輸出里packets to unknown port received的值指端口無應用監聽而分發至該端口的包
  • 輸出里packet receive errors的值指Udp接收錯誤數,正常情況下應該是0,在觀察中不停增加,證明出現Udp包溢出接收緩沖區的情況
    • 發生錯誤的包數與接收錯誤數非一一對應
  • 資料參見Udp Packet Receive ErrorsUdp packet drops and packet receive error difference

解決問題

服務端代碼優化

定論:
默認的UDP socket讀緩沖區不夠引發系統丟棄UDP包。
服務端代碼優化設置UDP socket讀緩沖區為2M,代碼如下

Bootstrap selfBootStrap = new Bootstrap();
selfBootStrap.group(group);
selfBootStrap.channel(NioDatagramChannel.class);
selfBootStrap.option(ChannelOption.SO_BROADCAST, true);
// 這一行設置了UDP socket讀緩沖區為2M
selfBootStrap.option(ChannelOption.SO_RCVBUF, 1024 * 2048);
selfBootStrap.handler(channelInitializer);
selfBootStrap.localAddress(selfPort);

理論上Udp socket讀緩沖區設置為2M在我們的測試場景下已經足夠。優化后雖有改善但仍有丟包現象。

Linux系統級調優

定論:
應用層設置了UDP socket緩沖區不一定在Linux上生效,原因在於Linux對Udp socket緩沖區存有系統級限制,超過該限制的緩沖區大小無效。

Windows對socket的緩沖區沒有限制

要點分析:
Linux通過net.core.rmem_max控制Udp的讀緩沖區,通過net.core.wmem_max控制Udp的寫緩沖區。
在程序的啟動sh腳本里添加如下代碼修改net.core.rmem_max

# 服務器默認UDP讀緩沖區最大128K。修改為2G。解決UDP丟包問題
rmemCount=`cat /etc/sysctl.conf|grep "net.core.rmem_max" | wc -l`
if [ ${rmemCount} -eq 0 ]
then
    echo "net.core.rmem_max = 2147483647" >> /etc/sysctl.conf
    sysctl -p
fi

腳本的作用就是修改/etc/sysctl.conf文件,並鍵入sysctl -p命令使自定義參數生效。
資料參見Improving UDP Performance by Configuring OS UDP Buffer LimitsUDP Drops on Linux


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM