2021-05-12 14:32:11
淺談UDP(封包長度,收包能力,丟包及進程結構選擇)
UDP封包長度
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層和資料鏈路層協定的制約。
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封包處理過程中的丟包,主要原因有兩個:
1、udp封包格式錯誤或校驗和檢查失敗。
2、應用程式來不及處理udp封包。
對於原因1,udp封包本身的錯誤很少見,應用程式也不可控,本文不討論。
首先介紹通用的udp丟包檢測方法,使用netstat命令,加-su引數。
# 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丟包的常見原因:
1、linux核心socket緩衝區設的太小
# cat /proc/sys/net/core/rmem_default
# cat /proc/sys/net/core/rmem_max
可以檢視socket緩衝區的預設值和最大值。
rmem_default和rmem_max設定為多大合適呢?如果伺服器的效能壓力不大,對處理時延也沒有很嚴格的要求,設定為1M左右即可。如果伺服器的效能壓力較大,或者對處理時延有很嚴格的要求,則必須謹慎設定rmem_default 和rmem_max,如果設得過小,會導致丟包,如果設得過大,會出現滾雪球。
2、伺服器負載過高,佔用了大量cpu資源,無法及時處理linux核心socket緩衝區中的udp封包,導致丟包。
一般來說,伺服器負載過高有兩個原因:收到的udp包過多;伺服器進程存在效能瓶頸。如果收到的udp包過多,就要考慮擴容了。伺服器進程存在效能瓶頸屬於效能優化的範疇,這裡不作過多討論。
3、磁碟IO忙
伺服器有大量IO操作,會導致進程阻塞,cpu都在等待磁碟IO,不能及時處理核心socket緩衝區中的udp封包。如果業務本身就是IO密集型的,要考慮在架構上進行優化,合理使用快取降低磁碟IO。
這裡有一個容易忽視的問題:很多伺服器都有在本地磁碟記錄紀錄檔的功能,由於運維誤操作導致紀錄檔記錄的級別過高,或者某些錯誤突然大量出現,使得往磁碟寫紀錄檔的IO請求量很大,磁碟IO忙,導致udp丟包。
對於運維誤操作,可以加強運營環境的管理,防止出錯。如果業務確實需要記錄大量的紀錄檔,可以使用記憶體log或者遠端log。
4、實體記憶體不夠用,出現swap交換
swap交換本質上也是一種磁碟IO忙,因為比較特殊,容易被忽視,所以單列出來。
只要規劃好實體記憶體的使用,並且合理設定系統引數,可以避免這個問題。
5)磁碟滿導致無法IO
沒有規劃好磁碟的使用,監控不到位,導致磁碟被寫滿後伺服器進程無法IO,處於阻塞狀態。最根本的辦法是規劃好磁碟的使用,防止業務資料或紀錄檔檔案把磁碟塞滿,同時加強監控,例如開發一個通用的工具,當磁碟使用率達到80%時就持續告警,留出充足的反應時間。
UDP收包能力測試
測試環境
處理器:Intel(R) Xeon(R) CPU X3440 @ 2.53GHz,4核,8超執行緒,千兆乙太網卡,8G記憶體
模型1
單機,單執行緒非同步UDP服務,無業務邏輯,只有收包操作,除UDP包頭外,一個位元組資料。
測試結果
進程個數 |
1 |
2 |
4 |
8 |
平均處理速度(包/秒) |
791676.1 |
1016197 |
1395040 |
1491744 |
網絡卡流量(Mb/s) |
514.361 |
713.786 |
714.375 |
714.036 |
CPU占用情況(%) |
100 |
200 |
325 |
370 |
現象:
1、單機UDP收包處理能力可以每秒達到150w左右。
2、處理能力隨著進程個數的增加而增強。
3、在處理達到峰值時,CPU資源並未耗盡。
結論:
1、UDP的處理能力還是非常可觀的。
2、對於現象2和現象3,可以看出,效能的瓶頸在網絡卡,而不在CPU,CPU的增加,處理能力的上升,來源於丟包(UDP_ERROR)個數的減少。
模型2
其他測試條件同模型1,除UDP包頭外,一百個位元組資料。
測試結果
進程個數 |
1 |
2 |
4 |
8 |
平均處理速度(包/秒) |
571433.4 |
752319.9 |
731545.6 |
751922.5 |
網絡卡流量(Mb/s) |
855.482 |
855.542 |
855.546 |
855.549 |
CPU占用情況(%) |
100 |
112.9 |
—— |
—— |
現象:
1、100個位元組的包大小,比較符合平常的業務情形。
2、UDP的處理能力還是非常可觀,單機峰值可以到達每秒75w。
3、在4,8個進程時,沒有記錄CPU的占用情況(網絡卡流量耗盡),不過可以肯定的是,CPU未耗盡。
4、隨著進程個數的上升,處理能力沒有明顯提升,但是,丟包(UDP_ERROR)的個數大幅下降。
模型3
單機,單進程,多執行緒非同步UDP服務,多執行緒共用一個fd,無業務邏輯,除UDP包頭外,一個位元組資料。
測試結果:
執行緒個數 |
1 |
2 |
平均處理速度(包/秒) |
791676 |
509868 |
網絡卡流量(Mb/s) |
514.361 |
714.229 |
CPU占用情況(%) |
100 |
150 |
現象:
1、隨著執行緒個數的增加,處理能力不升反降。
結論:
1、多執行緒共用一個fd,會造成相當大的鎖爭用。
2、多執行緒共用一個fd,當有包來時,會啟用所有的執行緒,導致頻繁的上下文切換。
最終結論:
1、UDP處理能力非常可觀,在日常的業務情形中,UDP一般不會成為效能瓶頸。
2、隨著進程個數的增加,處理能力未明顯上升,但是丟包個數明顯下降。
3、本次測試過程中,瓶頸在網絡卡,而不在CPU。
4、採用多進程監聽不同埠的模型,而不是多進程或多執行緒監聽同一個埠。
總結
UDP封包長度 |
在本機(loopback)傳輸,可以根據需要設定MTU,但記住,UDP最大理論長度65507。 在內網傳輸,最好控制在1472位元組(1500-8-20)。 在internet上傳輸,最好控制在548位元組(576-8-20)以內。 |
UDP收包能力 |
UDP處理能力非常可觀,在日常的業務情形中,UDP一般不會成為效能瓶頸。 隨著進程個數的增加,處理能力未明顯上升,但是丟包個數明顯下降。 採用多進程監聽不同埠的模型,而不是多進程或多執行緒監聽同一個埠。 |
本文永久更新連結地址:http://www.linuxidc.com/Linux/2016-01/127430.htm
相關文章