Linux 高性能網絡編程 工具篇
這是一張 linux 各個模塊的圖和對應的工具(當然這裏工具比較多,本文只將講和高性能調試和排查問題相關的工具)。
第一部分:Linux 服務器參數
1、內核參數
(1)max-file-number
在 linux 系統中很多資源都是以文件描述符表示的,但是文件描述符並非無限的大,系統分爲硬限制和軟限制(軟限制小於等於硬限制),如果需要修改,則通過/etc/security/limits.conf
:
hard nofile max-file-number
soft nofile max-file-number
有時我們在 linux 編程中會碰到錯誤:Too many open files
,這個表示某個進程打開的文件句柄超過限制,再打開文件就會報錯,這就是 linux 對用戶級限制的句柄數,查詢可以通過命令ulimit -n
,修改可以通過命令ulimit -SHn max-file-number
。
(2)limits.conf
中的其他限制
-
限制 cpu 運行時間,可以設置
hard cpu 1
,單位是分鐘 -
fsize 限制創建文件大小,可以設置
hard fsize 100
,單位是 kb
(3)/proc/sys/fs/file-max
系統級的文件描述符限制,可以臨時修改/proc/sys/fs/file-max
的值,放開限制。
(4)/proc/sys/fs/epoll/max_user_watches
epoll 內核事件表中註冊事件的總量,這裏包含用戶打開的所有 epoll 實例總共能監聽的事件數目。
2、網絡參數
(1)/proc/sys/net/core/somaxconn
指定 listen 監聽隊列中,能夠建立完整連接的從而進入 ESTABLISHD 狀態的 socket 最大數目。
(2)/proc/sys/net/ipv4/tcp_max_syn_backlog
指定 listen 監聽隊列中,能夠建立完整連接的從而進入 ESTABLISHD 或者 SYNC_RCVD 狀態的 socket 最大數目。
(3)/proc/sys/net/ipv4/tcp_wmem
和/proc/sys/net/ipv4/tcp_rmem
-
/proc/sys/net/ipv4/tcp_wmem
指定 socket 的 TCP 寫緩衝最大值,默認值和最小值 -
/proc/sys/net/ipv4/tcp_rmem
指定 socket 的 TCP 讀緩衝最大值,默認值和最小值
(4)/proc/sys/net/ipv4/tcp_syncookies
是否打開 TCP 的同步標籤,tcp_syncookies
目的是解決一個監聽 socket 因不停的重複收到來自同一個地址的連接請求,而導致 listen 監聽隊列的溢出。
以上永久生效的生效方式是修改或者添加選項到/etc/synctl.conf
,然後執行sysctl -p
。
第二部分:分析工具
測試程序,以下命令依賴的本代碼作爲樣例
#include <iostream>
#include <cmath>
using namespace std;
void for_loop()
{
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 10000; j++) {
int x = sin(i) + cos(j);
}
}
}
void loop1()
{
for (int i = 0; i < 10; i++) {
for_loop();
}
}
void loop2()
{
for (int i = 0; i < 100; i++) {
for_loop();
}
}
int main()
{
loop1();
loop2();
return 0;
}
// 編譯方式 g++ -g test.cc
1、gdb
gdb 是程序員必備的調試工具,網上資料比較多我就不詳細介紹,這裏幾個常用的調試方式:
gdb [options][執行文件 core文件|進程PID]
$ (gdb) info all-reg # 顯示所有處理器寄存器的內容,包括浮點和向量寄存器
$ (gdb) list filename:line_number # 顯示源代碼,並以指定的行作爲中心
$ (gdb) break [filename:] line_number # 在(指定文件或當前文件)指定行設置斷點
$ (gdb) continue / c [passes] # 繼續執行到下一個斷點,passes表示忽略幾次中斷
$ (gdb) step / s [lines] # 執行多少行後再次被中斷,如果遇到函數,將會進入函數,並在函數第一行停下來
$ (gdb) next / n [lines] # 執行多少行後再次被中斷,不會進入函數
$ (gdb) frame [number] # 顯示當前棧幀,或者選擇不同的棧幀
$ (gdb) info locals # 當前棧幀的局部變量
$ (gdb) info args # 列出對應函數調用的參數值
$ (gdb) bt # 打印堆棧信息
...
# 調試多進程程序,允許在執行fork以後繼續調試父進程還是子進程
$ (gdb) set follow-fork-mode mode(parent|child)
# 調試多線程程序常用命令
$ (gdb) info threads # 打印線程信息
$ (gdb) thread 線程ID # 切換線程ID
$ (gdb) set scheduler-locking (off|on|step) # 當前調試程序是否鎖定線程
與 gdp 配套的還有兩個工具是 gstack 和 gcore,gstack 是查看進程堆棧信息,gcore 是將進程堆棧轉存,然後使用 gdb 調試。
樣例:
(1)常用調試,命令gdb ./a.out
,輸出如下:
[root@VM-16-16-centos ~]# gdb ./a.out
GNU gdb (GDB) Red Hat Enterprise Linux 8.2-16.el8
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
(gdb) list
16 for (int i = 0; i < 10; i++) {
17 for_loop();
18 }
19 }
20
21 void loop2()
22 {
23 for (int i = 0; i < 100; i++) {
24 for_loop();
25 }
(2)用命令gstack 進程號
查看堆棧,然後gcore 進程號轉存數據
,最後用 gdb 調試,輸出如下:
[root@VM-16-16-centos ~]# gstack 365609
#0 0x00007f7ceef9bb55 in __sin_fma () from /lib64/libm.so.6
#1 0x0000000000400875 in std::sin<int> (__x=862) at /usr/include/c++/8/cmath:438
#2 0x0000000000400788 in for_loop () at test.cc:9
#3 0x00000000004007ef in loop2 () at test.cc:24
#4 0x0000000000400806 in main () at test.cc:31
[root@VM-16-16-centos ~]# gcore -p 365609
usage: gcore [-a] [-o filename] pid
[root@VM-16-16-centos ~]# gcore 365609
0x00007f7ceef9b602 in __sin_fma () from /lib64/libm.so.6
Saved corefile core.365609
[Inferior 1 (process 365609) detached]
# 其中轉存文件爲core.365609
[root@VM-16-16-centos ~]# gdb ./a.out ./core.365609
GNU gdb (GDB) Red Hat Enterprise Linux 8.2-16.el8
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
[New LWP 365609]
Core was generated by `./a.out'.
#0 0x00007f7ceef9b602 in __sin_fma () from /lib64/libm.so.6
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-151.el8.x86_64 libgcc-8.5.0-4.el8_5.x86_64 libstdc++-8.5.0-4.el8_5.x86_64
(gdb) bt full
#0 0x00007f7ceef9b602 in __sin_fma () from /lib64/libm.so.6
No symbol table info available.
#1 0x0000000000400875 in std::sin<int> (__x=12) at /usr/include/c++/8/cmath:438
No locals.
#2 0x0000000000400788 in for_loop () at test.cc:9
x = -1
j = 5327
i = 12
#3 0x00000000004007ef in loop2 () at test.cc:24
i = 69
#4 0x0000000000400806 in main () at test.cc:31
No locals.
(gdb) frame 1
#1 0x0000000000400875 in std::sin<int> (__x=12) at /usr/include/c++/8/cmath:438
438 { return __builtin_sin(__x); }
(gdb) info args
__x = 12
2、tcpdump
tcpdump 是一款經典的網絡抓包工具,也是 linux 下必備調試網絡工具,其中 tcpdump 使用參數:
tcpdump [-adeflnNOpqStvx][-c 數量][-F 文件名][-i 網絡接口][-r 文件名][-s snaplen][-T 類型][-w 文件名] [表達式]
樣例:
(1)常用抓包命令
tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
參數解釋:
tcp: ip icmp arp rarp 和 tcp、udp、icmp這些選項等都要放到第一個參數的位置,用來過濾數據報的類型
-i eth1:只抓經過接口eth1的包
-t:不顯示時間戳
-s 0:抓取數據包時默認抓取長度爲68字節,加上`-S 0`後可以抓到完整的數據包
-c 100:只抓取100個數據包
dst port ! 22:不抓取目標端口是22的數據包
src net 192.168.1.0/24:數據包的源網絡地址爲192.168.1.0/24
-w ./target.cap:保存成cap文件,方便用wireshark分析
(2)執行命令tcpdump -i any -AAA -c 3
,輸出如下:
[root@VM-16-16-centos ~]# tcpdump -i any -AAA -c 3
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
15:53:30.817134 IP VM-16-16-centos.ssh > 113.104.215.65.rrirtr: Flags [P.], seq 2416982452:2416982672, ack 3565832082, win 314, options [nop,nop,TS val 856138616 ecr 1045200609], length 220
......RT........EH....@.@.......qh.A......9...G....:7......
3..x>L~.$H.#..a.*.~..g.VG.n..k......8V`=_.2+Es+.'.,..AH.lEWmQ......Cm.]H......./...[`rh>J..d.N.....H.i.)....W.|'.......-...l.ie*1C....|. zv.....8 ..YO3..;..N+..I..../8e|,.P........xM......V....n.GGa...[y....J.R...........e......
15:53:30.817331 IP VM-16-16-centos.55721 > 183.60.82.98.domain: 41825+ PTR? 65.215.104.113.in-addr.arpa. (45)
......RT........E..I".@.@.RY.....<Rb...5.5...a...........65.215.104.113.in-addr.arpa.....
15:53:30.840249 IP 113.104.215.65.rrirtr > VM-16-16-centos.ssh: Flags [.], ack 0, win 2047, options [nop,nop,TS val 1045200644 ecr 856138605], length 0
........"$.'....E..4..@...zNqh.A..........G...9............
>L..3..m
3 packets captured
11 packets received by filter
2 packets dropped by kernel
3、lsof
lsof 是列出當前系統或者進程打開文件描述符的工具,其中使用方式:
lsof -i [46] [protocol][@hostname|ipaddr]:[service|port] // 顯示當前端口或者ip佔用的句柄列表
lsof -c [進程名] // 顯示當前進程名打開的句柄列表
lsof -p [進程id] // 顯示當前進程id打開的句柄列表
lsof -t [文件名] // 顯示打開當前文件的進程id
樣例:
(1)執行lsof -i:22
,查看 22 端口占用句柄,輸出如下:
[root@VM-16-16-centos ~]# lsof -i:22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1167 root 5u IPv4 21933 0t0 TCP *:ssh (LISTEN)
sshd 1167 root 6u IPv6 21935 0t0 TCP *:ssh (LISTEN)
sshd 39808 root 5u IPv4 372839047 0t0 TCP VM-16-16-centos:ssh->59.37.124.125:32754 (ESTABLISHED)
sshd 39821 root 5u IPv4 372839047 0t0 TCP VM-16-16-centos:ssh->59.37.124.125:32754 (ESTABLISHED)
(2)執行lsof -p 58582
,查看進程佔用句柄,輸出如下:
[root@VM-16-16-centos ~]# lsof -p 58582
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
a.out 58582 root cwd DIR 253,1 4096 393219 /root
a.out 58582 root rtd DIR 253,1 4096 2 /
a.out 58582 root txt REG 253,1 18240 394769 /root/a.out
a.out 58582 root mem REG 253,1 3167976 268071 /usr/lib64/libc-2.28.so
a.out 58582 root mem REG 253,1 99672 262185 /usr/lib64/libgcc_s-8-20210514.so.1
a.out 58582 root mem REG 253,1 2191840 280386 /usr/lib64/libm-2.28.so
a.out 58582 root mem REG 253,1 1660936 269721 /usr/lib64/libstdc++.so.6.0.25
a.out 58582 root mem REG 253,1 278504 268057 /usr/lib64/ld-2.28.so
a.out 58582 root 0u CHR 136,0 0t0 3 /dev/pts/0
a.out 58582 root 1u CHR 136,0 0t0 3 /dev/pts/0
a.out 58582 root 2u CHR 136,0 0t0 3 /dev/pts/0
4、nc
nc 是瑞士軍刀,主要用來快速建立連接,使用方式:
nc [-hlnruz][-g<網關...>][-G<指向器數目>][-i<延遲秒數>][-o<輸出文件>][-p<通信端口>][-s<來源位址>][-v...][-w<超時秒數>][主機名稱][通信端口...]
-g<網關> 設置路由器躍程通信網關,最多可設置8個
-G<指向器數目> 設置來源路由指向器,其數值爲4的倍數
-h 在線幫助
-i<延遲秒數> 設置時間間隔,以便傳送信息及掃描通信端口
-l 使用監聽模式,管控傳入的資料
-n 直接使用IP地址,而不通過域名服務器
-o<輸出文件> 指定文件名稱,把往來傳輸的數據以16進制字碼傾倒成該文件保存
-p<通信端口> 設置本地主機使用的通信端口
-r 亂數指定本地與遠端主機的通信端口
-s<來源位址> 設置本地主機送出數據包的IP地址
-u 使用UDP傳輸協議
-v 顯示指令執行過程
-w<超時秒數> 設置等待連線的時間
-z 使用0輸入/輸出模式,只在掃描通信端口時使用
樣例:
(1)web 服務器
# 1. 啓動server端,while :; do (echo -ne "HTTP/1.1 200 OK\r\nhello world")|nc -l -p 8000; done
# 2. 啓動client端,echo "GET / HTTP/1.0\r\n\r\n" | nc 127.0.0.1 8000,輸出如下:
[root@VM-16-16-centos ~]# echo "GET / HTTP/1.0\r\n\r\n" | nc 127.0.0.1 8000
HTTP/1.1 200 OK
hello world
(2)遠程控制
# 正向控制,被控端主動設置監聽端口及bash環境,控制端連接
# 被控制端執行下面的命令:
nc -lvnp 8888 -c bash
# 控制端執行下面的命令(可以輸入ls命令,就能獲取返回):
nc 127.0.0.1 8888
5、strace
strace 是測試服務性能的重要工具,它可以跟蹤程序運行過程中執行的系統調用和接收信號等,使用方式:
strace [-cdfrt][-e trace=all|file|process|network|signal|ipc...][-p 進程號]
-c 統計每一系統調用的所執行的時間,次數和出錯的次數等
-d 輸出strace關於標準錯誤的調試信息
-f 跟蹤由fork調用所產生的子進程
-F 嘗試跟蹤vfork調用,在-f時,vfork不被跟蹤
-a 設置返回值的輸出位置
-r 打印出相對時間關於每一個系統調用
-t 在輸出中的每一行前加上時間信息(方便查看調用事件)
-T 顯示每一調用所耗的時間(可以分析系統調用函數情況)
-x 以十六進制形式輸出非標準字符串
-xx 所有字符串以十六進制形式輸出
-p 跟蹤指定進程
其中:
-e expr指定一個表達式,格式[qualifier=][!]value1[,value2]...,但是隻能是(trace,abbrev,verbose,raw,signal,read,write)之一,以trace跟蹤格式爲例,如下樣例:
-e trace=set 跟蹤指定的系統調用,例如:-e trace=open,close,rean,write表示只跟蹤這四個系統調用,默認的爲set=all
-e trace=file 跟蹤有關文件操作的系統調用
-e trace=process 跟蹤有關進程控制的系統調用
-e trace=network 跟蹤與網絡有關的所有系統調用
-e trace=signal 跟蹤所有與系統信號有關的系統調用
-e trace=ipc 跟蹤所有與進程通訊有關的系統調用
-e trace=all 兩個特殊的符號all和none,all表示跟蹤所有的set,none表示不跟蹤
樣例:
(1)跟蹤上面的nc
命令,執行nc -lvnp 8888 -c bash
,輸出如下:
[root@VM-16-16-centos ~]# strace -e trace=network nc -lvnp 8888 -c bash
Ncat: Version 7.70 ( https://nmap.org/ncat )
socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_IPV6, IPV6_V6ONLY, [1], 4) = 0
bind(3, {sa_family=AF_INET6, sin6_port=htons(8888), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::", &sin6_addr), sin6_scope_id=0}, 28) = 0
listen(3, 10) = 0
Ncat: Listening on :::8888
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(4, 10) = 0
Ncat: Listening on 0.0.0.0:8888
accept(4, {sa_family=AF_INET, sin_port=htons(55084), sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 5
Ncat: Connection from 127.0.0.1.
Ncat: Connection from 127.0.0.1:55084.
recvfrom(5, "ls\n", 8192, 0, NULL, NULL) = 3
sendto(5, "a.out\ntest.cc\n", 14, 0, NULL, 0) = 14
(2)統計系統調用時間
[root@VM-16-16-centos ~]# strace -c ./a.out
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
27.95 0.000135 9 14 mmap
24.43 0.000118 11 10 mprotect
13.46 0.000065 7 9 read
8.28 0.000040 8 5 close
8.28 0.000040 8 5 openat
6.21 0.000030 6 5 fstat
6.21 0.000030 6 5 lseek
3.11 0.000015 15 1 munmap
2.07 0.000010 5 2 1 arch_prctl
0.00 0.000000 0 3 brk
0.00 0.000000 0 1 1 access
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.000483 7 61 2 total
6、netstat
nestat 是功能很強大的網絡信息統計工具,經常在網絡問題排查中使用,選項包括:
netstat [-natrisop][-c 採樣間隔(s)]
-n 顯示IP地址和端口號
-a 顯示結果中包含監聽的socket
-t 只顯示TCP連接信息
-u 只顯示UDP連接信息
-r 顯示路由信息
-i 顯示網卡的數據流量
-o 顯示socket定時器信息
-p 顯示socket所屬進程PID和名字
-s 顯示ICMP,TCP,UDP等socket的系統信息
樣例:
(1)顯示 TCP,UDP 和進程信息,命令netstat -tunp
,輸出如下:
[root@VM-16-16-centos ~]# netstat -tunp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 216 172.27.16.16:22 113.104.215.65:4034 ESTABLISHED 299304/sshd: root [
tcp 0 84 172.27.16.16:22 34.105.249.210:42030 ESTABLISHED 300012/sshd: root [
tcp 0 0 172.27.16.16:60822 169.254.0.3:80 TIME_WAIT -
tcp 0 0 172.27.16.16:22 113.104.215.65:1890 ESTABLISHED 281372/sshd: root [
tcp 0 0 172.27.16.16:60824 169.254.0.3:80 TIME_WAIT -
tcp 0 0 172.27.16.16:43802 169.254.0.55:5574 ESTABLISHED 3974640/YDService
tcp 0 389 172.27.16.16:22 34.105.249.210:55280 LAST_ACK -
tcp 0 0 172.27.16.16:60828 169.254.0.3:80 TIME_WAIT -
tcp 0 84 172.27.16.16:22 146.190.222.176:33062 ESTABLISHED 300017/sshd: unknow
tcp 0 0 172.27.16.16:60826 169.254.0.3:80 TIME_WAIT -
tcp 0 0 172.27.16.16:45878 169.254.0.138:8186 ESTABLISHED 214251/tat_agent
tcp 0 0 172.27.16.16:22 113.104.215.65:4443 ESTABLISHED 270055/sshd: root [
tcp 0 0 172.27.16.16:22 113.104.215.65:2186 ESTABLISHED 285317/sshd: root [
tcp 0 0 172.27.16.16:43800 169.254.0.55:5574 ESTABLISHED 3974640/YDService
udp 0 0 172.27.16.16:68 172.27.16.1:67 ESTABLISHED 989/NetworkManager
其中一些輸出信息簡單解釋:
-
Proto:協議信息,包括 TCP 和 UDP
-
Recv-Q:如果 TCP 連接狀態處於 Established,Recv-Q 的數值表示接收緩衝區中還沒拷貝到應用層的數據大小,如果 TCP 連接狀態處於 Listen 狀態,Recv-Q 的數值表示當前全連接隊列的大小
-
Send-Q:表示發送緩衝區中已發送但未被確認的數據大小(不管 TCP 是 Listen 狀態還是 Established 狀態都表示這個意思)
-
State:鏈路狀態,包括 LISTEN,SYN_SENT,SYN_RECV,ESTABLISHED,TIME-WAIT,UNKNOWN,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSE-WAIT 等
-
PID:進程信息,這裏包含進程名(通過 - p 參數輸出的)
(2)顯示 socket 當前的統計信息,命令netstat -s
,輸出如下:
[root@VM-16-16-centos ~]# netstat -s
IcmpMsg:
InType0: 37
InType3: 6665
InType5: 550
InType8: 11338192
InType11: 109
InType13: 3
OutType0: 11338192
OutType3: 205969
OutType14: 3
Tcp:
7023585 active connection openings
1100446 passive connection openings
30871 failed connection attempts
224072 connection resets received
8 connections established
68401617 segments received
67268650 segments sent out
330444 segments retransmitted
2734 bad segments received
5638980 resets sent
InCsumErrors: 2721
Udp:
4351700 packets received
450350 packets to unknown port received
145 packet receive errors
4374307 packets sent
0 receive buffer errors
0 send buffer errors
InCsumErrors: 145
UdpLite:
TcpExt:
604 SYN cookies sent
1874 SYN cookies received
129 invalid SYN cookies received
30846 resets received for embryonic SYN_RECV sockets
4 ICMP packets dropped because they were out-of-window
285778 TCP sockets finished time wait in fast timer
964 packets rejected in established connections because of timestamp
2382994 delayed acks sent
...
其中一些輸出信息簡單解釋(可以基於 TcpExt 一些信息分析當前網絡狀況,從而快速排查問題):
-
active connection openings:表示主動發起 TCP 連接的次數
-
passive connection openings:表示被動接受 TCP 連接的次數
-
failed connection attempts:表示 TCP 連接失敗的次數
-
connection resets received:表示 TCP 連接被重置的次數
-
connections established:表示當前已經建立的 TCP 連接數
-
segments received:表示接收到的 TCP 數據包的數量
-
segments sent out:表示發送的 TCP 數據包的數量
-
segments retransmitted:表示重傳的 TCP 數據包的數量
-
InCsumErrors:表示接收到的 TCP 數據包錯誤的數量
7、vmstat
vmstat 是輸出各個資源使用情況的工具,如進程,內存,CPU 使用率等信息,選項包括:
vmstat [-fsdp][-S k|K|m|M][interval採樣間隔(s)][count採樣次數]
-f 顯示系統啓動執行以來的fork次數
-s 顯示內存統計信息和活動統計信息,包括fork次數
-d 顯示磁盤統計信息
樣例:
(1)顯示常用統計信息(間隔 2s,並執行兩次輸出),命令vmstat 2 2
,輸出如下:
[root@VM-16-16-centos ~]# vmstat 2 2
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 298404 96824 1189732 0 0 1 34 1 0 0 0 99 0 0
0 0 0 298284 96824 1189736 0 0 0 214 760 1315 1 0 99 1 0
其中一些輸出信息簡單解釋:
-
procs 進程信息,r 是等待運行的進程數,b 是不可中斷的睡眠狀態的進程數
-
memory 內存信息,swpd 是 swap 內存數,free 是空間內存,buff 一些系統 buff 或者 io 緩存的中間內存,cache 是未寫入磁盤內存
-
swap:交換分區當前信息
-
io:塊設備當前信息
-
system:CPU 在內核態運行信息,包括 in 中斷次數,cs 上下文切換次數
-
cpu:CPU 使用信息,和後面
mpstat
命令輸出類似
(2)顯示系統活動數量統計,命令vmstat -s
,輸出如下:
[root@VM-16-16-centos ~]# vmstat -s
1860492 K total memory
274936 K used memory
701576 K active memory
707432 K inactive memory
299040 K free memory
96824 K buffer memory
1189692 K swap cache
0 K total swap
0 K used swap
0 K free swap
12318019 non-nice user cpu ticks
124590 nice user cpu ticks
11848347 system cpu ticks
2844992141 idle cpu ticks
4677889 IO-wait cpu ticks
0 IRQ cpu ticks
208152 softirq cpu ticks
0 stolen cpu ticks
15879112 pages paged in
985253486 pages paged out
0 pages swapped in
0 pages swapped out
1330511648 interrupts
260667271 CPU context switches
1678004734 boot time
58996940 forks
8、ifstat
ifstat 是簡單的網絡流量檢測工具,選項包括:
ifstat [-atb][-i 網卡][interval採樣間隔(s)][count採樣次數]
-a 監聽所有網卡接口
-t 每行輸出時間信息
-b 以Kbit/s爲單位顯示
-i 監聽指定的網卡接口
樣例:
(1)監聽所有網卡的流量情況,命令ifstat -a
,輸出如下:
[root@VM-16-16-centos ~]# ifstat -a
#kernel
Interface RX Pkts/Rate TX Pkts/Rate RX Data/Rate TX Data/Rate
RX Errs/Drop TX Errs/Drop RX Over/Rate TX Coll/Rate
lo 1228 0 1228 0 147340 0 147340 0
0 0 0 0 0 0 0 0
eth0 88238K 0 83403K 0 1934M 0 1021M 0
0 0 0 0 0 0 0 0
9、mpstat
mpstat 是查看每個 CPU 的使用情況,使用命令:
mpstat [-P|ALL][interval採樣間隔(s)][count採樣次數]
樣例:
(1)監聽 CPU 的使用情況,命令mpstat -P ALL 5 2
,輸出如下:
[root@VM-16-16-centos ~]# mpstat -P ALL 5 2
Linux 4.18.0-348.7.1.el8_5.x86_64 (VM-16-16-centos) 2023年08月19日 _x86_64_ (2 CPU)
10時02分15秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
10時02分20秒 all 0.70 0.00 0.80 0.50 0.00 0.00 0.00 0.00 0.00 98.00
10時02分20秒 0 0.60 0.00 0.80 0.20 0.00 0.00 0.00 0.00 0.00 98.40
10時02分20秒 1 0.80 0.00 0.80 0.80 0.00 0.00 0.00 0.00 0.00 97.60
10時02分20秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
10時02分25秒 all 0.50 0.00 0.30 0.00 0.00 0.00 0.00 0.00 0.00 99.20
10時02分25秒 0 0.40 0.00 0.40 0.00 0.00 0.00 0.00 0.00 0.00 99.20
10時02分25秒 1 0.60 0.00 0.20 0.00 0.00 0.00 0.00 0.00 0.00 99.20
平均時間: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
平均時間: all 0.60 0.00 0.55 0.25 0.00 0.00 0.00 0.00 0.00 98.60
平均時間: 0 0.50 0.00 0.60 0.10 0.00 0.00 0.00 0.00 0.00 98.80
平均時間: 1 0.70 0.00 0.50 0.40 0.00 0.00 0.00 0.00 0.00 98.40
其中一些輸出信息簡單解釋:
-
%usr:除了 nice 爲負的進程,系統上其他進程在用戶空間的 CPU 運行時間佔比
-
%nice:nice 爲負的進程在用戶空間的 CPU 運行時間佔比
-
%sys:系統上所有進程在內核空間的 CPU 運行時間佔比,但不包括硬中斷和軟中斷所耗的 CPU 時間
-
%iowait:CPU 等待磁盤操作的時間佔比
-
%irq:CPU 處理硬中斷的時間佔比
-
%soft:CPU 處理軟中斷的時間佔比
-
%steal:虛擬 CPU 等待時間佔比
-
%guest:虛擬 CPU 運行時間佔比
-
%idle:系統空間時間佔比
10、perf
perf 是 linux 的一款性能分析工具,能夠進行函數級和指令級的熱點查找,可以用來分析程序中熱點函數的 CPU 佔用率,從而定位性能瓶頸,使用命令:
perf [top|stat][record][report][-e 事件名稱][-p 進程ID]
-e 指定關注的事件,比如查看造成cache miss最多的函數排行:
perf top -e cache-misses
perf top -e task-clock
perf top -G // 得到調用關係圖
perf top-e cache-misses -G // 得到調用關係圖
perf top -e cycles // 指定性能事件
perf top -p 23015,32476 //查看這兩個進程的cpu cycles使用情況
perf top -s comm,pid,symbol // 顯示調用symbol的進程名和進程號
perf top --comms nginx,top // 僅顯示屬於指定進程的符號
perf top --symbols kfree // 僅顯示指定的符號
樣例:
(1)統計某個進程調用函數情況,命令perf top -p 368721
,輸出如下:
39.66% libm-2.28.so [.] __cos_fma
35.17% libm-2.28.so [.] __sin_fma
10.88% a.out [.] for_loop
6.84% a.out [.] std::cos<int>
6.43% a.out [.] std::sin<int>
0.96% a.out [.] sin@plt
0.03% a.out [.] cos@plt
0.01% [kernel] [k] _raw_spin_unlock_irqrestore
0.01% [kernel] [k] __softirqentry_text_start
0.00% [kernel] [k] tcp_v4_rcv
0.00% [kernel] [k] __inet_lookup_established
0.00% [kernel] [k] packet_rcv
0.00% [kernel] [k] update_io_ticks
0.00% [kernel] [k] _raw_spin_trylock
0.00% [kernel] [k] mod_objcg_state
11、http 壓測工具
這裏介紹壓測工具 http_bench,是 HTTP(HTTP/1, HTTP/2, HTTP/3, Websocket) 壓測工具,並支持單機和分佈式,使用命令:
-n 請求HTTP的次數
-c 併發的客戶端數量,但是不能大於HTTP的請求次數
-q 頻率限制,每秒的請求數
-d 壓測持續時間,默認10秒,例如:2s, 2m, 2h(s:秒,m:分鐘,h:小時)
-t 設置請求的超時時間,默認3s
-o 輸出結果格式,可以爲CSV,也可以直接打印
-m HTTP方法,包括GET, POST, PUT, DELETE, HEAD, OPTIONS.
-H 請求發起的HTTP的頭部信息,例如:-H "Accept: text/html" -H "Content-Type: application/xml"
-body HTTP發起POST請求的body數據
-a HTTP的鑑權請求, 例如:http://username:password@xxx/
-http 支持http1, http2, http3, ws和wss, 默認http1
-x HTTP的代理IP和端口
-disable-compression 不啓用壓縮
-disable-keepalive 不開啓keepalive
-cpus 使用cpu的內核數
-url 壓測單個URL
-verbose 打印詳細日誌,默認等級:3(0:TRACE, 1:DEBUG, 2:INFO, 3:ERROR)
-url-file 讀取文件中的URL,格式爲一行一個URL,發起請求每次隨機選擇發送的URL
-body-file 從文件中讀取請求的body數據
-listen 分佈式壓測任務機器監聽IP:PORT,例如: "127.0.0.1:12710".
-dashboard 監聽端口,瀏覽器發起壓測和查看QPS曲線.
-W 分佈式壓測執行任務的機器列表,例如: -W "127.0.0.1:12710" -W "127.0.0.1:12711".
-example 打印樣例信息.
樣例
./http_bench http://127.0.0.1:8000 -c 1000 -d 60s
Running 1000 connections, @ http://127.0.0.1:8000
Summary:
Total: 63.031 secs
Slowest: 0.640 secs
Fastest: 0.000 secs
Average: 0.072 secs
Requests/sec: 12132.423
Total data: 8.237 GB
Size/request: 11566 bytes
Status code distribution:
[200] 764713 responses
Latency distribution:
10% in 0.014 secs
25% in 0.030 secs
50% in 0.060 secs
75% in 0.097 secs
90% in 0.149 secs
95% in 0.181 secs
99% in 0.262 secs
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/9qh2J4EYz_bpl2BELkP9qw