網絡帶寬的單位bps,b表示的bit,一個Byte=8bit。通常常說的10M帶寬,10Mbps=10/8=1.25MBps(Byte)php
Mps是每秒傳輸的兆比特位數,是速度單位。MBps,指每秒傳輸多少兆字節,Mbps=Mbit/s即兆比特每秒。html
千兆網卡以太網理論上的限制是 128MB。這個數字從何而來?看看這些計算:linux
1Gb = 1024Mb;1024Mb/8 = 128MB;"b" = "bits,"、"B" = "bytes"ios
千兆帶寬,都是全雙工的,即上行(上傳)與下行(下載)都是千兆,理論都爲128MB/s,可是網絡都有損耗,按20%損耗實際帶寬會是100MB/s。git
linux下網卡相關檢查github
一、先用ifconfig看看有多少塊網卡和bonding。bonding是個很棒的東西,能夠把多塊網卡綁起來,突破單塊網卡的帶寬限制。數據庫
二、檢查每塊網卡的速度,好比"ethtool eth0"。再檢查bonding,好比"cat /proc/net/bonding/bond0", 留意其Bonding Mode是負載均衡的,再留意其捆綁的網卡的速度。windows
三、查看網卡是否支持多隊列,是否打開了多隊列,最後確認每一個隊列是否綁定到不一樣的CPU。api
四、最後檢查測試客戶機與服務機之間的帶寬,先簡單ping或traceroute 一下獲得RTT時間,iperf之類的可稍後。bash
當主機有1個以上的網卡時,Linux會將多個網卡綁定爲一個虛擬的bonded網絡接口,對TCP/IP而言只存在一個bonded網卡。多網卡綁定一方面可以提升網絡吞吐量,另外一方面也能夠加強網絡高可用。
能夠經過cat/proc/net/bonding/bond0查看本機的Bonding模式
通常不多須要開發去設置網卡Bonding模式。Linux支持7種Bonding模式(詳細的看內核):
Mode 0(balance-rr) Round-robin策略,這個模式具有負載均衡和容錯能力
Mode 1(active-backup) 主備策略,在綁定中只有一個網卡被激活,其餘處於備份狀態
Mode 2(balance-xor) XOR策略,經過源MAC地址與目的MAC地址作異或操做選擇slave網卡
Mode 3 (broadcast) 廣播,在全部的網卡上傳送全部的報文
Mode 4 (802.3ad) IEEE 802.3ad動態鏈路聚合。建立共享相同的速率和雙工模式的聚合組
Mode 5 (balance-tlb) Adaptive transmit loadbalancing
Mode 6 (balance-alb) Adaptive loadbalancing
windows
打開"網絡和共享中心"->選擇網絡,查看網絡鏈接狀態。以下圖所示:
11Mbps
linux
使用查詢及設置網卡參數的命令ethtool(http://man.linuxde.net/ethtool)查看,如使用ethtool eth1
# ethtool eth1 Settings for eth1: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Advertised auto-negotiation: Yes Speed: 1000Mb/s Duplex: Full Port: Twisted Pair PHYAD: 0 Transceiver: internal Auto-negotiation: on Supports Wake-on: umbg Wake-on: d Link detected: yes
操做完畢後,輸出信息中Speed:這一項就指示了網卡的速度。
隨着網絡的帶寬的不斷提高,單核CPU已經不能知足網卡的需求,這時經過多隊列網卡驅動的支持,能夠將每一個隊列經過中斷綁定到不一樣的CPU核上,充分利用多核提高數據包的處理能力。
1)查看網卡是否支持多隊列
使用lspci -vvv命令,找到Ethernetcontroller項:
若是有MSI-X, Enable+ 而且Count > 1,則該網卡是多隊列網卡。網卡的中斷機制是MSI-X,即網卡的每一個隊列均可以分配中斷(MSI-X支持2048箇中斷)。
備註:linux 2.6.32 上有lspci命令,但無-vvv參數。
2)查看是否打開了網卡多隊列。
使用命令cat/proc/interrupts,若是看到eth0-TxRx-0代表多隊列支持已經打開:
smp_affinity_list和smp_affinity任意更改一個文件都會生效,兩個文件相互影響,只不過是表示方法不一致,但通常都是修改smp_affinity 文件
3)最後確認每一個隊列是否綁定到不一樣的CPU。
cat/proc/interrupts查詢到每一個隊列的中斷號,對應的文件/proc/irq/${IRQ_NUM}/smp_affinity爲中斷號IRQ_NUM綁定的CPU核的狀況。以十六進制表示,每一位表明一個CPU核:(00000001)表明CPU0(00000010)表明CPU1(00000011)表明CPU0和CPU1。
中斷的親緣性設置能夠在 cat /proc/irq/${中斷號}/smp_affinity 或 cat /proc/irq/${中斷號}/smp_affinity_list 中確認,前者是16進制掩碼形式,後者是以CPU Core序號形式。例以下圖中,將16進制的400轉換成2進制後,爲 10000000000,「1」在第10位上,表示親緣性是第10個CPU Core。
那爲何中斷號只設置一個CPU Core呢?而不是爲每個中斷號設置多個CPU Core平行處理。通過測試,發現當給中斷設置了多個CPU Core後,它也僅能由設置的第一個CPU Core來處理,其餘的CPU Core並不會參與中斷處理,緣由猜測是當CPU能夠平行收包時,不一樣的核收取了同一個queue的數據包,但處理速度不一致,致使提交到IP層後的順序也不一致,這就會產生亂序的問題,由同一個核來處理能夠避免了亂序問題。
若是綁定的不均衡,能夠手工設置,例如:
echo "1" > /proc/irq/99/smp_affinity echo "2" > /proc/irq/100/smp_affinity echo "4" > /proc/irq/101/smp_affinity echo "8" > /proc/irq/102/smp_affinity echo "10" > /proc/irq/103/smp_affinity echo "20" > /proc/irq/104/smp_affinity echo "40" > /proc/irq/105/smp_affinity echo "80" > /proc/irq/106/smp_affinity
上述命令使用時須要注意一個是權限,一個是不一樣系統之間命令的差別。
理論參考:多隊列網卡CPU中斷均衡
能夠先作ping、traceroute看下 參考資料:網絡丟包分析
能夠在系統不繁忙或者臨時下線前檢測客戶端和server或者proxy 的帶寬:
1)使用 iperf -s 命令將 Iperf 啓動爲 server 模式:
iperf –s ———————————————————— Server listening on TCP port 5001 TCP window size: 8.00 KByte (default) ————————————————————
2)啓動客戶端,向IP爲10.230.48.65的主機發出TCP測試,並每2秒返回一次測試結果,以Mbytes/sec爲單位顯示測試結果:
iperf -c 10.230.48.65 -f M -i 2
在服務端上,運行:
# iperf -s -f M
這臺機器將用做服務器並以'M' = MBytes/sec爲單位輸出執行速度。
在客戶端節點上,運行:
# iperf -c ginger -P 4 -f M -w 256k -t 60
兩個屏幕上的結果都指示了速度是多少。在使用千兆網卡的普通服務器上,可能會看到速度約爲 112MB。這是 TCP 堆棧和物理電纜中的經常使用帶寬。經過以端到端的方式鏈接兩臺服務器,每臺服務器使用兩個聯結的以太網卡,得到了約 220MB的帶寬。
ping命令
上邊Ping www.a.shifen.com [220.181.111.188],這裏的地址是指域名對應的服務器地址。
如hosts文件裏,配置 220.181.111.188 www.a.shifen.com
tracert
它位於NIC和IP層之間,是一個典型的FIFO(先進先出)環形隊列。RingBuffer沒有包含數據自己,而是包含了指向sk_buff(socketkernel buffers)的描述符。
可使用ethtool-g eth0查看當前RingBuffer的設置:
上面的例子接收隊列爲4096,傳輸隊列爲256。
ifconfig的輸出中有兩項,分別是:
RX==receive,接收,從開啓到如今接收封包的狀況,是下行流量。
TX==Transmit,發送,從開啓到如今發送封包的狀況,是上行流量。
ifconfig觀察接收和傳輸隊列的運行情況:
[root@test etc]# ifconfig eth1
eth1 Link encap:Ethernet HWaddr 00:26:B9:58:19:88 inet addr:192.168.0.46 Bcast:192.168.0.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6049782538 errors:0 dropped:2373 overruns:0 frame:0 TX packets:7415059121 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:2611876455455 (2.3 TiB) TX bytes:6028598337794 (5.4 TiB) Interrupt:114 Memory:d8000000-d8012800
RX errors: 表示總的收包的錯誤數量,這包括 too-long-frames 錯誤,Ring Buffer 溢出錯誤,crc 校驗錯誤,幀同步錯誤,fifo overruns 以及 missed pkg 等等。
RX dropped: 表示數據包已經進入了 Ring Buffer,可是因爲內存不夠等系統緣由,致使在拷貝到內存的過程當中被丟棄。
RX overruns: 表示了 fifo 的 overruns,這是因爲 Ring Buffer(aka Driver Queue) 傳輸的 IO 大於 kernel 可以處理的 IO 致使的,而 Ring Buffer 則是指在發起 IRQ 請求以前的那塊 buffer。很明顯,overruns 的增大意味着數據包沒到 Ring Buffer 就被網卡物理層給丟棄了,而 CPU 沒法及時的處理中斷是形成 Ring Buffer 滿的緣由之一,例如中斷分配的不均勻(都壓在 core0),沒有作 affinity 而形成的丟包。
RX frame: 表示 misaligned 的 frames。
當dropped數量持續增長,建議增大RingBuffer,使用ethtool-G進行設置。
對於 TX 的來講,counter 增大的緣由主要包括 aborted transmission, errors due to carrirer, fifo error, heartbeat erros 以及 windown error,而 collisions 則表示因爲 CSMA/CD 形成的傳輸中斷。
txqueuelen 1000
QDisc(queueing discipline )位於IP層和網卡的ringbuffer之間。QDisc實現了流量管理的高級功能,包括流量分類,優先級和流量整形(rate-shaping)。可使用tc命令配置QDisc。QDisc的隊列長度由txqueuelen設置,和接收數據包的隊列長度由內核參數net.core.netdev_max_backlog控制所不一樣,txqueuelen是和網卡關聯。
RX和TX輸出的值使有的單位參數是bytes,而利用該命令,咱們也能夠配置腳本進行流量檢測。
大名鼎鼎的nagios就有一個插件check_traffic,經過ifconfig的輸出的RX、TX值經過之間的差,再除去中間間隔的時間算出流量大小的。該插件的下載頁爲:https://github.com/cloved/check_traffic/downloads 。
現摘錄其中部分關於度量值轉換的部分以下:
#to K
uIn=`echo "$ctbpsIn / 1024" | bc` uOut=`echo "$ctbpsOut / 1024" | bc` #to M if [ "$isM" = "True" ]; then uIn=`echo "scale=$Scale; $uIn / 1024" | bc` uOut=`echo "scale=$Scale; $uOut / 1024" | bc` fi #to B if [ "$isB" = "True" ]; then uIn=`echo "scale=$Scale; $uIn / 8" | bc` uOut=`echo "scale=$Scale; $uOut / 8" | bc`
2、監控
動態監控CPU中斷狀況,觀察中斷變化
watch -d -n 1 ‘cat /proc/interrupts’
查看網卡中斷相關信息
cat /proc/interrupts | grep -E 「eth|CPU」
網卡親和性設置
修改proc/irq/irq_number/smp_affinity以前,先停掉irq自動調節服務,否則修改的值就會被覆蓋。
/etc/init.d/irqbalance stop
經過查看網卡中斷相關信息,獲得網卡中斷爲19
[root@master ~]# cd /proc/irq/19 [root@master 19]# cat smp_affinity 00000000,00000000,00000000,00000001 [root@master 19]# cat smp_affinity_list 0
# taskset -p 30011 pid 30011's current affinity mask: ff
# taskset -p 1 30011 pid 30011's current affinity mask: ff pid 30011's new affinity mask: 1
# taskset -p -c 1,3 30011 pid 30011's current affinity list: 0 pid 30011's new affinity list: 1,3 # taskset -p -c 1-7 30011 pid 30011's current affinity list: 1,3 pid 30011's new affinity list: 1-7
可執行test.sh查看smp_affinity_list中的值的變化
#!/bin/bash irq=`grep 'eth' /proc/interrupts | awk '{print $1}' | cut -d : -f 1` for i in $irq do num=`cat /proc/irq/$i/smp_affinity_list` echo /proc/irq/$i/smp_affinity_list" "$num done
網卡綁定的時候最好和一個物理CPU的核挨個綁定,這樣避免L1,L2,L3踐踏。
使用systemtap診斷測試環境軟中斷分佈的方法
global hard, soft, wq probe irq_handler.entry { hard[irq, dev_name]++; } probe timer.s(1) { println("==irq number:dev_name") foreach( [irq, dev_name] in hard- limit 5) { printf("%d,%s->%d\n", irq, kernel_string(dev_name), hard[irq, dev_name]); } println("==softirq cpu:h:vec:action") foreach( [c,h,vec,action] in soft- limit 5) { printf("%d:%x:%x:%s->%d\n", c, h, vec, symdata(action), soft[c,h,vec,action]); } println("==workqueue wq_thread:work_func") foreach( [wq_thread,work_func] in wq- limit 5) { printf("%x:%x->%d\n", wq_thread, work_func, wq[wq_thread, work_func]); } println("\n") delete hard delete soft delete wq } probe softirq.entry { soft[cpu(), h,vec,action]++; } probe workqueue.execute { wq[wq_thread, work_func]++ } probe begin { println("~") }
執行結果:
==irq number:dev_name 87,eth0-0->1693 90,eth0-3->1263 95,eth1-3->746 92,eth1-0->703 89,eth0-2->654 ==softirq cpu:h:vec:action 0:ffffffff81a83098:ffffffff81a83080:0xffffffff81461a00->8928 0:ffffffff81a83088:ffffffff81a83080:0xffffffff81084940->626 0:ffffffff81a830c8:ffffffff81a83080:0xffffffff810ecd70->614 16:ffffffff81a83088:ffffffff81a83080:0xffffffff81084940->225 16:ffffffff81a830c8:ffffffff81a83080:0xffffffff810ecd70->224 ==workqueue wq_thread:work_func ffff88083062aae0:ffffffffa01c53d0->10 ffff88083062aae0:ffffffffa01ca8f0->10 ffff88083420a080:ffffffff81142160->2 ffff8808343fe040:ffffffff8127c9d0->2 ffff880834282ae0:ffffffff8133bd20->1
下面是action對應的符號信息:
addr2line -e /usr/lib/debug/lib/modules/2.6.32-431.20.3.el6.mt20161028.x86_64/vmlinux ffffffff81461a00 /usr/src/debug/kernel-2.6.32-431.20.3.el6/linux-2.6.32-431.20.3.el6.mt20161028.x86_64/net/core/dev.c:4013
打開這個文件,發現它是在執行 static void net_rx_action(struct softirq_action *h)這個函數,而這個函數正是NET_RX_SOFTIRQ 對應的軟中斷處理程序。所以能夠確認網卡的軟中斷在機器上分佈很是不均,並且主要集中在CPU 0上。經過/proc/interrupts能確認硬中斷集中在CPU 0上,所以軟中斷也都由CPU 0處理,如何優化網卡的中斷成爲了咱們關注的重點。
set_irq_affinity.sh
# cat set_irq_affinity.sh # setting up irq affinity according to /proc/interrupts # 2008-11-25 Robert Olsson # 2009-02-19 updated by Jesse Brandeburg # # > Dave Miller: # (To get consistent naming in /proc/interrups) # I would suggest that people use something like: # char buf[IFNAMSIZ+6]; # # sprintf(buf, "%s-%s-%d", # netdev->name, # (RX_INTERRUPT ? "rx" : "tx"), # queue->index); # # Assuming a device with two RX and TX queues. # This script will assign: # # eth0-rx-0 CPU0 # eth0-rx-1 CPU1 # eth0-tx-0 CPU0 # eth0-tx-1 CPU1 # set_affinity() { if [ $VEC -ge 32 ] then MASK_FILL="" MASK_ZERO="00000000" let "IDX = $VEC / 32" for ((i=1; i<=$IDX;i++)) do MASK_FILL="${MASK_FILL},${MASK_ZERO}" done let "VEC -= 32 * $IDX" MASK_TMP=$((1<<$VEC)) MASK=`printf "%X%s" $MASK_TMP $MASK_FILL` else MASK_TMP=$((1<<(`expr $VEC + $CORE`))) MASK=`printf "%X" $MASK_TMP` fi printf "%s mask=%s for /proc/irq/%d/smp_affinity\n" $DEV $MASK $IRQ printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity } if [ $# -ne 2 ] ; then echo "Description:" echo " This script attempts to bind each queue of a multi-queue NIC" echo " to the same numbered core, ie tx0|rx0 --> cpu0, tx1|rx1 --> cpu1" echo "usage:" echo " $0 core eth0 [eth1 eth2 eth3]" exit fi CORE=$1 # check for irqbalance running IRQBALANCE_ON=`ps ax | grep -v grep | grep -q irqbalance; echo $?` if [ "$IRQBALANCE_ON" == "0" ] ; then echo " WARNING: irqbalance is running and will" echo " likely override this script's affinitization." echo " Please stop the irqbalance service and/or execute" echo " 'killall irqbalance'" fi # # Set up the desired devices. # shift 1 for DEV in $* do for DIR in rx tx TxRx do MAX=`grep $DEV-$DIR /proc/interrupts | wc -l` if [ "$MAX" == "0" ] ; then MAX=`egrep -i "$DEV:.*$DIR" /proc/interrupts | wc -l` fi if [ "$MAX" == "0" ] ; then echo no $DIR vectors found on $DEV continue fi for VEC in `seq 0 1 $MAX` do IRQ=`cat /proc/interrupts | grep -i $DEV-$DIR-$VEC"$" | cut -d: -f1 | sed "s/ //g"` if [ -n "$IRQ" ]; then set_affinity else IRQ=`cat /proc/interrupts | egrep -i $DEV:v$VEC-$DIR"$" | cut -d: -f1 | sed "s/ //g"` if [ -n "$IRQ" ]; then set_affinity fi fi done done done
腳本參數是:set_irq_affinity.sh core eth0 [eth1 eth2 eth3] 能夠一次設置多個網卡,core的意思是從這個號開始遞增。
#./set_irq_affinity.sh 0 em1 no rx vectors found on em1 no tx vectors found on em1 em1 mask=1 for /proc/irq/109/smp_affinity em1 mask=2 for /proc/irq/110/smp_affinity em1 mask=4 for /proc/irq/111/smp_affinity em1 mask=8 for /proc/irq/112/smp_affinity em1 mask=10 for /proc/irq/113/smp_affinity em1 mask=20 for /proc/irq/114/smp_affinity em1 mask=40 for /proc/irq/115/smp_affinity em1 mask=80 for /proc/irq/116/smp_affinity #./set_irq_affinity.sh 8 em2 no rx vectors found on em2 no tx vectors found on em2 em2 mask=100 for /proc/irq/118/smp_affinity em2 mask=200 for /proc/irq/119/smp_affinity em2 mask=400 for /proc/irq/120/smp_affinity em2 mask=800 for /proc/irq/121/smp_affinity em2 mask=1000 for /proc/irq/122/smp_affinity em2 mask=2000 for /proc/irq/123/smp_affinity em2 mask=4000 for /proc/irq/124/smp_affinity em2 mask=8000 for /proc/irq/125/smp_affinity
watch -n 1 "/sbin/ifconfig eth0|grep bytes"
若是網絡出現丟包,發現丟包是由於隊列中的數據包超過了 netdev_max_backlog 形成了丟棄,所以首先想到是臨時調大netdev_max_backlog可否解決燃眉之急,事實證實,對於輕微丟包調大參數能夠緩解丟包,但對於大量丟包則幾乎不怎麼管用,內核處理速度跟不上收包速度的問題仍是客觀存在,本質仍是由於單核處理中斷有瓶頸,即便不丟包,服務響應速度也會變慢。所以若是能同時使用多個CPU Core來處理中斷,就能顯著提升中斷處理的效率,而且每一個CPU都會實例化一個softnet_data對象,隊列數也增長了。
這部分丟包能夠在cat /proc/net/softnet_stat的輸出結果中進行確認:
參考資料: