linux性能优化怎么评估系统的网络性能

Posted sysu_lluozh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux性能优化怎么评估系统的网络性能相关的知识,希望对你有一定的参考价值。

在性能优化从C100K到C1000K时仅仅增加物理资源时不够的,需要对系统的软硬件进行统一优化。从硬件的中断处理,到网络协议栈的文件描述符数量、连接状态跟踪、缓存队列,再到应用程序的工作模型等的整个网络链路,都需要深入优化

在实际的工作项目中,需要评估系统的网络性能以便考察系统的处理能力,并为容量规划提供基准数据

那么,到底该怎么评估网络的性能呢?

一、性能指标回顾

在评估网络性能前,先回顾一下衡量网络性能的指标有哪些
带宽、吞吐量、延时、PPS等都是最常用的网络性能指标,接下来看看它们具体的定义:

  • 带宽

表示链路的最大传输速率,单位是 b/s(比特/秒)
在服务器选购网卡时,带宽就是最核心的参考指标,常用的带宽有1000M、10G、40G、100G等

  • 吞吐量

表示没有丢包时的最大数据传输速率,单位通常为 b/s(比特/秒)或者B/s(字节/秒)
吞吐量受带宽的限制,吞吐量/带宽也就是该网络链路的使用率

  • 延时

表示从网络请求发出后,一直到收到远端响应所需要的时间延迟
这个指标在不同场景中可能会有不同的含义,它可以表示建立连接需要的时间(比如TCP握手延 时),或者一个数据包往返所需时间(比如 RTT)

PPS
Packet Per Second(包/秒)的缩写,表示以网络包为单位的传输速率
PPS通常用来评估网络的转发能力,而基于Linux服务器的转发很容易受到网络包大小的影(交换机通常不会受到太大影响,即交换机可以线性转发)

这四个指标中,带宽跟物理网卡配置是直接关联的
一般来说,网卡确定后带宽也就确定(当然,实际带宽会受限于整个网络链路中最小的那个模块)

另外,很多地方所说的"网络带宽测试",其实测试的实际上不是带宽而是网络吞吐量
Linux服务器的网络吞吐量一般会比带宽小,而对交换机等专门的网络设备来说,吞吐量一般会接近带宽

最后的PPS则是以网络包为单位的网络传输速率,通常用在需要大量转发的场景中
而对TCP或者Web服务来说,更多会用并发连接数和每秒请求数(QPS,Query per Second)等指标,它们更能反应实际应用程序的性能

二、网络基准测试

熟悉网络的性能指标后,接下来看看如何通过性能测试来确定这些指标的基准值

思考一个问题,已经知道Linux网络基于TCP/IP协议栈,而不同协议层的行为显然不同,那么测试之前,应该弄清楚要评估的网络性能究竟属于协议栈的哪 一层?换句话说,应用程序基于协议栈的哪一层呢?

根据TCP/IP协议栈的原理,这个问题应该不难回答。比如:

  • 基于HTTP或者HTTPS的Web应用程序,显然属于应用层,即需要测试HTTP/HTTPS的性能

  • 对大多数游戏服务器来说,为了支持更大的同时在线人数通常会基于TCP或UDP与客户端进行交互,这时就需要测试TCP/UDP的性能

  • 把Linux作为一个软交换机或者路由器来是呀,这种情况下更关注网络包的处理能力(即 PPS),重点关注网络层的转发性能

接下来,从下往上了解不同协议层的网络性能测试方法
不过要注意低层协议是其上的各层网络协议的基础,自然低层协议的性能也就决定了高层的网络性能

三、各协议层的性能测试

3.1 转发性能

首先来看网络接口层和网络层,它们主要负责网络包的封装、寻址、路由以及发送和接收
在这两个网络协议层中,每秒可处理的网络包数PPS,就是最重要的性能指标
特别是64B小包的处理能力值得特别关注。那么,如何来测试网络包的处理能力呢?

说到网络包相关的测试,使用一个相关工具,也就是软中断案例中的hping3
在那个案例中,hping3作为一个 SYN 攻击的工具来使用,实际上hping3更多的用途是作为一个测试网络包处理能力的性能工具

再来介绍另一个更常用的工具,Linux内核自带的高性能网络测试工具pktgen
pktgen支持丰富的自定义选项,方便根据实际需要构造所需网络包从而更准确地测试出目标服务器的性能

不过,在 Linux 系统中并不能直接找到pktgen命令,因为pktgen作为一个内核线程来运行需要加载pktgen内核模块后,再通过/proc文件系统来交互

pktgen启动的两个内核线程和/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

pktgen在每个CPU上启动一个内核线程,并可以通过/proc/net/pktgen下面的同名文件,跟这些线程交互,而pgctrl则主要用来控制这次测试的开启和停止

在使用pktgen测试网络性能时,需要先给每个内核线程kpktgend_X以及测试网卡,配置pktgen选项,然后再通过 pgctrl 启动测试

3.2 TCP/UDP性能

说到TCP和UDP的测试,很可能会想到相应的测试工具比如iperf或者netperf

iperf和netperf都是最常用的网络性能测试工具,测试TCP和UDP的吞吐量。它们都以客户端和服务器通信的方式,测试一段时间内的平均吞吐量

接下来,以iperf为例看一下TCP性能的测试方法
目前,iperf的最新版本为iperf3,可以运行下面的命令来安装:

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

