我们说了经典的C10K和C1000K的问题,从C10K中说了对应的epoll网络方案,到C1000K的软硬件的共同优化
最后,实现C10M,就不是物理上可以解决的问题了,内核中的冗长的网络协议栈就是最大负担,这是XDP和DPDK就是解决方案
但是在实际中,我们一般不会单机并发如此多的请求,而是通过调整系统架构,将请求分到多台服务器中处理
对于这种架构,需要我们对每一个服务器的网络性能有一个大概的认知,一直到可以进行调优
对于网络相关性能的指标,常见的有带宽 吞吐量 延迟 PPS等,都是常用的网络性能指标
对于这些指标的具体含义,分别如下
带宽: 链路的最大传输速率,单位是b/s,随着物理网卡而浮动,常见的带宽有 1000M,10G,40G,100G等
吞吐量: 没有丢包的时候最大数据传输速率
延时: 从网络请求发出之后,到收到远端响应,需要的网络延迟
PPS: Packet Per Second 包或者秒的缩写,以网络包为单位的传输速率,PPS评估网络的转发能力,受到网络包大小的影响。
其中指标,最为常见的相关测试是网络带宽测试,但是实际上测试的并不是带宽,而是网络吞吐量,Linux的网络吞吐量比带宽要小,但是对于交换机等专门的传输设备来说,基本上吞吐量等于带宽
最后的PPS,以网络包为单位的传输速率,一般更为常见的是并发连接数和每秒请求数等指标,更加能够反应实际应用程序的性能
接下来,我们说一下如何通过性能测试来确定指标的基准值
但是因为Linux基于多层网络架构,即Linux网络基于TCP/IP协议栈
在多层模型中,我们首先要确定的是,要利用哪一个层次作为测试的基准
比如HTTP或者HTTPS的Web应用程序,明显是属于应用层,需要我们测试这一层的性能
对于游戏 IOT服务端,一般基于TCP或UDP,这就需要我们测试TCP或者UDP性能
或者是Linux作为一个软交换机或者路由器来做,这就是PPS相关处理能力
那我们按照不同的协议层,进行相关的测试工作
对于网络包的处理能力,即PPS的性能,可以使用hpings作为相关的工具,
或者使用pktgen,进行测试目标服务器性能,使用就先不详说了,因为在实际的使用中,并不常见
然后是TCP/UDP性能
掌握了PPS的测试方法,接下来看TCP UDP的性能测试方法,说到TCP UDP的测试,常见比如iperf或者netperf,都是测试网络性能的测试工具,测试TCP UDP的吞吐量,都是利用客户端和服务器端通信的方式,进行测试评估
常见的iperf的操作如下,我们可以如下的使用
首先是在目标机器上启动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
最后服务器给出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行中就是测试的汇总信息,包括了测试的时间 0-15 数据传输量 15GBytes 和带宽 860Mbit/sec
还分为了发送和接收两行
然后是HTTP相关的性能
对于这也难怪,我们常见的测试方式都是并发连接数或者每秒请求数等
对于HTTP的性能,很多的工具都可以测试,比如ab webbench,都是常用的HTTP压力测试工具,ab是Apache自带的HTTP压测工具,HTTP的每秒请求数,延迟 延迟分布情况
对于ab的测试,基本如下
# -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分为了三个部分,请求的汇总,Request Per second 为1074,然后是每个请求的延迟分为了两行,第一行927ms是平均延迟,下一行的0.927ms,则是平均响应时间,Transfer rate 吞吐量为 890KB/s中显示
第二部分是连接时间的汇总,就是建立连接,请求 等待以及汇总的各类时间,最大最小 平均 中位处理时间
最后给出了不同时间段内处理情况,90%的请求,在274ms之内完成
说完了不同段内的测试工具和负载性能
是否可以直接表示应用程序的实际性能了?一般是不太可能的,应用程序基于HTTP协议,一般内部都有着不同的payload
影响着Web应用程序内部的处理逻辑,从而影响最终性能
模拟用户负载的情况下,ab和iperf等工具的作用并不大,但我们可以使用wrk TCPCopy Jmeter LoadRunner实现这个目标
wrk的安装需要我们拉下来代码之后,直接编译源码进行安装,我们可以按照如下的命令,进行编译安装
cd /usr/local/src
yum install git -y
git clone https://github.com/wg/wrk.git
cd wrk
yum -y install gcc
make
ln -s /usr/local/src/wrk/wrk /usr/local/bin
wrk -t 2 -c 50 -d 20 –latency http://localhost:5000
最后wrk -c 1000 -t 2 http://192.168.0.30
测试之后,查看WRK的返回
# -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 |
两个线程,并发1000个连接,测试了Nginx的性能
每秒的请求数是9641,吞吐量为7.82MB,平均延迟为65ms,比之前的ab好得多
wrk还支持使用lua脚本进行构建请求负载,具体细节需要对Lua有一定的了解
相比较之后Jmeter 和 LoadRunner则更加简单,但是是商业化的工具
总结一下今天的网络性能评估
性能评估是优化网络性能的前提,在网络性能瓶颈出现的时候,需要进行网络性能优化,根据TCP/协议栈的原理,进行不同层次的评估
应用层可以进行wrk Jmeter继续用户负载,测试应用内程序的请求数
传输层,使用iperf等工具,测试TCP吞吐情况
向下,可以用Linux自带的pktgen,测试PPS