引言
本期分享一個(gè)比較常見(jiàn)的?絡(luò)問(wèn)題--丟包。例如我們?nèi)?a href="http://ttokpm.com/tags/pi/" target="_blank">ping?個(gè)?站,如果能ping通,且?站返回信息全?,則說(shuō)明與?站服務(wù)器的通信是暢通的,如果ping不通,或者?站返回的信息不全等,則很可能是數(shù)據(jù)被丟包了,類(lèi)似情況想必?家都不陌?。針對(duì)?絡(luò)丟包,本?提供?些常見(jiàn)的丟包故障定位?法,希望能夠幫助?家對(duì)?絡(luò)丟包有更多的認(rèn)識(shí),遇到丟包莫要慌,且跟著?起來(lái)漲姿(知)勢(shì)(識(shí))···
什么是丟包
數(shù)據(jù)在Internet上是以數(shù)據(jù)包為單位傳輸?shù)?,單位為字?jié),數(shù)據(jù)在?絡(luò)上傳輸,受?絡(luò)設(shè)備,?絡(luò)質(zhì)量等原因的影響,使得接收到的數(shù)據(jù)?于發(fā)送出去的數(shù)據(jù),造成丟包。
數(shù)據(jù)包接收、發(fā)送原理
發(fā)送數(shù)據(jù)包:
1.應(yīng)?程序的數(shù)據(jù)包,在TCP層增加TCP報(bào)?頭,形成可傳輸?shù)臄?shù)據(jù)包。
2.在IP層增加IP報(bào)頭,形成IP報(bào)?。
3.經(jīng)過(guò)數(shù)據(jù)?卡驅(qū)動(dòng)程序?qū)P包再添加14字節(jié)的MAC頭,構(gòu)成frame(暫?CRC),frame(暫?CRC)中含有發(fā)送端和接收端的MAC地址。
4.驅(qū)動(dòng)程序?qū)rame(暫?CRC)拷貝到?卡的緩沖區(qū),由?卡處理。
5.?卡為frame(暫?CRC)添加頭部同步信息和CRC校驗(yàn),將其封裝為可以發(fā)送的packet,然后再發(fā)送到?線(xiàn)上,這樣說(shuō)就完成了?個(gè)IP報(bào)?的發(fā)送了,所有連接到這個(gè)?線(xiàn)上的?卡都可以看到該packet。
接收數(shù)據(jù)包:
1.?卡收到?線(xiàn)上的packet,?先檢查packet的CRC校驗(yàn),保證完整性,然后將packet頭去掉,得到frame。(?卡會(huì)檢查MAC包內(nèi)的?的MAC地址是否和本?卡的MAC地址?樣,不?樣則會(huì)丟棄。)
2.?卡將frame拷貝到預(yù)分配的ring buffer緩沖。
3.?卡驅(qū)動(dòng)程序通知內(nèi)核處理,經(jīng)過(guò)TCP/IP協(xié)議棧層層解碼處理。
4.應(yīng)?程序從socket buffer 中讀取數(shù)據(jù)。
核心思路
了解了收發(fā)包的原理,可以了解到丟包原因主要會(huì)涉及?卡設(shè)備、?卡驅(qū)動(dòng)、內(nèi)核協(xié)議棧三?類(lèi)。以下我們將遵循“從下到上分層分析(各層可能性出現(xiàn)的丟包場(chǎng)景),然后查看關(guān)鍵信息,最終得出分析結(jié)果”的原則展開(kāi)介紹。
目錄--網(wǎng)絡(luò)丟包情形概覽
> 硬件網(wǎng)卡丟包
> 網(wǎng)卡驅(qū)動(dòng)丟包
> 以太網(wǎng)鏈路層丟包
> 網(wǎng)絡(luò)IP層丟包
> 傳輸層UDP/TCP丟包
> 應(yīng)用層socket丟包
針對(duì)以上6種情形,分別作出如下詳述~
硬件網(wǎng)卡丟包
Ring Buffer溢出
如圖所示,物理介質(zhì)上的數(shù)據(jù)幀到達(dá)后首先由NIC(網(wǎng)絡(luò)適配器)讀取,寫(xiě)入設(shè)備內(nèi)部緩沖區(qū)Ring Buffer中,再由中斷處理程序觸發(fā)Softirq從中消費(fèi),Ring Buffer的大小因網(wǎng)卡設(shè)備而異。當(dāng)網(wǎng)絡(luò)數(shù)據(jù)包到達(dá)(生產(chǎn))的速率快于內(nèi)核處理(消費(fèi))的速率時(shí),Ring Buffer很快會(huì)被填滿(mǎn),新來(lái)的數(shù)據(jù)包將被丟棄;
查看:
通過(guò)ethtool或/proc/net/dev可以查看因Ring Buffer滿(mǎn)而丟棄的包統(tǒng)計(jì),在統(tǒng)計(jì)項(xiàng)中以fifo標(biāo)識(shí):
$ ethtool -S eth0|grep rx_fiforx_fifo_errors: 0$ cat /proc/net/devInter-|Receive|Transmitface|bytespacketserrsdropfifoframecompressedmulticast|bytes packets errs drop fifo colls carrier compressedeth0: 17253386680731 42839525880 0 0 0 0 0 244182022 14879545018057 41657801805 0 0 0 0 0 0#查看eth0網(wǎng)卡RingBuffer最大值和當(dāng)前設(shè)置
$ ethtool -g eth0解決方案:修改網(wǎng)卡eth0接收與發(fā)送硬件緩存區(qū)大小
$ ethtool -G eth0 rx 4096 tx 4096
網(wǎng)卡端口協(xié)商丟包
1. 查看網(wǎng)卡丟包統(tǒng)計(jì):ethtool -S eth1/eth0
2. 查看網(wǎng)卡配置狀態(tài):ethtool eth1/eth0
主要查看網(wǎng)卡和上游網(wǎng)絡(luò)設(shè)備協(xié)商速率和模式是否符合預(yù)期;
解決方案:
1 重新自協(xié)商: ethtool -r eth1/eth0;
2 如果上游不支持自協(xié)商,可以強(qiáng)制設(shè)置端口速率:
ethtool -s eth1 speed 1000 duplex full autoneg off
網(wǎng)卡流控丟包
1. 查看流控統(tǒng)計(jì):
ethtool -S eth1 | grep control
rx_flow_control_xon是在網(wǎng)卡的RX Buffer滿(mǎn)或其他網(wǎng)卡內(nèi)部的資源受限時(shí),給交換機(jī)端口發(fā)送的開(kāi)啟流控的pause幀計(jì)數(shù)。對(duì)應(yīng)的,tx_flow_control_xoff是在資源可用之后發(fā)送的關(guān)閉流控的pause幀計(jì)數(shù)。
2 .查看網(wǎng)絡(luò)流控配置:ethtool -a eth1
解決方案:關(guān)閉網(wǎng)卡流控
ethtool -A ethx autoneg off //自協(xié)商關(guān)閉ethtool -A ethx tx off //發(fā)送模塊關(guān)閉ethtool -A ethx rx off //接收模塊關(guān)閉
報(bào)文mac地址丟包
一般計(jì)算機(jī)網(wǎng)卡都工作在非混雜模式下,此時(shí)網(wǎng)卡只接受來(lái)自網(wǎng)絡(luò)端口的目的地址指向自己的數(shù)據(jù),如果報(bào)文的目的mac地址不是對(duì)端的接口的mac地址,一般都會(huì)丟包,一般這種情況很有可能是源端設(shè)置靜態(tài)arp表項(xiàng)或者動(dòng)態(tài)學(xué)習(xí)的arp表項(xiàng)沒(méi)有及時(shí)更新,但目的端mac地址已發(fā)生變化(換了網(wǎng)卡),沒(méi)有更新通知到源端(比如更新報(bào)文被丟失,中間交換機(jī)異常等情況);
查看:
1.目的端抓包,tcpdump可以開(kāi)啟混雜模式,可以抓到對(duì)應(yīng)的報(bào)文,然后查看mac地址;
2.源端查看arp表或者抓包(上一跳設(shè)備),看發(fā)送的mac地址是否和下一跳目的端的mac地址一致;
解決方案:
1.刷新arp表然后發(fā)包觸發(fā)arp重新學(xué)習(xí)(可能影響其他報(bào)文,增加延時(shí),需要小心操作);
2.可以在源端手動(dòng)設(shè)置正確的靜態(tài)的arp表項(xiàng);
其他網(wǎng)卡異常丟包
這類(lèi)異常比少見(jiàn),但如果都不是上面哪些情況,但網(wǎng)卡統(tǒng)計(jì)里面任然有丟包計(jì)數(shù),可以試著排查一下:
網(wǎng)卡firmware版本:
排查一下網(wǎng)卡phy芯片firmware是不是有bug,安裝的版本是不是符合預(yù)期,查看 ethtool -i eth1:
和廠家提case詢(xún)問(wèn)是不是已知問(wèn)題,有沒(méi)有新版本等;
網(wǎng)線(xiàn)接觸不良:
如果網(wǎng)卡統(tǒng)計(jì)里面存在crc error 計(jì)數(shù)增長(zhǎng),很可能是網(wǎng)線(xiàn)接觸不良,可以通知網(wǎng)管排查一下:
ethtool -S eth0
解決方案:一般試著重新插拔一下網(wǎng)線(xiàn),或者換一根網(wǎng)線(xiàn),排查插口是否符合端口規(guī)格等;
報(bào)文長(zhǎng)度丟包
網(wǎng)卡有接收正確報(bào)文長(zhǎng)度范圍,一般正常以太網(wǎng)報(bào)文長(zhǎng)度范圍:64-1518,發(fā)送端正常情況會(huì)填充或者分片來(lái)適配,偶爾會(huì)發(fā)生一些異常情況導(dǎo)致發(fā)送報(bào)文不正常丟包;
查看:
ethtool-Seth1|greplength_errors
解決方案:
1 調(diào)整接口MTU配置,是否開(kāi)啟支持以太網(wǎng)巨幀;
2 發(fā)送端開(kāi)啟PATH MTU進(jìn)行合理分片;
簡(jiǎn)單總結(jié)一下網(wǎng)卡丟包:
網(wǎng)卡驅(qū)動(dòng)丟包
查看:ifconfig eth1/eth0 等接口
1.RX errors: 表示總的收包的錯(cuò)誤數(shù)量,還包括too-long-frames錯(cuò)誤,Ring Buffer 溢出錯(cuò)誤,crc 校驗(yàn)錯(cuò)誤,幀同步錯(cuò)誤,fifo overruns 以及 missed pkg 等等。
2.RX dropped: 表示數(shù)據(jù)包已經(jīng)進(jìn)入了 Ring Buffer,但是由于內(nèi)存不夠等系統(tǒng)原因,導(dǎo)致在拷貝到內(nèi)存的過(guò)程中被丟棄。
3.RX overruns: 表示了 fifo 的 overruns,這是由于 Ring Buffer(aka Driver Queue) 傳輸?shù)?IO 大于 kernel 能夠處理的 IO 導(dǎo)致的,而 Ring Buffer 則是指在發(fā)起 IRQ 請(qǐng)求之前的那塊 buffer。很明顯,overruns 的增大意味著數(shù)據(jù)包沒(méi)到 Ring Buffer 就被網(wǎng)卡物理層給丟棄了,而 CPU 無(wú)法即使的處理中斷是造成 Ring Buffer 滿(mǎn)的原因之一,上面那臺(tái)有問(wèn)題的機(jī)器就是因?yàn)?interruprs 分布的不均勻(都?jí)涸?core0),沒(méi)有做 affinity 而造成的丟包。
4. RX frame: 表示 misaligned 的 frames。
5. 對(duì)于 TX 的來(lái)說(shuō),出現(xiàn)上述 counter 增大的原因主要包括 aborted transmission, errors due to carrirer, fifo error, heartbeat erros 以及 windown error,而 collisions 則表示由于 CSMA/CD 造成的傳輸中斷。
驅(qū)動(dòng)溢出丟包
netdev_max_backlog是內(nèi)核從NIC收到包后,交由協(xié)議棧(如IP、TCP)處理之前的緩沖隊(duì)列。每個(gè)CPU核都有一個(gè)backlog隊(duì)列,與Ring Buffer同理,當(dāng)接收包的速率大于內(nèi)核協(xié)議棧處理的速率時(shí),CPU的backlog隊(duì)列不斷增長(zhǎng),當(dāng)達(dá)到設(shè)定的netdev_max_backlog值時(shí),數(shù)據(jù)包將被丟棄。
查看:
通過(guò)查看/proc/net/softnet_stat可以確定是否發(fā)生了netdev backlog隊(duì)列溢出:
其中:每一行代表每個(gè)CPU核的狀態(tài)統(tǒng)計(jì),從CPU0依次往下;每一列代表一個(gè)CPU核的各項(xiàng)統(tǒng)計(jì):第一列代表中斷處理程序收到的包總數(shù);第二列即代表由于netdev_max_backlog隊(duì)列溢出而被丟棄的包總數(shù)。從上面的輸出可以看出,這臺(tái)服務(wù)器統(tǒng)計(jì)中,并沒(méi)有因?yàn)閚etdev_max_backlog導(dǎo)致的丟包。
解決方案:
netdev_max_backlog的默認(rèn)值是1000,在高速鏈路上,可能會(huì)出現(xiàn)上述第二統(tǒng)計(jì)不為0的情況,可以通過(guò)修改內(nèi)核參數(shù)net.core.netdev_max_backlog來(lái)解決:
$ sysctl -w net.core.netdev_max_backlog=2000
單核負(fù)載高導(dǎo)致丟包
單核CPU軟中斷占有高, 導(dǎo)致應(yīng)用沒(méi)有機(jī)會(huì)收發(fā)或者收包比較慢,即使調(diào)整netdev_max_backlog隊(duì)列大小仍然會(huì)一段時(shí)間后丟包,處理速度跟不上網(wǎng)卡接收的速度;
查看:mpstat -P ALL 1
單核軟中斷占有100%,導(dǎo)致應(yīng)用沒(méi)有機(jī)會(huì)收發(fā)或者收包比較慢而丟包;
解決方案:
1.調(diào)整網(wǎng)卡RSS隊(duì)列配置:
查看:ethtool -x ethx;
調(diào)整:ethtool -X ethx xxxx;
2.看一下網(wǎng)卡中斷配置是否均衡 cat /proc/interrupts
調(diào)整:
1) irqbalance 調(diào)整;# 查看當(dāng)前運(yùn)行情況serviceirqbalancestatus# 終止服務(wù)service irqbalance stop2) 中斷綁CPU核 echo mask > /proc/irq/xxx/smp_affinity
3.根據(jù)CPU和網(wǎng)卡隊(duì)列個(gè)數(shù)調(diào)整網(wǎng)卡多隊(duì)列和RPS配置
-CPU大于網(wǎng)卡隊(duì)列個(gè)數(shù):
查看網(wǎng)卡隊(duì)列 ethtool -x ethx;
協(xié)議棧開(kāi)啟RPS并設(shè)置RPS;
echo $mask(CPU配置)> /sys/class/net/$eth/queues/rx-$i/rps_cpusecho 4096(網(wǎng)卡buff)> /sys/class/net/$eth/queues/rx-$i/rps_flow_cnt2)CPU小于網(wǎng)卡隊(duì)列個(gè)數(shù),綁中斷就可以,可以試著關(guān)閉RPS看一下效果:echo 0 > /sys/class/net/
4.numa CPU調(diào)整,對(duì)齊網(wǎng)卡位置,可以提高內(nèi)核處理速度,從而給更多CPU給應(yīng)用收包,減緩丟包概率;
查看網(wǎng)卡numa位置:
ethtool -i eth1|grep bus-infolspci -s bus-info -vv|grep node
上面中斷和RPS設(shè)置里面mask需要重新按numa CPU分配重新設(shè)置;
5.可以試著開(kāi)啟中斷聚合(看網(wǎng)卡是否支持)
查看 :
ethtool -c ethxCoalesceparametersforeth1:Adaptive RX: on TX: onstats-block-usecs: 0sample-interval: 0pkt-rate-low: 0pkt-rate-high: 0 rx-usecs: 25rx-frames: 0rx-usecs-irq: 0rx-frames-irq: 256 tx-usecs: 25tx-frames: 0tx-usecs-irq: 0tx-frames-irq: 256 rx-usecs-low: 0rx-frame-low: 0tx-usecs-low: 0tx-frame-low: 0 rx-usecs-high: 0rx-frame-high: 0tx-usecs-high: 0tx-frame-high: 0
調(diào)整:
ethtool -C ethx adaptive-rx on
簡(jiǎn)單總結(jié)一下網(wǎng)卡驅(qū)動(dòng)丟包處理:
內(nèi)核協(xié)議棧丟包
以太網(wǎng)鏈路層丟包
neighbor系統(tǒng)arp丟包
arp_ignore配置丟包
arp_ignore參數(shù)的作用是控制系統(tǒng)在收到外部的arp請(qǐng)求時(shí),是否要返回arp響應(yīng)。arp_ignore參數(shù)常用的取值主要有0,1,2,3~8較少用到;
查看:sysctl -a|grep arp_ignore
解決方案:根據(jù)實(shí)際場(chǎng)景設(shè)置對(duì)應(yīng)值;
0:響應(yīng)任意網(wǎng)卡上接收到的對(duì)本機(jī)IP地址的arp請(qǐng)求(包括環(huán)回網(wǎng)卡上的地址),而不管該目的IP是否在接收網(wǎng)卡上。
1:只響應(yīng)目的IP地址為接收網(wǎng)卡上的本地地址的arp請(qǐng)求。
2:只響應(yīng)目的IP地址為接收網(wǎng)卡上的本地地址的arp請(qǐng)求,并且arp請(qǐng)求的源IP必須和接收網(wǎng)卡同網(wǎng)段。
3:如果ARP請(qǐng)求數(shù)據(jù)包所請(qǐng)求的IP地址對(duì)應(yīng)的本地地址其作用域(scope)為主機(jī)(host),則不回應(yīng)ARP響應(yīng)數(shù)據(jù)包,如果作用域?yàn)槿郑╣lobal)或鏈路(link),則回應(yīng)ARP響應(yīng)數(shù)據(jù)包。
arp_filter配置丟包
在多接口系統(tǒng)里面(比如騰訊云的彈性網(wǎng)卡場(chǎng)景),這些接口都可以回應(yīng)arp請(qǐng)求,導(dǎo)致對(duì)端有可能學(xué)到不同的mac地址,后續(xù)報(bào)文發(fā)送可能由于mac地址和接收?qǐng)?bào)文接口mac地址不一樣而導(dǎo)致丟包,arp_filter主要是用來(lái)適配這種場(chǎng)景;
查看:
sysctl -a | grep arp_filter
解決方案:
根據(jù)實(shí)際場(chǎng)景設(shè)置對(duì)應(yīng)的值,一般默認(rèn)是關(guān)掉此過(guò)濾規(guī)則,特殊情況可以打開(kāi);0:默認(rèn)值,表示回應(yīng)arp請(qǐng)求的時(shí)候不檢查接口情況;1:表示回應(yīng)arp請(qǐng)求時(shí)會(huì)檢查接口是否和接收請(qǐng)求接口一致,不一致就不回應(yīng);
arp表滿(mǎn)導(dǎo)致丟包
比如下面這種情況,由于突發(fā)arp表項(xiàng)很多 超過(guò)協(xié)議棧默認(rèn)配置,發(fā)送報(bào)文的時(shí)候部分arp創(chuàng)建失敗,導(dǎo)致發(fā)送失敗,從而丟包:
查看:
查看arp狀態(tài):cat /proc/net/stat/arp_cache ,table_fulls統(tǒng)計(jì):
查看dmesg消息(內(nèi)核打?。?/p>
dmesg|grep neighbourneighbour:arp_cache:neighbortableoverflow!
查看當(dāng)前arp表大?。篿p n|wc -l
查看系統(tǒng)配額:
sysctl -a |grep net.ipv4.neigh.default.gc_threshgc_thresh1:存在于ARP高速緩存中的最少層數(shù),如果少于這個(gè)數(shù),垃圾收集器將不會(huì)運(yùn)行。缺省值是128。 gc_thresh2 :保存在 ARP 高速緩存中的最多的記錄軟限制。垃圾收集器在開(kāi)始收集前,允許記錄數(shù)超過(guò)這個(gè)數(shù)字 5 秒。缺省值是 512。gc_thresh3 :保存在 ARP 高速緩存中的最多記錄的硬限制,一旦高速緩存中的數(shù)目高于此,垃圾收集器將馬上運(yùn)行。缺省值是1024。
一般在內(nèi)存足夠情況下,可以認(rèn)為gc_thresh3 值是arp 表總大?。?/p>
解決方案:根據(jù)實(shí)際arp最大值情況(比如訪問(wèn)其他子機(jī)最大個(gè)數(shù)),調(diào)整arp表大小
$ sudo sysctl -w net.ipv4.neigh.default.gc_thresh1=1024$ sudo sysctl -w net.ipv4.neigh.default.gc_thresh2=2048$ sudo sysctl -w net.ipv4.neigh.default.gc_thresh3=4096$ sudo sysctl -p
arp請(qǐng)求緩存隊(duì)列溢出丟包
查看:
cat /proc/net/stat/arp_cache ,unresolved_discards是否有新增計(jì)數(shù)
解決方案:根據(jù)客戶(hù)需求調(diào)整緩存隊(duì)列大小unres_qlen_bytes:
網(wǎng)絡(luò)IP層丟包
接口ip地址配置丟包
1. 本機(jī)服務(wù)不通,檢查lo接口有沒(méi)有配置地址是127.0.0.1;
2 .本機(jī)接收失敗, 查看local路由表:ip r show table local|grep 子機(jī)ip地址;這種丟包一般會(huì)出現(xiàn)在多IP場(chǎng)景,子機(jī)底層配置多ip失敗,導(dǎo)致對(duì)應(yīng)ip收不到包而丟包;
解決方案:
1.配置正確接口ip地址;比如ip a add 1.1.1.1 dev eth0
2.如果發(fā)現(xiàn)接口有地址還丟包,可能是local路由表沒(méi)有對(duì)應(yīng)條目,緊急情況下,可以用手工補(bǔ)上:
比如ip r add local 本機(jī)ip地址 dev eth0 table local ;
路由丟包
路由配置丟包
查看:
1.查看配置 路由是否設(shè)置正確(是否可達(dá)),是否配置策略路由(在彈性網(wǎng)卡場(chǎng)景會(huì)出現(xiàn)此配置)ip rule:
然后找到對(duì)應(yīng)路由表。查看路由表:
或者直接用 ip r get x.x.x.x,讓系統(tǒng)幫你查找是否存在可達(dá)路由,接口是否符合預(yù)期;
2.查看系統(tǒng)統(tǒng)計(jì)信息:
netstat -s|grep "dropped because of missing route"
解決方案:重新配置正確的路由;
反向路由過(guò)濾丟包
反向路由過(guò)濾機(jī)制是Linux通過(guò)反向路由查詢(xún),檢查收到的數(shù)據(jù)包源IP是否可路由(Loose mode)、是否最佳路由(Strict mode),如果沒(méi)有通過(guò)驗(yàn)證,則丟棄數(shù)據(jù)包,設(shè)計(jì)的目的是防范IP地址欺騙攻擊。
查看:
rp_filter提供三種模式供配置:
0 - 不驗(yàn)證
1 - RFC3704定義的嚴(yán)格模式:對(duì)每個(gè)收到的數(shù)據(jù)包,查詢(xún)反向路由,如果數(shù)據(jù)包入口和反向路由出口不一致,則不通過(guò)
2 - RFC3704定義的松散模式:對(duì)每個(gè)收到的數(shù)據(jù)包,查詢(xún)反向路由,如果任何接口都不可達(dá),則不通過(guò)
查看當(dāng)前rp_filter策略配置:
$cat /proc/sys/net/ipv4/conf/eth0/rp_filter
如果這里設(shè)置為1,就需要查看主機(jī)的網(wǎng)絡(luò)環(huán)境和路由策略是否可能會(huì)導(dǎo)致客戶(hù)端的入包無(wú)法通過(guò)反向路由驗(yàn)證了。
從原理來(lái)看這個(gè)機(jī)制工作在網(wǎng)絡(luò)層,因此,如果客戶(hù)端能夠Ping通服務(wù)器,就能夠排除這個(gè)因素了。
解決方案:
根據(jù)實(shí)際網(wǎng)絡(luò)環(huán)境將rp_filter設(shè)置為0或2:
$sysctl-wnet.ipv4.conf.all.rp_filter=2或$ sysctl -w net.ipv4.conf.eth0.rp_filter=2
防火墻丟包
客戶(hù)設(shè)置規(guī)則導(dǎo)致丟包
查看:
iptables -nvL |grep DROP ;
解決方案: 修改防火墻規(guī)則;
連接跟蹤導(dǎo)致丟包
連接跟蹤表溢出丟包
kernel 用 ip_conntrack 模塊來(lái)記錄 iptables 網(wǎng)絡(luò)包的狀態(tài),并把每條記錄保存到 table 里(這個(gè) table 在內(nèi)存里,可以通過(guò)/proc/net/ip_conntrack 查看當(dāng)前已經(jīng)記錄的總數(shù)),如果網(wǎng)絡(luò)狀況繁忙,比如高連接,高并發(fā)連接等會(huì)導(dǎo)致逐步占用這個(gè) table 可用空間,一般這個(gè) table 很大不容易占滿(mǎn)并且可以自己清理,table 的記錄會(huì)一直呆在 table 里占用空間直到源 IP 發(fā)一個(gè) RST 包,但是如果出現(xiàn)被攻擊、錯(cuò)誤的網(wǎng)絡(luò)配置、有問(wèn)題的路由/路由器、有問(wèn)題的網(wǎng)卡等情況的時(shí)候,就會(huì)導(dǎo)致源 IP 發(fā)的這個(gè) RST 包收不到,這樣就積累在 table 里,越積累越多直到占滿(mǎn)。無(wú)論,哪種情況導(dǎo)致table變滿(mǎn),滿(mǎn)了以后就會(huì)丟包,出現(xiàn)外部無(wú)法連接服務(wù)器的情況。內(nèi)核會(huì)報(bào)如下錯(cuò)誤信息:kernel: ip_conntrack: table full, dropping packet;
查看當(dāng)前連接跟蹤數(shù) :
cat /proc/sys/net/netfilter/nf_conntrack_max
解決方案:
增大跟蹤的最大條數(shù)net.netfilter.nf_conntrack_max = 3276800減少跟蹤連接的最大有效時(shí)間net.netfilter.nf_conntrack_tcp_timeout_established = 1200net.netfilter.nf_conntrack_udp_timeout_stream = 180net.netfilter.nf_conntrack_icmp_timeout = 30
ct創(chuàng)建沖突失導(dǎo)致丟包
查看:當(dāng)前連接跟蹤統(tǒng)計(jì):cat /proc/net/stat/nf_conntrack,可以查各種ct異常丟包統(tǒng)計(jì)
解決方案:內(nèi)核熱補(bǔ)丁修復(fù)或者更新內(nèi)核版本(合入補(bǔ)丁修改);
傳輸層UDP/TCP丟包
tcp 連接跟蹤安全檢查丟包
丟包原因:由于連接沒(méi)有斷開(kāi),但服務(wù)端或者client之前出現(xiàn)過(guò)發(fā)包異常等情況(報(bào)文沒(méi)有經(jīng)過(guò)連接跟蹤模塊更新窗口計(jì)數(shù)),沒(méi)有更新合法的window范圍,導(dǎo)致后續(xù)報(bào)文安全檢查被丟包;協(xié)議棧用nf_conntrack_tcp_be_liberal 來(lái)控制這個(gè)選項(xiàng):
1:關(guān)閉,只有不在tcp窗口內(nèi)的rst包被標(biāo)志為無(wú)效;
0:開(kāi)啟; 所有不在tcp窗口中的包都被標(biāo)志為無(wú)效;
查看:
查看配置:
sysctl -a|grep nf_conntrack_tcp_be_liberal net.netfilter.nf_conntrack_tcp_be_liberal = 1
查看log:
一般情況下netfiler模塊默認(rèn)沒(méi)有加載log,需要手動(dòng)加載;
modprobe ipt_LOG11sysctl-wnet.netfilter.nf_log.2=ipt_LOG
然后發(fā)包后在查看syslog;
解決方案:根據(jù)實(shí)際抓包分析情況判斷是不是此機(jī)制導(dǎo)致的丟包,可以試著關(guān)閉試一下;
分片重組丟包
情況總結(jié):超時(shí)
查看:
netstat -s|grep timeout601 fragments dropped after timeout
解決方法:調(diào)整超時(shí)時(shí)間
net.ipv4.ipfrag_time = 30sysctl -w net.ipv4.ipfrag_time=60
frag_high_thresh, 分片的內(nèi)存超過(guò)一定閾值會(huì)導(dǎo)致系統(tǒng)安全檢查丟包
查看:
netstat -s|grep reassembles8094 packet reassembles failed
解決方案:調(diào)整大小
net.ipv4.ipfrag_high_thresh net.ipv4.ipfrag_low_thresh
分片安全距檢查離丟包
查看:
netstat -s|grep reassembles8094 packet reassembles failed
解決方案:把ipfrag_max_dist設(shè)置為0,就關(guān)掉此安全檢查
pfrag_max_dist特性,在一些場(chǎng)景下其實(shí)并不適用:
1.有大量的網(wǎng)絡(luò)報(bào)文交互
2.發(fā)送端的并發(fā)度很高,同時(shí)SMP架構(gòu),導(dǎo)致很容易造成這種亂序情況;
分片hash bucket沖突鏈太長(zhǎng)超過(guò)系統(tǒng)默認(rèn)值128
查看:
dmesg|grep“Droppingfragment”inet_frag_find: Fragment hash bucket 128 list length grew over limit. Dropping fragment.
解決方案:熱補(bǔ)丁調(diào)整hash大??;
系統(tǒng)內(nèi)存不足,創(chuàng)建新分片隊(duì)列失敗
查看方法:
netstat-s|grepreassembles8094 packet reassembles failed
dropwatch查看丟包位置 :
解決方案:
a.增大系統(tǒng)網(wǎng)絡(luò)內(nèi)存:
net.core.rmem_default net.core.rmem_max net.core.wmem_default
b.系統(tǒng)回收內(nèi)存:
緊急情況下,可以用/proc/sys/vm/drop_caches, 去釋放一下虛擬內(nèi)存;
To free pagecache:# echo 1 > /proc/sys/vm/drop_cachesTo free dentries and inodes:# echo 2 > /proc/sys/vm/drop_cachesTo free pagecache, dentries and inodes:echo 3 > /proc/sys/vm/drop_caches
MTU丟包
查看:
1.檢查接口MTU配置,ifconfig eth1/eth0,默認(rèn)是1500;
2.進(jìn)行MTU探測(cè),然后設(shè)置接口對(duì)應(yīng)的MTU值;
解決方案:
1. 根據(jù)實(shí)際情況,設(shè)置正確MTU值;
2. 設(shè)置合理的tcp mss,啟用TCP MTU Probe:
cat /proc/sys/net/ipv4/tcp_mtu_probing:tcp_mtu_probing - INTEGER Controls TCP Packetization-Layer Path MTU Discovery.Takes three values:0 - Disabled 1 - Disabled by default, enabled when an ICMP black hole detected2 - Always enabled, use initial MSS of tcp_base_mss.
tcp層丟包
TIME_WAIT過(guò)多丟包
大量TIMEWAIT出現(xiàn),并且需要解決的場(chǎng)景,在高并發(fā)短連接的TCP服務(wù)器上,當(dāng)服務(wù)器處理完請(qǐng)求后立刻按照主動(dòng)正常關(guān)閉連接。。。這個(gè)場(chǎng)景下,會(huì)出現(xiàn)大量socket處于TIMEWAIT狀態(tài)。如果客戶(hù)端的并發(fā)量持續(xù)很高,此時(shí)部分客戶(hù)端就會(huì)顯示連接不上;
查看:
查看系統(tǒng)log :
dmsgTCP: time wait bucket table overflow;
查看系統(tǒng)配置:
sysctl -a|grep tcp_max_tw_bucketsnet.ipv4.tcp_max_tw_buckets = 16384
解決方案:
1. tw_reuse,tw_recycle 必須在客戶(hù)端和服務(wù)端timestamps 開(kāi)啟時(shí)才管用(默認(rèn)打開(kāi))
2. tw_reuse 只對(duì)客戶(hù)端起作用,開(kāi)啟后客戶(hù)端在1s內(nèi)回收;
3. tw_recycle對(duì)客戶(hù)端和服務(wù)器同時(shí)起作用,開(kāi)啟后在3.5*RTO 內(nèi)回收,RTO 200ms~ 120s具體時(shí)間視網(wǎng)絡(luò)狀況。內(nèi)網(wǎng)狀況比tw_reuse稍快,公網(wǎng)尤其移動(dòng)網(wǎng)絡(luò)大多要比tw_reuse 慢,優(yōu)點(diǎn)就是能夠回收服務(wù)端的TIME_WAIT數(shù)量;
在服務(wù)端,如果網(wǎng)絡(luò)路徑會(huì)經(jīng)過(guò)NAT節(jié)點(diǎn),不要啟用net.ipv4.tcp_tw_recycle,會(huì)導(dǎo)致時(shí)間戳混亂,引起其他丟包問(wèn)題;
4. 調(diào)整tcp_max_tw_buckets大小,如果內(nèi)存足夠:
sysctl -w net.ipv4.tcp_max_tw_buckets=163840;
時(shí)間戳異常丟包
當(dāng)多個(gè)客戶(hù)端處于同一個(gè)NAT環(huán)境時(shí),同時(shí)訪問(wèn)服務(wù)器,不同客戶(hù)端的時(shí)間可能不一致,此時(shí)服務(wù)端接收到同一個(gè)NAT發(fā)送的請(qǐng)求,就會(huì)出現(xiàn)時(shí)間戳錯(cuò)亂的現(xiàn)象,于是后面的數(shù)據(jù)包就被丟棄了,具體的表現(xiàn)通常是是客戶(hù)端明明發(fā)送的SYN,但服務(wù)端就是不響應(yīng)ACK。在服務(wù)器借助下面的命令可以來(lái)確認(rèn)數(shù)據(jù)包是否有不斷被丟棄的現(xiàn)象。
檢查:
netstat -s | grep rejects
解決方案:
如果網(wǎng)絡(luò)路徑會(huì)經(jīng)過(guò)NAT節(jié)點(diǎn),不要啟用net.ipv4.tcp_tw_recycle;
TCP隊(duì)列問(wèn)題導(dǎo)致丟包
原理:
tcp狀態(tài)機(jī)(三次握手)
協(xié)議處理:
一個(gè)是半連接隊(duì)列(syn queue):
在三次握手協(xié)議中,服務(wù)器維護(hù)一個(gè)半連接隊(duì)列,該隊(duì)列為每個(gè)客戶(hù)端的SYN包開(kāi)設(shè)一個(gè)條目(服務(wù)端在接收到SYN包的時(shí)候,就已經(jīng)創(chuàng)建了request_sock結(jié)構(gòu),存儲(chǔ)在半連接隊(duì)列中),該條目表明服務(wù)器已收到SYN包,并向客戶(hù)發(fā)出確認(rèn),正在等待客戶(hù)的確認(rèn)包(會(huì)進(jìn)行第二次握手發(fā)送SYN+ACK的包加以確認(rèn))。這些條目所標(biāo)識(shí)的連接在服務(wù)器處于Syn_RECV狀態(tài),當(dāng)服務(wù)器收到客戶(hù)的確認(rèn)包時(shí),刪除該條目,服務(wù)器進(jìn)入ESTABLISHED狀態(tài)。該隊(duì)列為SYN隊(duì)列,長(zhǎng)度為max(64,/proc/sys/net/ipv4/tcp_max_syn_backlog), 機(jī)器的tcp_max_syn_backlog值在/proc/sys/net/ipv4/tcp_max_syn_backlog下配置;
一個(gè)是全連接隊(duì)列(accept queue):
第三次握手時(shí),當(dāng)server接收到ACK 報(bào)之后, 會(huì)進(jìn)入一個(gè)新的叫 accept 的隊(duì)列,該隊(duì)列的長(zhǎng)度為 min(backlog, somaxconn),默認(rèn)情況下,somaxconn 的值為 128,表示最多有 129 的 ESTAB 的連接等待 accept(),而 backlog 的值則應(yīng)該是由 int listen(int sockfd, int backlog) 中的第二個(gè)參數(shù)指定,listen 里面的 backlog 可以有我們的應(yīng)用程序去定義的;
查看:
連接建立失敗,syn丟包:
netstat -s |grep -i listenSYNs to LISTEN sockets dropped
也會(huì)受到連接滿(mǎn)丟包影響
解決方案:增加大小 tcp_max_syn_backlog
連接滿(mǎn)丟包
-xxx times the listen queue of a socket overflowed
查看:
查看accept隊(duì)列大小 :net.core.somaxconn
ss -lnt查詢(xún)socket隊(duì)列 :LISTEN 狀態(tài): Recv-Q 表示的當(dāng)前等待服務(wù)端調(diào)用 accept 完成三次握手的 listen backlog 數(shù)值,也就是說(shuō),當(dāng)客戶(hù)端通過(guò) connect() 去連接正在 listen() 的服務(wù)端時(shí),這些連接會(huì)一直處于這個(gè) queue 里面直到被服務(wù)端 accept();Send-Q 表示的則是最大的 listen backlog 數(shù)值,這就就是上面提到的 min(backlog, somaxconn) 的值,
看一下是不是應(yīng)用程序設(shè)置限制, int listen(int sockfd, int backlog);
解決方案:
Linux內(nèi)核參進(jìn)行優(yōu)化,可以緩解壓力 tcp_abort_on_overflow=1
調(diào)整net.core.somaxconn大小;
應(yīng)用程序設(shè)置問(wèn)題,通知客戶(hù)程序修改;
syn flood攻擊丟包
目前,Linux下默認(rèn)會(huì)進(jìn)行5次重發(fā)SYN-ACK包,重試的間隔時(shí)間從1s開(kāi)始,下次的重試間隔時(shí)間是前一次的雙倍,5次的重試時(shí)間間隔為1s, 2s, 4s, 8s, 16s,總共31s,第5次發(fā)出后還要等32s都知道第5次也超時(shí)了,所以,總共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s,TCP才會(huì)把斷開(kāi)這個(gè)連接。由于,SYN超時(shí)需要63秒,那么就給攻擊者一個(gè)攻擊服務(wù)器的機(jī)會(huì),攻擊者在短時(shí)間內(nèi)發(fā)送大量的SYN包給Server(俗稱(chēng) SYN flood 攻擊),用于耗盡Server的SYN隊(duì)列。對(duì)于應(yīng)對(duì)SYN 過(guò)多的問(wèn)題;
查看: 查看syslog: kernel: [3649830.269068] TCP: Possible SYN flooding on port xxx. Sending cookies. Check SNMP counters.
解決方案:
增大tcp_max_syn_backlog
減少tcp_synack_retries
啟用tcp_syncookies
啟用tcp_abort_on_overflow,tcp_abort_on_overflow修改成 1,1表示第三步的時(shí)候如果全連接隊(duì)列滿(mǎn)了,server發(fā)送一個(gè)reset包給client,表示廢掉這個(gè)握手過(guò)程和這個(gè)連接(本來(lái)在server端這個(gè)連接就還沒(méi)建立起來(lái));
PAWS機(jī)制丟包
原理:PAWS(Protect Against Wrapped Sequence numbers),高帶寬下,TCP序列號(hào)可能在較短的時(shí)間內(nèi)就被重復(fù)使用(recycle/wrapped)
就可能導(dǎo)致同一條TCP流在短時(shí)間內(nèi)出現(xiàn)序號(hào)一樣的兩個(gè)合法的數(shù)據(jù)包及其確認(rèn)包。
查看:
$netstat-s|grep-e"passiveconnectionsrejectedbecauseoftimestamp" -e "packets rejects in established connections because of timestamp” 387158 passive connections rejected because of time stamp825313 packets rejects in established connections because of timestamp
通過(guò)sysctl查看是否啟用了tcp_tw_recycle及tcp_timestamp:
$ sysctl net.ipv4.tcp_tw_recyclenet.ipv4.tcp_tw_recycle = 1 $ sysctl net.ipv4.tcp_timestampsnet.ipv4.tcp_timestamps = 1
1. tcp_tw_recycle參數(shù)。它用來(lái)快速回收TIME_WAIT連接,不過(guò)如果在NAT環(huán)境下會(huì)引發(fā)問(wèn)題;
2. 當(dāng)多個(gè)客戶(hù)端通過(guò)NAT方式聯(lián)網(wǎng)并與服務(wù)端交互時(shí),服務(wù)端看到的是同一個(gè)IP,也就是說(shuō)對(duì)服務(wù)端而言這些客戶(hù)端實(shí)際上等同于一個(gè),可惜由于這些客戶(hù)端的時(shí)間戳可能存在差異,于是乎從服務(wù)端的視角看,便可能出現(xiàn)時(shí)間戳錯(cuò)亂的現(xiàn)象,進(jìn)而直接導(dǎo)致時(shí)間戳小的數(shù)據(jù)包被丟棄。如果發(fā)生了此類(lèi)問(wèn)題,具體的表現(xiàn)通常是是客戶(hù)端明明發(fā)送的SYN,但服務(wù)端就是不響應(yīng)ACK。
解決方案:
在NAT環(huán)境下,清除tcp時(shí)間戳選項(xiàng),或者不開(kāi)啟tcp_tw_recycle參數(shù);
TLP問(wèn)題丟包
TLP主要是為了解決尾丟包重傳效率的問(wèn)題,TLP能夠有效的避免較長(zhǎng)的RTO超時(shí),進(jìn)而提高TCP性能,詳細(xì)參考文章:
http://perthcharles.github.io/2015/10/31/wiki-network-tcp-tlp/;
但在低時(shí)延場(chǎng)景下(短連接小包量),TLP與延遲ACK組合可能會(huì)造成無(wú)效重傳,導(dǎo)致客戶(hù)端感發(fā)現(xiàn)大量假重傳包,加大了響應(yīng)延遲;
查看:
查看協(xié)議棧統(tǒng)計(jì):
netstat -s |grep TCPLossProbes
查看系統(tǒng)配置:
sysctl -a | grep tcp_early_retrans
解決方案:
1.關(guān)掉延遲ack,打開(kāi)快速ack;
2.linux實(shí)現(xiàn)nodelay語(yǔ)意不是快速ack,只是關(guān)閉nagle算法;
3.打開(kāi)快速ack選項(xiàng),socket里面有個(gè) TCP_QUICKACK 選項(xiàng),需要每次recv后再設(shè)置一次。
內(nèi)存不足導(dǎo)致丟包
查看:
查看log:
dmesg|grep“outofmemory”
查看系統(tǒng)配置:
cat /proc/sys/net/ipv4/tcp_memcat /proc/sys/net/ipv4/tcp_rmemcat /proc/sys/net/ipv4/tcp_wmem
解決方案:
根據(jù)TCP業(yè)務(wù)并發(fā)流量,調(diào)整系統(tǒng)參數(shù),一般試著增大2倍或者其他倍數(shù)來(lái)看是否緩解;
sysclt -w net.ipv4.tcp_mem=sysclt -w net.ipv4.tcp_wmem=sysclt -w net.ipv4.tcp_rmem=sysctl -p
TCP超時(shí)丟包
查看:
抓包分析一下網(wǎng)絡(luò)RTT:
用其他工具測(cè)試一下當(dāng)前端到端網(wǎng)絡(luò)質(zhì)量(hping等);
# hping -S 9.199.10.104 -AHPING 9.199.10.104 (bond1 9.199.10.104): SA set, 40 headers + 0 data byteslen=46 ip=9.199.10.104 ttl=53 DF id=47617 sport=0 flags=R seq=0 win=0 rtt=38.3 mslen=46 ip=9.199.10.104 ttl=53 DF id=47658 sport=0 flags=R seq=1 win=0 rtt=38.3 mslen=46 ip=9.199.10.104 ttl=53 DF id=47739 sport=0 flags=R seq=2 win=0 rtt=30.4 mslen=46 ip=9.199.10.104 ttl=53 DF id=47842 sport=0 flags=R seq=3 win=0 rtt=30.4 mslen=46 ip=9.199.10.104 ttl=53 DF id=48485 sport=0 flags=R seq=4 win=0 rtt=38.7 mslen=46 ip=9.199.10.104 ttl=53 DF id=49274 sport=0 flags=R seq=5 win=0 rtt=34.1 mslen=46 ip=9.199.10.104 ttl=53 DF id=49491 sport=0 flags=R seq=6 win=0 rtt=30.3 ms
解決方案:
關(guān)閉Nagle算法,減少小包延遲;
關(guān)閉延遲ack:
sysctl -w net.ipv4.tcp_no_delay_ack=1
TCP亂序丟包
此時(shí)TCP會(huì)無(wú)法判斷是數(shù)據(jù)包丟失還是亂序,因?yàn)閬G包和亂序都會(huì)導(dǎo)致接收端收到次序混亂的數(shù)據(jù)包,造成接收端的數(shù)據(jù)空洞。TCP會(huì)將這種情況暫定為數(shù)據(jù)包的亂序,因?yàn)閬y序是時(shí)間問(wèn)題(可能是數(shù)據(jù)包的遲到),而丟包則意味著重傳。當(dāng)TCP意識(shí)到包出現(xiàn)亂序的情況時(shí),會(huì)立即ACK,該ACK的TSER部分包含的TSEV值會(huì)記錄當(dāng)前接收端收到有序報(bào)文段的時(shí)刻。這會(huì)使得數(shù)據(jù)包的RTT樣本值增大,進(jìn)一步導(dǎo)致RTO時(shí)間延長(zhǎng)。這對(duì)TCP來(lái)說(shuō)無(wú)疑是有益的,因?yàn)門(mén)CP有充分的時(shí)間判斷數(shù)據(jù)包到底是失序還是丟了來(lái)防止不必要的數(shù)據(jù)重傳。當(dāng)然嚴(yán)重的亂序則會(huì)讓發(fā)送端以為是丟包一旦重復(fù)的ACK超過(guò)TCP的閾值,便會(huì)觸發(fā)超時(shí)重傳機(jī)制,以及時(shí)解決這種問(wèn)題;詳細(xì)請(qǐng)參考博客:
https://blog.csdn.net/dog250/article/details/78692585
查看:抓包分析是否存在很多亂序報(bào)文:
解決方案:如果在多徑傳輸場(chǎng)景或者網(wǎng)絡(luò)質(zhì)量不好,可以通過(guò)修改下面值來(lái)提供系統(tǒng)對(duì)TCP無(wú)序傳送的容錯(cuò)率:
擁塞控制丟包
在互聯(lián)網(wǎng)發(fā)展的過(guò)程當(dāng)中,TCP算法也做出了一定改變,先后演進(jìn)了
Reno、NewReno、Cubic和Vegas,這些改進(jìn)算法大體可以分為基于丟包和基于延時(shí)的擁塞控制算法?;趤G包的擁塞控制算法以Reno、NewReno為代表,它的主要問(wèn)題有Buffer bloat和長(zhǎng)肥管道兩種,基于丟包的協(xié)議擁塞控制機(jī)制是被動(dòng)式的,其依據(jù)網(wǎng)絡(luò)中的丟包事件來(lái)做網(wǎng)絡(luò)擁塞判斷。即使網(wǎng)絡(luò)中的負(fù)載很高,只要沒(méi)有產(chǎn)生擁塞丟包,協(xié)議就不會(huì)主動(dòng)降低自己的發(fā)送速度。最初路由器轉(zhuǎn)發(fā)出口的Buffer 是比較小的,TCP在利用時(shí)容易造成全局同步,降低帶寬利用率,隨后路由器廠家由于硬件成本下降不斷地增加Buffer,基于丟包反饋的協(xié)議在不丟包的情況下持續(xù)占用路由器buffer,雖然提高了網(wǎng)絡(luò)帶寬的利用率,但同時(shí)也意味著發(fā)生擁塞丟包后,網(wǎng)絡(luò)抖動(dòng)性加大。另外對(duì)于帶寬和RTT都很高的長(zhǎng)肥管道問(wèn)題來(lái)說(shuō),管道中隨機(jī)丟包的可能性很大,TCP的默認(rèn)buffer設(shè)置比較小加上隨機(jī)丟包造成的cwnd經(jīng)常下折,導(dǎo)致帶寬利用率依舊很低; BBR(Bottleneck Bandwidth and Round-trip propagation time)是一種基于帶寬和延遲反饋的擁塞控制算法。目前已經(jīng)演化到第二版,是一個(gè)典型的封閉反饋系統(tǒng),發(fā)送多少報(bào)文和用多快的速度發(fā)送這些報(bào)文都是在每次反饋中不斷調(diào)節(jié)。在BBR提出之前,擁塞控制都是基于事件的算法,需要通過(guò)丟包或延時(shí)事件驅(qū)動(dòng);BBR提出之后,擁塞控制是基于反饋的自主自動(dòng)控制算法,對(duì)于速率的控制是由算法決定,而不由網(wǎng)絡(luò)事件決定,BBR算法的核心是找到最大帶寬(Max BW)和最小延時(shí)(Min RTT)這兩個(gè)參數(shù),最大帶寬和最小延時(shí)的乘積可以得到BDP(Bandwidth Delay Product), 而B(niǎo)DP就是網(wǎng)絡(luò)鏈路中可以存放數(shù)據(jù)的最大容量。BDP驅(qū)動(dòng)Probing State Machine得到Rate quantum和cwnd,分別設(shè)置到發(fā)送引擎中就可以解決發(fā)送速度和數(shù)據(jù)量的問(wèn)題。
Linux 4.9內(nèi)核首次采用BBR擁塞控制算法第一個(gè)版本,BBR抗丟包能力比其他算法要強(qiáng),但這個(gè)版本在某些場(chǎng)景下面有問(wèn)題(缺點(diǎn)),BBR在實(shí)時(shí)音視頻領(lǐng)域存在的問(wèn)題,深隊(duì)列競(jìng)爭(zhēng)不過(guò)Cubic。
問(wèn)題現(xiàn)象就是:在深隊(duì)列場(chǎng)景,BBR的ProbeRTT階段只發(fā)4個(gè)包,發(fā)送速率下降太多會(huì)引發(fā)延遲加大和卡頓問(wèn)題。
查看:
ss -sti //在源端 ss -sti|grep 10.125.42.49:47699 -A 3 ( 10.125.42.49:47699 是目的端地址和端口號(hào))
解決方案:
ProbeRTT并不適用實(shí)時(shí)音視頻領(lǐng)域,因此可以選擇直接去除,或者像BBRV2把probe RTT縮短到2.5s一次,使用0.5xBDP發(fā)送;
如果沒(méi)有特殊需求,切換成穩(wěn)定的cubic算法;
UDP層丟包
收發(fā)包失敗丟包
查看:netstat 統(tǒng)計(jì)
如果有持續(xù)的 receive buffer errors/send buffer errors 計(jì)數(shù);
解決方案:
CPU負(fù)載(多核綁核配置),網(wǎng)絡(luò)負(fù)載(軟中斷優(yōu)化,調(diào)整驅(qū)動(dòng)隊(duì)列netdev_max_backlog),內(nèi)存配置(協(xié)議棧內(nèi)存);
按峰值在來(lái),增大buffer緩存區(qū)大?。?/p>
net.ipv4.udp_mem = xxxnet.ipv4.udp_rmem_min = xxxnet.ipv4.udp_wmem_min = xxx
3. 調(diào)整應(yīng)用設(shè)計(jì):
UDP本身就是無(wú)連接不可靠的協(xié)議,適用于報(bào)文偶爾丟失也不影響程序狀態(tài)的場(chǎng)景,比如視頻、音頻、游戲、監(jiān)控等。對(duì)報(bào)文可靠性要求比較高的應(yīng)用不要使用 UDP,推薦直接使用 TCP。當(dāng)然,也可以在應(yīng)用層做重試、去重保證可靠性
如果發(fā)現(xiàn)服務(wù)器丟包,首先通過(guò)監(jiān)控查看系統(tǒng)負(fù)載是否過(guò)高,先想辦法把負(fù)載降低再看丟包問(wèn)題是否消失
如果系統(tǒng)負(fù)載過(guò)高,UDP丟包是沒(méi)有有效解決方案的。如果是應(yīng)用異常導(dǎo)致CPU、memory、IO 過(guò)高,請(qǐng)及時(shí)定位異常應(yīng)用并修復(fù);如果是資源不夠,監(jiān)控應(yīng)該能及時(shí)發(fā)現(xiàn)并快速擴(kuò)容
對(duì)于系統(tǒng)大量接收或者發(fā)送UDP報(bào)文的,可以通過(guò)調(diào)節(jié)系統(tǒng)和程序的 socket buffer size 來(lái)降低丟包的概率
應(yīng)用程序在處理UDP報(bào)文時(shí),要采用異步方式,在兩次接收?qǐng)?bào)文之間不要有太多的處理邏輯
應(yīng)用層socket丟包
socket緩存區(qū)接收丟包
查看:
1. 抓包分析是否存在丟包情況;
2. 查看統(tǒng)計(jì):
netstat -s|grep "packet receive errors"
解決方案:
調(diào)整socket緩沖區(qū)大小:
socket配置(所有協(xié)議socket):# Default Socket Receive Buffernet.core.rmem_default = 31457280# Maximum Socket Receive Buffernet.core.rmem_max = 67108864
具體大小調(diào)整原理:
緩沖區(qū)大小沒(méi)有任何設(shè)置值是最佳的,因?yàn)樽罴汛笮‰S具體情況而不同
緩沖區(qū)估算原理:在數(shù)據(jù)通信中,帶寬時(shí)延乘積(英語(yǔ):bandwidth-delay product;或稱(chēng)帶寬延時(shí)乘積、帶寬延時(shí)積等)指的是一個(gè)數(shù)據(jù)鏈路的能力(每秒比特)與來(lái)回通信延遲(單位秒)的乘積。[1][2]其結(jié)果是以比特(或字節(jié))為單位的一個(gè)數(shù)據(jù)總量,等同在任何特定時(shí)間該網(wǎng)絡(luò)線(xiàn)路上的最大數(shù)據(jù)量——已發(fā)送但尚未確認(rèn)的數(shù)據(jù)。
BDP = 帶寬 * RTT
可以通過(guò)計(jì)算當(dāng)面節(jié)點(diǎn)帶寬和統(tǒng)計(jì)平均時(shí)延來(lái)估算BDP,即緩沖區(qū)的大小,可以參考下面常見(jiàn)場(chǎng)景估計(jì):
參考:https://docs.oracle.com/cd/E56344_01/html/E53803/gnkor.html
應(yīng)用設(shè)置tcp連接數(shù)大小丟包
查看:
請(qǐng)參考上面TCP連接隊(duì)列分析;
解決方案:
設(shè)置合理的連接隊(duì)列大小,當(dāng)?shù)谌挝帐謺r(shí),當(dāng)server接收到ACK 報(bào)之后, 會(huì)進(jìn)入一個(gè)新的叫 accept 的隊(duì)列,該隊(duì)列的長(zhǎng)度為 min(backlog, somaxconn),默認(rèn)情況下,somaxconn 的值為 128,表示最多有 129 的 ESTAB 的連接等待 accept(),而 backlog 的值則應(yīng)該是由 int listen(int sockfd, int backlog) 中的第二個(gè)參數(shù)指定,listen 里面的 backlog 可以有我們的應(yīng)用程序去定義的;
應(yīng)用發(fā)送太快導(dǎo)致丟包
查看統(tǒng)計(jì):
netstat-s|grep"sendbuffererrors
解決方案:
ICMP/UDP沒(méi)有流控機(jī)制,需要應(yīng)用設(shè)計(jì)合理發(fā)送方式和速度,照顧到底層buff大小和CPU負(fù)載以及網(wǎng)絡(luò)帶寬質(zhì)量;
設(shè)置合理的sock緩沖區(qū)大?。?/p>
setsockopt(s,SOL_SOCKET,SO_SNDBUF, i(const char*)&nSendBuf,sizeof(int));
調(diào)整系統(tǒng)socket緩沖區(qū)大?。?/p>
# Default Socket Send Buffer net.core.wmem_default = 31457280 # Maximum Socket Send Buffer net.core.wmem_max = 33554432
附:簡(jiǎn)單總結(jié)一下內(nèi)核協(xié)議棧丟包:
相關(guān)工具介紹
1.dropwatch工具
原理:監(jiān)聽(tīng) kfree_skb(把網(wǎng)絡(luò)報(bào)文丟棄時(shí)會(huì)調(diào)用該函數(shù))函數(shù)或者事件嗎,然后打印對(duì)應(yīng)調(diào)用堆棧;想要詳細(xì)了解 linux 系統(tǒng)在執(zhí)行哪個(gè)函數(shù)時(shí)丟包的話(huà),可以使用 dropwatch 工具,它監(jiān)聽(tīng)系統(tǒng)丟包信息,并打印出丟包發(fā)生的函數(shù):
2. tcpdump工具
原理: tcpdump 是一個(gè)Unix下一個(gè)功能強(qiáng)大的網(wǎng)絡(luò)抓包工具,它允許用戶(hù)攔截和顯示發(fā)送或收到過(guò)網(wǎng)絡(luò)連接到該計(jì)算機(jī)的TCP/IP和其他數(shù)據(jù)包
抓包命令參考:
https://www.tcpdump.org/manpages/tcpdump.1.html
數(shù)據(jù)包分析:
1.用wireshark工具分析 參考:Wireshark數(shù)據(jù)包分析實(shí)戰(zhàn).pdf
2.可以轉(zhuǎn)化生成CSV數(shù)據(jù),用Excel或者shell去分析特定場(chǎng)景報(bào)文;
3.可以在linux上用tshark命令行工具進(jìn)行分析:
https://www.wireshark.org/docs/man-pages/tshark.html
總結(jié)
本文只是分析大部分可能會(huì)丟包節(jié)點(diǎn),提供了單個(gè)節(jié)點(diǎn)丟包排查和相關(guān)的解決方案, 丟包問(wèn)題牽扯網(wǎng)絡(luò)鏈路各個(gè)組件,尤其是在云網(wǎng)絡(luò)時(shí)代,網(wǎng)絡(luò)拓?fù)鋸?fù)雜多變,涉及運(yùn)營(yíng)商網(wǎng)絡(luò),IDC網(wǎng)絡(luò),專(zhuān)線(xiàn)等underlay網(wǎng)絡(luò),邊界網(wǎng)關(guān),VPC網(wǎng)絡(luò),CLB負(fù)載均衡等云上overlay網(wǎng)絡(luò),各種丟包問(wèn)題排障起來(lái)非常復(fù)雜且困難,但掌握網(wǎng)絡(luò)通信基本原理后,可以分解網(wǎng)絡(luò)拓?fù)?,?duì)通信節(jié)點(diǎn)進(jìn)行逐一排查,也可以找到丟包位置,后續(xù)會(huì)更加深入介紹云計(jì)算時(shí)代,云上網(wǎng)絡(luò)丟包排查方法,網(wǎng)絡(luò)架構(gòu)解析等,達(dá)到任何丟包問(wèn)題都可以快速排查和定位解決,幫助客戶(hù)快速恢復(fù)業(yè)務(wù),下期再會(huì)。
責(zé)任編輯:lq
-
Mac
+關(guān)注
關(guān)注
0文章
1095瀏覽量
51341 -
數(shù)據(jù)包
+關(guān)注
關(guān)注
0文章
248瀏覽量
24345 -
丟包
+關(guān)注
關(guān)注
1文章
12瀏覽量
8133
原文標(biāo)題:云網(wǎng)絡(luò)丟包故障定位全景指南
文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論