Flume使用udp丟包問題

原文鏈接:http://kane-xie.github.io/2018/10/13/2018-10-13_Flume%20UDP%20Source%E4%B8%A2%E5%8C%85%E9%97%AE%E9%A2%98/

問題描述

有用戶提出通過udp協議發送數據到實時平臺,所以考慮在flume接收節點添加udp source來接收udp請求

  • flume配置如下
1
2
3
4
a2.sources.syslog_udp_src.type=syslogudp
a2.sources.syslog_udp_src.host=0.0.0.0
a2.sources.syslog_udp_src.port=5340
a2.sources.syslog_udp_src.channels=test_channel
  • 系統環境如下
1
2
3
CentOS Linux release 7.2.1511
4核cpu
8G內存

在測試中發現當發送速度超過500/s時開始出現數據丟失,開始以爲是網絡丟包,但通過tcpdump抓包比對發現並沒有丟包

netstat -su命令顯示有數據包接收失敗

1
2
3
4
5
6
Udp:
    4329216468 packets received
    329761 packets to unknown port received.
    301745872 packet receive errors
    337569082 packets sent
    RcvbufErrors: 1061789

 

  • packets received表示application接收到的數據包的數量
  • packets to unknown port表示由於端口沒有打開而丟失的數據包數據量,例如應用掛掉或者重啓
  • packet receive errors表示接收數據包的異常的數量,需要注意的是error和接收失敗的數據包並不是一對一的關係,即有一個數據包有可能會產生多個error

問題原因

當客戶端發送一個udp請求到flume時,整個流轉順序是這樣的

1
Client -> Kernel UDP socket buffer(4MB) -> Flume UDP Source buffer(64KB) -> Flume Channel buffer(磁盤,file channel)

 

  • flume通過SyslogUDPSource接收UDP請求,底層是使用Netty的OioDatagramChannelFactory來創建服務器端channel,實現BIO(阻塞式IO)。BIO會對每個請求分配一個線程來處理,這種處理模式效率很低。經過測試,Flume UDP只能達到1100+的QPS,0.324MB/s

  • 當client的發送速度大於flume udp source的接收速度時,數據開始在Kernel UDP socket buffer堆積,當buffer滿了的時候,後續的請求就會被丟棄,發生packet receive errors

  • 即使平均吞吐量沒有超過flume udp的接收能力,但如果出現發送速度波動或者網絡波動導致短時間內Kernel UDP socket buffer被填滿,也會出現接收失敗

解決方案

  • 網上看了一下,有的建議擴大Kernel UDP socket buffer,比如50MB
    1
    2
    
    sysctl -w net.core.rmem_max=52428800
    sysctl -w net.core.netdev_max_backlog=2000
    

但這只能在一定程度上避免波動的問題,如果發送速度大於接收速度,再大的緩存總會有滿的時候

  • 用NIO重寫flume SyslogUDPSource,提高處理效率,目前並沒有這麼做的打算,因爲採取了下一個方案

  • 部署syslog-ng接收udp請求,並轉發到flume tcp source。Syslog-ng是一個輕量框架,並不需要對數據進行過多的處理和緩存,可以直接對udp請求進行轉發,並且使用的是多路複用的NIO,因此處理效率很高。即使是這樣,經過壓力測試發現也同樣是有瓶頸,當qps大於24000時開始出現同樣的packet receive errors,因爲無論如何syslog-ng也是有處理上限的

    1
    2
    
    2.5W QPS,丟包率0.008%
    10W QPS,丟包率2.2%
    
  • 以上兩種方案在數據量大到一定程度的時候都不可避免的丟包,所以如果可以的話,應該在數據發送之前就進行必要的過濾,把不需要的數據扔掉,降低請求數

  • 最終的解決方案,也是我最推崇的:

放棄UDP,改用TCP

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章