然后,在目标机器上启动iperf服务端:

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

接着,在另一台机器上运行iperf客户端运行测试:

# ‑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

稍等一会儿(15秒)测试结束后,回到目标服务器查看iperf的报告:

[ 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行就是测试的汇总结果,包括测试时间、数据传输量以及带宽等,按照发送和接收,这一部分又分为了sender和receiver两行

从测试结果可以看到,这台机器TCP接收的带宽(吞吐量)为860Mb/s,跟目标的1Gb/s相比还是有些差距的

3.3 HTTP 性能

从传输层再往上到了应用层
有的应用程序会直接基于TCP或UDP构建服务,当然有大量的应用基于应用层的协议来构建服务,HTTP就是最常用的一个应用层协议。比如常用的Apache、nginx等各种Web服务都是基于 HTTP

要测试HTTP的性能有大量的工具可以使用,比如ab、webbench等,都是常用的HTTP压力测试工具
其中,ab是Apache自带的HTTP压测工具,主要测试HTTP服务的每秒请求数、请求延迟、吞吐量以及请求延迟的分布情况等

运行下面的命令安装ab工具:

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

接下来,在目标机器上使用Docker启动一个Nginx服务,然后用ab来测试它的性能
首先,在目标机器上运行下面的命令:

$ 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)

可以看到,ab的测试结果分为三个部分,分别是:

  • 请求汇总
  1. Requests per second为1074
  2. 每个请求的延迟(Time per request)分为两行,第一行的927ms表示平均延迟,包括了线程运行的调度时间和网络请求响应时间,而下一行的0.927ms ,则表示实际请求的响应时间
  3. Transfer rate表示吞吐量(BPS)为890KB/s
  • 连接时间汇总

分别展示了建立连接、请求、等待以及汇总等的各类时间,包括最小、最大、平均以及中值处理时间

  • 请求延迟汇总

给出了不同时间段内处理请求的百分比,比如90%的请求都可以在274ms内完成

3.4 应用负载性能

当使用iperf或者ab等测试工具得到TCP、HTTP等的性能数据后,这些数据是否就能表示应用程序的实际性能呢?答案是否定的

比如,应用程序基于HTTP协议为最终用户提供一个Web服务。这时,使用ab工具可以得到某个页面的访问性能,但这个结果跟用户的实际请求很可能不一致
因为用户请求往往会附带着各种各种的负载(payload),而这些负载会影响Web应用程序内部的处理逻辑,从而影响最终性能

那么,为了得到应用程序的实际性能就要求性能工具本身可以模拟用户的请求负载,而iperf、ab这类工具就无能为力了
幸运的是,可以用wrk、TCPCopy、Jmeter或者LoadRunner等实现这个目标

wrk是一个HTTP性能测试工具,内置了LuaJIT,方便根据实际需求生成所需的请求负载,或者自定义响应的处理方法

wrk工具本身不提供yum或apt的安装方法,需要通过源码编译来安装
可以运行下面的命令编译和安装wrk:

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

wrk的命令行参数比较简单。比如可以用wrk来测试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

使用 2 个线程、并发1000连接测试Nginx的性能,可以看到每秒请求数为9641,吞吐量为7.82MB,平均延迟为65ms,比前面ab的测试结果要好很多

这也说明,性能工具本身的性能对性能测试也是至关重要的,不合适的性能工具并不能准确测出应用程序的最佳性能

当然,wrk最大的优势是其内置的LuaJIT,可以用来实现复杂场景的性能测试
wrk在调用Lua脚本时可以将HTTP请求分为三个阶段,即setup、running、done,如下图所 示:

在这里插入图片描述
比如,可以在setup阶段为请求设置认证参数(wrk官方示例):

‑‑ 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

而在执行测试时,通过-s选项执行脚本的路径:

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

wrk需要用Lua脚本来构造请求负载,这对于大部分场景来说可能已经足够。不过,它的缺点也正是所有东西都需要代码来构造,并且工具本身不提供GUI环境

四、小结

回顾网络的性能指标,并学习网络性能的评估方法

性能评估是优化网络性能的前提,只有在发现网络性能瓶颈时才需要进行网络性能优化
根据TCP/IP协议栈的原理,不同协议层关注的性能重点不完全一样,也就对应不同的性能测试方法,比如:

  • 在应用层,使用wrk、Jmeter等模拟用户的负载,测试应用程序的每秒请求数、处理延迟、错误数等
  • 在传输层,则可以使用iperf等工具, 关注的是TCP、UDP等传输层协议的工作状况,比如TCP连接数、TCP重传、TCP错误数等
  • 在网络层,可以用Linux内核自带的pktgen测试服务器的网络包的处理能力PPS

由于低层协议是高层协议的基础,所以一般情况下需要从上到下对每个协议层进行性能测试,然后根据性能测试的结果结合Linux 网络协议栈的原理,找出导致性能瓶颈的根源,进而优化网络性能

以上是关于linux性能优化怎么评估系统的网络性能的主要内容,如果未能解决你的问题,请参考以下文章

关于linux系统调优这一篇文章就够了

关于linux系统调优这一篇文章就够了

Linux - 网络性能评估

Linux按照CPU内存磁盘IO网络性能监测

磁盘 IO 和网络 IO 该如何评估监控性能定位和优化

linux系统优化