这篇文章上次修改于 899 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

低层协议的性能,决定了高层的网络性能。如下为不同协议层的网络性能测试方法。

1 转发性能

首先查看网络接口层和网络层,PPS 是重要性能指标,特别 64B 小包的处理能力。

pkgen 为 Linux 自带的高性能网络测试工具。需要加载 pkgen 再通过 /proc 与其交互:

$ modprobe pktgen
$ ps -ef | grep pktgen | grep -v grep
root     26384     2  0 06:17 ?        00:00:00 [kpktgend_0]
root     26385     2  0 06:17 ?        00:00:00 [kpktgend_1]
$ ls /proc/net/pktgen/
kpktgend_0  kpktgend_1  pgctrl

发包测试示例:

# 定义一个工具函数,方便后面配置各种测试选项
function pgset() {
    local result
    echo $1 > $PGDEV

    result=`cat $PGDEV | fgrep "Result: OK:"`
    if [ "$result" = "" ]; then
         cat $PGDEV | fgrep Result:
    fi
}

# 为0号线程绑定eth0网卡
PGDEV=/proc/net/pktgen/kpktgend_0
pgset "rem_device_all"   # 清空网卡绑定
pgset "add_device eth0"  # 添加eth0网卡

# 配置eth0网卡的测试选项
PGDEV=/proc/net/pktgen/eth0
pgset "count 1000000"    # 总发包数量
pgset "delay 5000"       # 不同包之间的发送延迟(单位纳秒)
pgset "clone_skb 0"      # SKB包复制
pgset "pkt_size 64"      # 网络包大小
pgset "dst 192.168.0.30" # 目的IP
pgset "dst_mac 11:11:11:11:11:11"  # 目的MAC

# 启动测试
PGDEV=/proc/net/pktgen/pgctrl
pgset "start"

查看测试报告:

$ cat /proc/net/pktgen/eth0
Params: count 1000000  min_pkt_size: 64  max_pkt_size: 64
     frags: 0  delay: 0  clone_skb: 0  ifname: eth0
     flows: 0 flowlen: 0
...
Current:
     pkts-sofar: 1000000  errors: 0
     started: 1534853256071us  stopped: 1534861576098us idle: 70673us
...
Result: OK: 8320027(c8249354+d70673) usec, 1000000 (64byte,0frags)
  120191pps 61Mb/sec (61537792bps) errors: 0
  • 第一部分 Params 是测试项。
  • 第二部分 Current 是测试进度。
  • 第三部分 Result 是测试结果,包含所用时间、网络包数量和分片、PPS、吞吐量和错误数。

2 TCP/UDP 性能

安装 iperf3:

# Ubuntu
apt-get install iperf3
# CentOS
yum install iperf3

在目标机器上启动 iperf3 服务端:

# -s表示启动服务端,-i表示汇报间隔,-p表示监听端口
$ iperf3 -s -i 1 -p 10000

在另一台机器上运行 iperf3 客户端,进行测试:

# -c表示启动客户端,192.168.0.30为目标服务器的IP
# -b表示目标带宽(单位是bits/s)
# -t表示测试时间
# -P表示并发数,-p表示目标服务器监听端口
$ iperf3 -c 192.168.0.30 -b 1G -t 15 -P 2 -p 10000

测试结束后,在目标服务器查看结果:

[ ID] Interval           Transfer     Bandwidth
...
[SUM]   0.00-15.04  sec  0.00 Bytes  0.00 bits/sec                  sender
[SUM]   0.00-15.04  sec  1.51 GBytes   860 Mbits/sec                  receiver

SUM 行为测试汇总结果,包括测试时间,数据传输量和带宽等。

3 HTTP 性能

可使用 ab、webbench 等 HTTP 压力测试工具。

安装 ab 工具:

# Ubuntu
$ apt-get install -y apache2-utils
# CentOS
$ yum install -y httpd-tools

在目标服务器上启动一个 Nginx 服务:

$ docker run -p 80:80 -itd nginx

在另一台机器上运行 ab 命令,测试 Nginx 服务型:

# -c表示并发请求数为1000,-n表示总的请求数为10000
$ ab -c 1000 -n 10000 http://192.168.0.30/
...
Server Software:        nginx/1.15.8
Server Hostname:        192.168.0.30
Server Port:            80

...

Requests per second:    1078.54 [#/sec] (mean)
Time per request:       927.183 [ms] (mean)
Time per request:       0.927 [ms] (mean, across all concurrent requests)
Transfer rate:          890.00 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   27 152.1      1    1038
Processing:     9  207 843.0     22    9242
Waiting:        8  207 843.0     22    9242
Total:         15  233 857.7     23    9268

Percentage of the requests served within a certain time (ms)
  50%     23
  66%     24
  75%     24
  80%     26
  90%    274
  95%   1195
  98%   2335
  99%   4663
 100%   9268 (longest request)
  • 请求汇总部分

    • 每秒请求数量为 1078
    • 每个请求的延迟分为两行,第一行 927ms 为平均延迟,包括线程运行的调度时间和网络请求响应时间。第二行 0.927ms 为实际请求的响应时间。
    • 吞吐量为 890 KB/s
  • 连接时间汇总部分,展示了建立连接、请求、等待和汇总各类时间。
  • 请求延迟汇总部分,展示了不同时间段内处理请求的百分比,如 90% 的请求都可以在 274ms 内完成。

4 应用负载性能

用户请求中带有的各种负载会影响应用程序内部处理逻辑,从而影响最终的性能。

wrk、TCPCopy、Jmeter 或 LoadRunner 可以模拟用户负载。

安装 wrk:

$ https://github.com/wg/wrk
$ cd wrk
$ apt-get install build-essential -y
$ make
$ sudo cp wrk /usr/local/bin/

测试前面的 Nginx 服务:

# -c表示并发连接数1000,-t表示线程数为2
$ wrk -c 1000 -t 2 http://192.168.0.30/
Running 10s test @ http://192.168.0.30/
  2 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    65.83ms  174.06ms   1.99s    95.85%
    Req/Sec     4.87k   628.73     6.78k    69.00%
  96954 requests in 10.06s, 78.59MB read
  Socket errors: connect 0, read 0, write 0, timeout 179
Requests/sec:   9641.31
Transfer/sec:      7.82MB

每秒请求数为 9641,平均延迟为 65ms,比前面的 ab 测试结果要好一些。说明性能测试工具本身的性能对性能测试也很重要。

为请求设置认证参数:

-- example script that demonstrates response handling and
-- retrieving an authentication token to set on all future
-- requests

token = nil
path  = "/authenticate"

request = function()
   return wrk.format("GET", path)
end

response = function(status, headers, body)
   if not token and status == 200 then
      token = headers["X-Token"]
      path  = "/resource"
      wrk.headers["X-Token"] = token
   end
end

测试时指定脚本路径:

$ wrk -c 1000 -t 2 -s auth.lua http://192.168.0.30/

Jemeter、LoadRunner 针对复杂场景提供了脚本录制、回放、GUI 等更丰富的功能,使用起来也更方便。

参考

倪朋飞. Linux 性能优化实战.