Linux高性能网络编程十谈 | 工具篇

系统 Linux
上篇文章主要是介绍《Linux高性能网络编程十谈|协程》,整理如何设计高性能网络编程,接下来的两篇文章主要介绍工具和性能问题分析的总结,有相关的问题可以在留言区留言,我将解答大家的疑问。

上篇文章主要是介绍《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


责任编辑:华轩 来源: 周末程序猿
相关推荐

2023-11-01 10:38:46

Linux高性能网络编程

2024-03-18 13:43:20

Linux架构

2023-11-01 11:59:13

2023-11-01 11:27:10

Linux协程

2023-11-01 10:58:31

系统调用高性能网络编程Linux

2023-11-01 11:51:08

Linux性能优化

2023-11-01 11:07:05

Linux高性能网络编程线程

2023-11-01 11:13:58

Linux信号处理定时器

2023-11-01 11:20:57

2023-11-01 10:43:31

Linux高性能网络编程

2024-08-06 08:22:18

2024-10-06 14:37:52

2024-09-03 09:15:37

2024-10-16 11:03:30

Linux高性能编程

2020-11-06 18:51:17

LinuxTCP服务器

2013-07-01 17:35:30

2010-06-02 15:21:29

Linux 网络性能

2010-06-02 15:45:45

Linux 网络性能

2010-06-02 15:37:38

Linux 网络性能

2010-12-22 13:19:43

Linux性能监测网络
点赞
收藏

51CTO技术栈公众号