UDP數據包長度linux
UDP數據包的理論長度編程
udp數據包的理論長度是多少,合適的udp數據包應該是多少呢?從TCP-IP詳解卷一第11章的udp數據包的包頭能夠看出,udp的最大包長度是2^16-1的個字節。因爲udp包頭佔8個字節,而在ip層進行封裝後的ip包頭佔去20字節,因此這個是udp數據包的最大理論長度是2^16-1-8-20=65507。緩存
然而這個只是udp數據包的最大理論長度。首先,咱們知道,TCP/IP一般被認爲是一個四層協議系統,包括鏈路層、網絡層、運輸層、應用層。UDP屬於運輸層,在傳輸過程當中,udp包的總體是做爲下層協議的數據字段進行傳輸的,它的長度大小受到下層ip層和數據鏈路層協議的制約。性能優化
【文章福利】小編推薦本身的linuxC/C++語言交流羣:832218493!整理了一些我的以爲比較好的學習書籍、視頻資料共享在羣文件裏面,有須要的能夠自行添加哦!~服務器
MTU相關概念網絡
以太網(Ethernet)數據幀的長度必須在46-1500字節之間,這是由以太網的物理特性決定的。這個1500字節被稱爲鏈路層的MTU(最大傳輸單元)。因特網協議容許IP分片,這樣就能夠將數據包分紅足夠小的片斷以經過那些最大傳輸單元小於該數據包原始大小的鏈路了。這一分片過程發生在網絡層,它使用的是將分組發送到鏈路上的網絡接口的最大傳輸單元的值。這個最大傳輸單元的值就是MTU(Maximum Transmission Unit)。它是指一種通訊協議的某一層上面所能經過的最大數據包大小(以字節爲單位)。最大傳輸單元這個參數一般與通訊接口有關(網絡接口卡、串口等)。多線程
在因特網協議中,一條因特網傳輸路徑的「路徑最大傳輸單元」被定義爲從源地址到目的地址所通過「路徑」上的全部IP跳的最大傳輸單元的最小值。架構
須要注意的是,loopback的MTU不受上述限制,查看loopback MTU值:運維
[root@bogon ~]# cat /sys/class/net/lo/mtu異步
65536
IP分包udp數據包長度的影響
如上所述,因爲網絡接口卡的制約,mtu的長度被限制在1500字節,這個長度指的是鏈路層的數據區。對於大於這個數值的分組可能被分片,不然沒法發送,而分組交換的網絡是不可靠的,存在着丟包。IP 協議的發送方不作重傳。接收方只有在收到所有的分片後才能 reassemble並送至上層協議處理代碼,不然在應用程序看來這些分組已經被丟棄。
假定同一時刻網絡丟包的機率是均等的,那麼較大的IP datagram必然有更大的機率被丟棄,由於只要丟失了一個fragment,就致使整個IP datagram接收不到。不超過MTU的分組是不存在分片問題的。
MTU的值並不包括鏈路層的首部和尾部的18個字節。因此,這個1500字節就是網絡層IP數據報的長度限制。由於IP數據報的首部爲20字節,因此IP數據報的數據區長度最大爲1480字節。而這個1480字節就是用來放TCP傳來的TCP報文段或UDP傳來的UDP數據報的。又由於UDP數據報的首部8字節,因此UDP數據報的數據區最大長度爲1472字節。這個1472字節就是咱們可使用的字節數。
當咱們發送的UDP數據大於1472的時候會怎樣呢?這也就是說IP數據報大於1500字節,大於MTU。這個時候發送方IP層就須要分片(fragmentation)。把數據報分紅若干片,使每一片都小於MTU。而接收方IP層則須要進行數據報的重組。而更嚴重的是,因爲UDP的特性,當某一片數據傳送中丟失時,接收方便沒法重組數據報。將致使丟棄整個UDP數據報。所以,在普通的局域網環境下,將UDP的數據控制在1472字節如下爲好。
進行Internet編程時則不一樣,由於Internet上的路由器可能會將MTU設爲不一樣的值。若是咱們假定MTU爲1500來發送數據的,而途經的某個網絡的MTU值小於1500字節,那麼系統將會使用一系列的機制來調整MTU值,使數據報可以順利到達目的地。鑑於Internet上的標準MTU值爲576字節,因此在進行Internet的UDP編程時,最好將UDP的數據長度控件在548字節(576-8-20)之內。
UDP丟包
udp丟包是指網卡接收到數據包後,linux內核的tcp/ip協議棧在udp數據包處理過程當中的丟包,主要緣由有兩個:
一、udp數據包格式錯誤或校驗和檢查失敗。
二、應用程序來不及處理udp數據包。
對於緣由1,udp數據包自己的錯誤不多見,應用程序也不可控,本文不討論。
首先介紹通用的udp丟包檢測方法,使用netstat命令,加-su參數。
Udp:
2495354 packets received
2100876 packets to unknown port received.
3596307 packet receive errors
14412863 packets sent
RcvbufErrors: 3596307
SndbufErrors: 0
從上面的輸出中,能夠看到有一行輸出包含了"packet receive errors",若是每隔一段時間執行netstat -su,發現行首的數字不斷變大,代表發生了udp丟包。
下面介紹一下應用程序來不及處理而致使udp丟包的常見緣由:
一、linux內核socket緩衝區設的過小 # cat /proc/sys/net/core/rmem_default
能夠查看socket緩衝區的缺省值和最大值。
rmem_default和rmem_max設置爲多大合適呢?若是服務器的性能壓力不大,對處理時延也沒有很嚴格的要求,設置爲1M左右便可。若是服務器的性能壓力較大,或者對處理時延有很嚴格的要求,則必須謹慎設置rmem_default 和rmem_max,若是設得太小,會致使丟包,若是設得過大,會出現滾雪球。
二、服務器負載太高,佔用了大量cpu資源,沒法及時處理linux內核socket緩衝區中的udp數據包,致使丟包。
通常來講,服務器負載太高有兩個緣由:收到的udp包過多;服務器進程存在性能瓶頸。若是收到的udp包過多,就要考慮擴容了。服務器進程存在性能瓶頸屬於性能優化的範疇,這裏不做過多討論。
三、磁盤IO忙
服務器有大量IO操做,會致使進程阻塞,cpu都在等待磁盤IO,不能及時處理內核socket緩衝區中的udp數據包。若是業務自己就是IO密集型的,要考慮在架構上進行優化,合理使用緩存下降磁盤IO。
這裏有一個容易忽視的問題:不少服務器都有在本地磁盤記錄日誌的功能,因爲運維誤操做致使日誌記錄的級別太高,或者某些錯誤忽然大量出現,使得往磁盤寫日誌的IO請求量很大,磁盤IO忙,致使udp丟包。
對於運維誤操做,能夠增強運營環境的管理,防止出錯。若是業務確實須要記錄大量的日誌,可使用內存log或者遠程log。
四、物理內存不夠用,出現swap交換
swap交換本質上也是一種磁盤IO忙,由於比較特殊,容易被忽視,因此單列出來。
只要規劃好物理內存的使用,而且合理設置系統參數,能夠避免這個問題。
5)磁盤滿致使沒法IO
沒有規劃好磁盤的使用,監控不到位,致使磁盤被寫滿後服務器進程沒法IO,處於阻塞狀態。最根本的辦法是規劃好磁盤的使用,防止業務數據或日誌文件把磁盤塞滿,同時增強監控,例如開發一個通用的工具,當磁盤使用率達到80%時就持續告警,留出充足的反應時間。
UDP收包能力測試
測試環境
處理器:Intel(R) Xeon(R) CPU X3440 @ 2.53GHz,4核,8超線程,千兆以太網卡,8G內存
模型1
單機,單線程異步UDP服務,無業務邏輯,只有收包操做,除UDP包頭外,一個字節數據。
測試結果
現象:
一、單機UDP收包處理能力能夠每秒達到150w左右。
二、處理能力隨着進程個數的增長而加強。
三、在處理達到峯值時,CPU資源並未耗盡。
結論:
一、UDP的處理能力仍是很是可觀的。
二、對於現象2和現象3,能夠看出,性能的瓶頸在網卡,而不在CPU,CPU的增長,處理能力的上升,來源於丟包(UDP_ERROR)個數的減小。
模型2
其餘測試條件同模型1,除UDP包頭外,一百個字節數據。
測試結果
現象:
一、100個字節的包大小,比較符合日常的業務情形。
二、UDP的處理能力仍是很是可觀,單機峯值能夠到達每秒75w。
三、在4,8個進程時,沒有記錄CPU的佔用狀況(網卡流量耗盡),不過能夠確定的是,CPU未耗盡。
四、隨着進程個數的上升,處理能力沒有明顯提高,可是,丟包(UDP_ERROR)的個數大幅降低。
模型3
單機,單進程,多線程異步UDP服務,多線程共用一個fd,無業務邏輯,除UDP包頭外,一個字節數據。
測試結果:
現象:
一、隨着線程個數的增長,處理能力不升反降。
結論:
一、多線程共用一個fd,會形成至關大的鎖爭用。
二、多線程共用一個fd,當有包來時,會激活全部的線程,致使頻繁的上下文切換。
最終結論:
一、UDP處理能力很是可觀,在平常的業務情形中,UDP通常不會成爲性能瓶頸。
二、隨着進程個數的增長,處理能力未明顯上升,可是丟包個數明顯降低。
三、本次測試過程當中,瓶頸在網卡,而不在CPU。
四、採用多進程監聽不一樣端口的模型,而不是多進程或多線程監聽同一個端口。
總結