一 網(wǎng)絡(luò)概念:
1.帶寬: 標(biāo)識(shí)網(wǎng)卡的最大傳輸速率,單位為 b/s,比如 1Gbps,10Gbps,相當(dāng)于馬路多寬
2.吞吐量: 單位時(shí)間內(nèi)傳輸數(shù)據(jù)量大小單位為 b/s 或 B/s ,吞吐量/帶寬,就是網(wǎng)絡(luò)的使用率,相當(dāng)于單位時(shí)間內(nèi)馬路上路過有多少人吧(包括車?yán)锏牡龋?/span>
3.延時(shí): 發(fā)送網(wǎng)絡(luò)請(qǐng)求,到收到遠(yuǎn)端響應(yīng),需要的時(shí)間延遲,比如 TCP 握手延遲,或者數(shù)據(jù)包往返時(shí)間,相當(dāng)于一去一回時(shí)間。
4.pps : 每秒轉(zhuǎn)發(fā)包數(shù)量,如果吞吐量是以字節(jié)為單位,PPS 是以包為單位,可以理解成路上車的數(shù)量,以車位單位。
5.并發(fā)連接數(shù): TCP 連接數(shù)量。 6.丟包率: 丟包的百分比。 7.重傳率: 重傳的包的比例。
二 網(wǎng)卡有用命令
2.1 監(jiān)控是否丟包 watch
watch -d ifconfig ens33
errors 表示發(fā)生錯(cuò)誤的數(shù)據(jù)包數(shù),比如校驗(yàn)錯(cuò)誤、幀同步錯(cuò)誤等;
dropped 表示丟棄的數(shù)據(jù)包數(shù),即數(shù)據(jù)包已經(jīng)收到了 Ring Buffer,但因?yàn)閮?nèi)存不足等原因丟包,主要應(yīng)用層或系統(tǒng)內(nèi)核處理慢;
overruns 表示超限數(shù)據(jù)包數(shù),即網(wǎng)絡(luò) I/O 速度過快,導(dǎo)致 Ring Buffer 中的數(shù)據(jù)包來不及處理(隊(duì)列滿)而導(dǎo)致的丟包(網(wǎng)卡收包隊(duì)列已滿);
carrier 表示發(fā)生 carrirer 錯(cuò)誤的數(shù)據(jù)包數(shù),比如雙工模式不匹配、物理電纜出現(xiàn)問題等;
collisions 表示碰撞數(shù)據(jù)包數(shù)。
2.2 查看系統(tǒng)中連接信息
netstat -lnp
其中: -l 表示只顯示監(jiān)聽套接字 ;
-n 表示顯示數(shù)字地址和端口(而不是名字)
-p 表示顯示進(jìn)程信息
[root@iZbp10p2g1civrw4ggigvfZ ~]# netstat -lnp
Active Internet connections (only servers)
Proto recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 1444/master
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 20330/nginx: master
TCP 0 0 0.0.0.0:2332 0.0.0.0:* LISTEN 1712/nginx: master
tcp 0 0 0.0.0.0:5278 0.0.0.0:* LISTEN 27975/java
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1840/php-fpm: maste
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1937/mysqld
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 1684/redis-server 0
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 20330/nginx: master
tcp 0 0 0.0.0.0:2353 0.0.0.0:* LISTEN 24490/sshd: /usr/sb
tcp 0 0 0.0.0.0:23 0.0.0.0:* LISTEN 1/systemd
tcp6 0 0 :::25 :::* LISTEN 1444/master
tcp6 0 0 :::33060 :::* LISTEN 1937/mysqld
tcp6 0 0 :::2353 :::* LISTEN 24490/sshd: /usr/sb
udp 0 0 0.0.0.0:68 0.0.0.0:* 1026/dhclient
udp 0 0 127.0.0.1:323 0.0.0.0:* 749/chronyd
udp6 0 0 ::1:323 :::* 749/chronyd
Active UNIX domain sockets (only servers)
Proto RefCnt Flags Type State I-Node PID/Program name Path
....
ss -ltnp
-l 表示只顯示監(jiān)聽套接字
-t 表示只顯示 TCP 套接字
-n 表示顯示數(shù)字地址和端口(而不是名字) -p 表示顯示進(jìn)程信息
注意:下面是 ss 命令下的解釋:
Established 狀態(tài)時(shí),Recv-Q 表示套接字緩沖還沒有被應(yīng)用程序取走的字節(jié)數(shù)( ,而 Send-Q 表示還沒有被遠(yuǎn)端主機(jī)確認(rèn)的字節(jié)數(shù) LISTEN 狀態(tài)時(shí)候 Recv-Q 表示使用的全連接隊(duì)列的長(zhǎng)度 Send-Q 表示全連接隊(duì)列的最大長(zhǎng)度。
ss 只顯示已經(jīng)連接、關(guān)閉、孤兒套接字等簡(jiǎn)要統(tǒng)計(jì),而 netstat 則提供的是更詳細(xì)的網(wǎng)絡(luò)協(xié)議棧信息。
netstat -s
root@iZbp10p2g1civrw4ggigvfZ ~]# netstat -s
Ip:
368894134 total packets received
0 forwarded
0 incoming packets discarded
368894127 incoming packets delivered
204418238 requests sent out
133 dropped because of missing route
7 reassemblies required
1 packets reassembled ok
Icmp:
91913511 ICMP messages received
90910972 input ICMP message failed.
InCsumErrors: 2
ICMP input histogram:
destination unreachable: 4391
....
netstat 在排查 tcp 連接時(shí)候還是非常有用的,比如我們可以通過:
netstat -s | egrep "listen"
79019 times the listen queue of a socket overflowed
多次觀察是否會(huì)增加,如果會(huì)增加,說明有監(jiān)聽隊(duì)列滿了,導(dǎo)致的連接拒絕問題。 如果隊(duì)列滿了,可以通過查看:
cat /proc/sys/net/ipv4/tcp_abort_on_overflow
值為 0 表示連接隊(duì)列如果滿了,系統(tǒng)會(huì)直接扔掉客戶端的 ack 報(bào)文,將這個(gè)值改成 1,會(huì)在隊(duì)列滿的情況下直接發(fā) reset 包給客戶端。
ss -s命令統(tǒng)計(jì)信息:
[root@iZbp10p2g1civrw4ggigvfZ ~]# ss -s
Total: 210 (kernel 276)
TCP: 22 (estab 7, closed 2, orphaned 0, synrecv 0, timewait 1/0), ports 0
Transport Total IP IPv6
* 276 - -
RAW 0 0 0
UDP 3 2 1
TCP 20 17 3
INET 23 19 4
FRAG 0 0 0
2.3 網(wǎng)絡(luò)統(tǒng)計(jì)指標(biāo)統(tǒng)計(jì)信息
sar -n DEV 1
[root@iZbp10p2g1civrw4ggigvfZ ~]# sar -n DEV 1
Linux 3.10.0-1062.4.3.el7.x86_64 (iZbp10p2g1civrw4ggigvfZ) 12/25/2021 _x86_64_ (2 CPU)
02:16:52 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
02:16:53 PM eth0 0.99 0.99 0.06 0.09 0.00 0.00 0.00
02:16:53 PM lo 11.88 11.88 1.95 1.95 0.00 0.00 0.00
02:16:53 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
02:16:54 PM eth0 0.99 0.99 0.06 0.17 0.00 0.00 0.00
02:16:54 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- rxpck/s 和 txpck/s 每秒接收的數(shù)據(jù)包數(shù)量和每秒發(fā)送數(shù)據(jù)包的數(shù)量。
- rxkB/s 和 txkB/s 每秒接收的字節(jié)數(shù)和發(fā)送的吞吐量。
- rxcmp/s 和 txcmp/s 每秒鐘接收和發(fā)送的壓縮數(shù)據(jù)包。
- rxmcst/s 每秒收到多播的數(shù)量。
2.4 帶寬查看
[root@localhost ~]# ethtool ens33 | grep Speed
Speed: 1000Mb/s
以上為千兆網(wǎng)卡
2.5 連通性測(cè)試和延時(shí)查看
這個(gè)比較簡(jiǎn)單,我們一般通過 PING 進(jìn)行測(cè)試,如下:
[root@localhost ~]# ping -c10 www.baidu.com
PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=55 time=36.2 ms
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=55 time=36.1 ms
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=55 time=35.8 ms
...
time=35.8 ms 標(biāo)識(shí)往返時(shí)延。 設(shè)置 ping 包大小,可以測(cè)試網(wǎng)絡(luò)中 mtu 大概范圍:
[root@localhost ~]# ping -c 4 -s 1420 www.baidu.com
PING www.a.shifen.com (14.215.177.38) 1420(1448) bytes of data.
1428 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=55 time=36.4 ms
1428 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=55 time=35.2 ms
1428 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=55 time=36.5 ms
三 網(wǎng)絡(luò)層性能測(cè)試
3.1 網(wǎng)路層可以通過 pktgen 來測(cè)試網(wǎng)絡(luò)性能
# 加載發(fā)包工具
$ modprobe pktgen
定義發(fā)包腳本:
# 定義一個(gè)工具函數(shù),方便后面配置各種測(cè)試選項(xiàng)
function pgset() {
local result
echo $1 > $PGDEV
result=`cat $PGDEV | fgrep "Result: OK:"`
if [ "$result" = "" ]; then
cat $PGDEV | fgrep Result:
fi
}
# 為0號(hào)線程綁定ens33網(wǎng)卡
PGDEV=/proc/net/pktgen/kpktgend_0
pgset "rem_device_all" # 清空網(wǎng)卡綁定
pgset "add_device eth0" # 添加eth0網(wǎng)卡
# 配置ens33網(wǎng)卡的測(cè)試選項(xiàng)
PGDEV=/proc/net/pktgen/ens33
pgset "count 1000000" # 總發(fā)包數(shù)量
pgset "delay 5000" # 不同包之間的發(fā)送延遲(單位納秒)
pgset "clone_skb 0" # SKB包復(fù)制
pgset "pkt_size 64" # 網(wǎng)絡(luò)包大小
pgset "dst 192.168.1.30" # 目的IP
pgset "dst_mac 11:11:11:11:11:11" # 目的MAC
# 啟動(dòng)測(cè)試
PGDEV=/proc/net/pktgen/pgctrl
pgset "start"
查看測(cè)試結(jié)果:
[root@localhost pktgen]# cat /proc/net/pktgen/em1
Params: count 1000000 min_pkt_size: 64 max_pkt_size: 64
frags: 0 delay: 5000 clone_skb: 0 ifname: em1
flows: 0 flowlen: 0
queue_map_min: 0 queue_map_max: 0
dst_min: 192.168.1.29 dst_max:
src_min: src_max:
src_mac: f8:bc:12:4c:65:00 dst_mac: 11:11:11:11:11:11
udp_src_min: 9 udp_src_max: 9 udp_dst_min: 9 udp_dst_max: 9
src_mac_count: 0 dst_mac_count: 0
Flags:
Current:
pkts-sofar: 1000000 errors: 0
started: 335193101003us stopped: 335198101130us idle: 4529619us
seq_num: 1000001 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
cur_saddr: 192.168.1.29 cur_daddr: 192.168.1.30
cur_udp_dst: 9 cur_udp_src: 9
cur_queue_map: 0
flows: 0
Result: OK: 5000126(c470506+d4529619) usec, 1000000 (64byte,0frags)
199994pps 102Mb/sec (102396928bps) errors: 0
- 第一部分的 Params 是測(cè)試選項(xiàng);
- 第二部分的 Current 是測(cè)試進(jìn)度,其中, packts so far(pkts-sofar)表示已經(jīng)發(fā)送了 100 萬個(gè)包,也就表明測(cè)試已完成。
- 第三部分的 Result 是測(cè)試結(jié)果,包含測(cè)試所用時(shí)間、網(wǎng)絡(luò)包數(shù)量和分片、PPS、吞吐量以及錯(cuò)誤數(shù)。 結(jié)果每秒發(fā)送 19 萬個(gè)包,吞吐量為 102Mb/s.
3.2 TCP/UDP 性能測(cè)試
iperf 和 netperf 是用來測(cè)試 tcp、udp 的吞吐量的常用工具。
# 安裝
yum install iperf3
# 測(cè)試
# -s 啟動(dòng)服務(wù)器端 -i 匯報(bào)間隔 -p 端口啟動(dòng)1234
$iperf3 -s -i 1 -p 1234
# -c表示啟動(dòng)客戶端,127.0.0.1為目標(biāo)服務(wù)器的IP
# -b表示目標(biāo)帶寬(單位是bits/s)
# -t表示測(cè)試時(shí)間
# -P表示并發(fā)數(shù),-p表示目標(biāo)服務(wù)器監(jiān)聽端口
$iperf3 -c 127.0.0.1 -b 10G -t 15 -P 2 -p 1234
報(bào)告查看,本機(jī)測(cè)試 20Gbps 還是可以達(dá)到的。
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-15.00 sec 17.5 GBytes 10.0 Gbits/sec 6 sender
[ 5] 0.00-15.03 sec 17.5 GBytes 9.98 Gbits/sec receiver
[ 7] 0.00-15.00 sec 17.5 GBytes 10.0 Gbits/sec 2 sender
[ 7] 0.00-15.03 sec 17.5 GBytes 9.98 Gbits/sec receiver
[SUM] 0.00-15.00 sec 34.9 GBytes 20.0 Gbits/sec 8 sender
[SUM] 0.00-15.03 sec 34.9 GBytes 20.0 Gbits/sec receiver
3.3 HTTP 性能測(cè)試
http 性能測(cè)試可以選擇的不少,常用的有 ab(Apache 自帶的 HTTP 壓測(cè)工具),webbench。
# ab工具安裝
yum install -y httpd-tools
運(yùn)行下 http 服務(wù)器:
[root@localhost ~]# podman run -p 80:80 -itd nginx
b924819bbd3c3eadcd14e2c6b2088f838fa88399fd8404dfbd9863d04570f900
[root@localhost ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b924819bbd3c docker.io/feisky/nginx:latest nginx -g daemon o... 9 seconds ago Up 8 seconds ago 0.0.0.0:80->80/tcp beautiful_tereshkov
測(cè)試:
# -c表示并發(fā)請(qǐng)求數(shù)為1000,-n表示總的請(qǐng)求數(shù)為10000
[root@localhost ~]# ab -c 1000 -n 10000 http://192.168.31.50/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.31.50 (be patient)
apr_socket_recv: Connection reset by peer (104)
Total of 223 requests completed
[root@localhost ~]#
直接報(bào)錯(cuò),尷尬了,難道是隊(duì)列不夠設(shè)置下:
vim /etc/sysctl.conf
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_syn_backlog =1024
# 生效:sysctl -p
# 注意net.ipv4.tcp_syncookies設(shè)置為1的話,半連接隊(duì)列沒有用的
SYN Cookie 是對(duì) TCP 服務(wù)器端的三次握手協(xié)議作一些修改,專門用來防范 SYN Flood 攻擊的一種手段。它的原理是,在 TCP 服務(wù)器收到 TCP SYN 包并返回 TCP SYN+ACK 包時(shí),不分配一個(gè)專門的數(shù)據(jù)區(qū),而是根據(jù)這個(gè) SYN 包計(jì)算出一個(gè) cookie 值。在收到 TCP ACK 包時(shí),TCP 服務(wù)器在根據(jù)那個(gè) cookie 值檢查這個(gè) TCP ACK 包的合法性。如果合法,再分配專門的數(shù)據(jù)區(qū)進(jìn)行處理未來的 TCP 連接。
結(jié)果還不行,抓包看下,都是直接對(duì) 80 端口發(fā)送 RST 報(bào)文,有點(diǎn)尷尬,沒看到連接報(bào)文,后來查了下,可能是在接手 tcp_syncookies 報(bào)錯(cuò),所以把報(bào)錯(cuò)繼續(xù)發(fā)送選項(xiàng)打開,即加個(gè)-r 選項(xiàng) 如下:
[root@localhost ~]# ab -r -c 1000 -n 10000 http://192.168.31.50/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.31.50 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: nginx/1.15.4
Server Hostname: 192.168.31.50
Server Port: 80
Document Path: /
Document Length: 153 bytes
Concurrency Level: 1000
Time taken for tests: 0.994 seconds
Complete requests: 10000
Failed requests: 0
Non-2xx responses: 10000
Total transferred: 3030000 bytes
HTML transferred: 1530000 bytes
Requests per second: 10061.44 [#/sec] (mean)
Time per request: 99.389 [ms] (mean)
Time per request: 0.099 [ms] (mean, across all concurrent requests)
Transfer rate: 2977.16 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 5 6.7 2 39
Processing: 1 32 101.8 11 851
Waiting: 1 31 101.8 10 851
Total: 3 37 104.4 13 870
Percentage of the requests served within a certain time (ms)
50% 13
66% 16
75% 19
80% 21
90% 44
95% 84
98% 453
99% 858
100% 870 (longest request)
關(guān)鍵輸出信息:
1. 每秒平均發(fā)送請(qǐng)求:Requests per second: 10061.44 [#/sec](mean)
2. 平均請(qǐng)求時(shí)延 Time per request: 99.389 [ms](mean)
3. 吞吐量: Transfer rate: 2977.16 [Kbytes/sec] received
3.4 應(yīng)用層測(cè)試性能
wrk、TCPCopy、Jmeter 或者 LoadRunner 等工具可以測(cè)試實(shí)際負(fù)載的。 以 wrk 為例測(cè)試:
wget https://github.com.cnpmjs.org/wg/wrk
tar xvf wrk*
cd wrk*
make
cp wrk /usr/local/bin
測(cè)試:
# 測(cè)試 -t12 開始12個(gè)線程 -c400 保持400個(gè)http連接 -d30s 持續(xù)時(shí)間30s
[root@localhost wrk-master]# wrk -t12 -c400 -d30s http://192.168.31.50/
Running 30s test @ http://192.168.31.50/
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 22.42ms 17.12ms 564.75ms 97.18%
Req/Sec 1.56k 261.57 3.13k 70.10%
558047 requests in 30.04s, 163.89MB read
Non-2xx or 3xx responses: 558047
Requests/sec: 18574.38
Transfer/sec: 5.46MB
- 每秒發(fā)送請(qǐng)求數(shù):18574.38
- 吞吐量為:5.46MB/s
- 平均時(shí)延:22.42ms