网络带宽压力测试教程_网络压力测试怎么做-程序员宅基地

技术标签: github  git  Linux  网络  压力测试  

1.需要安装一下编译工具,通过运行下面命令来安装工具:


  1. # 安装 make 工具

  2. sudo apt-get install make

  3. # 安装 gcc编译环境

  4. sudo apt-get install build-essential

2、安装完成之后安装git:

2.1.使用git -version命令查看环境是否安装git,如下图:

2.2.如果没安装就使用命令:apt-get install git (需要root权限就使用:sudo apt-get install git )

3、安装完成之后使用 git 下载 wrk 的源码到本地:


  1. #下载命令

  2. git clone https://github.com/wg/wrk.git

  3. #切换路径到wrk目录下

  4. cd wrk

  5. #使用make命令编译环境

  6. make

就 ok了. 
make 成功以后在目录下有一个 wrk 文件. 就是它了. 你可以把这个文件复制到其他目录, 比如 bin 目录. 或者就这个目录下执行. 

如果编译过程中出现:


  1. src/wrk.h:11:25: fatal error: openssl/ssl.h: No such file or directory

  2. #include <openssl/ssl.h>


是因为系统中没有安装openssl的库. 
 

sudo apt-get install libssl-dev 


或 

sudo yum install  openssl-devel 



我们先来做一个简单的性能测试: 
命令如下:

./wrk -t12 -c100 -d30s http://www.baidu.com  

30秒钟结束以后可以看到如下输出: 
 


  1. Running 30s test @ http://www.baidu.com

  2. 12 threads and 100 connections

  3. Thread Stats Avg Stdev Max +/- Stdev

  4. Latency 538.64ms 368.66ms 1.99s 77.33%

  5. Req/Sec 15.62 10.28 80.00 75.35%

  6. 5073 requests in 30.09s, 75.28MB read

  7. Socket errors: connect 0, read 5, write 0, timeout 64

  8. Requests/sec: 168.59

  9. Transfer/sec: 2.50MB


先解释一下输出: 
12 threads and 100 connections 
这个能看懂英文的都知道啥意思: 用12个线程模拟100个连接. 
对应的参数 -t 和 -c 可以控制这两个参数. 

一般线程数不宜过多. 核数的2到4倍足够了. 多了反而因为线程切换过多造成效率降低. 因为 wrk 不是使用每个连接一个线程的模型, 而是通过异步网络 io(异步IO解释见:两段文章清楚弄明白什么是异步IO、同步IO、同步阻塞IO、同步非阻塞IO、异步阻塞IO、异步非阻塞IO_土渣渣的博客-程序员宅基地) 提升并发量. 所以网络通信不会阻塞线程执行. 这也是 wrk 可以用很少的线程模拟大量网路连接的原因. 而现在很多性能工具并没有采用这种方式, 而是采用提高线程数来实现高并发. 所以并发量一旦设的很高, 测试机自身压力就很大. 测试效果反而下降. 

简单说一下wrk里面各个参数什么意思?

  • -t 需要模拟的线程数
  • -c 需要模拟的连接数
  • --timeout 超时的时间
  • -d 测试的持续时间

结果:

  • Latency:响应时间
  • Req/Sec:每个线程每秒钟的完成的请求数

  • Avg:平均
  • Max:最大
  • Stdev:标准差
  • +/- Stdev: 正负一个标准差占比

标准差如果太大说明样本本身离散程度比较高. 有可能系统性能波动很大.

如果想看响应时间的分布情况可以加上--latency参数

在 wrk 的测试结果中,有一项为Requests/sec,我们一般称之为QPS(每秒请求数),这是一项压力测试的性能指标,通过这个参数我们可以看出应用程序的吞吐量。


下面是线程统计: 


  1. Thread Stats Avg Stdev Max +/- Stdev

  2. Latency 538.64ms 368.66ms 1.99s 77.33%

  3. Req/Sec 15.62 10.28 80.00 75.35%



Latency: 可以理解为响应时间, 有平均值, 标准偏差, 最大值, 正负一个标准差占比. 
Req/Sec: 每个线程每秒钟的完成的请求数, 同样有平均值, 标准偏差, 最大值, 正负一个标准差占比. 

一般我们来说我们主要关注平均值和最大值. 标准差如果太大说明样本本身离散程度比较高. 有可能系统性能波动很大. 

接下来:


  1. 5073 requests in 30.09s, 75.28MB read

  2. Socket errors: connect 0, read 5, write 0, timeout 64

  3. Requests/sec: 168.59

  4. Transfer/sec: 2.50MB


30秒钟总共完成请求数和读取数据量. 
然后是错误统计, 上面的统计可以看到, 5个读错误, 64个超时. 
然后是所以线程总共平均每秒钟完成168个请求. 每秒钟读取2.5兆数据量. 

可以看到, 相对于专业性能测试工具. wrk 的统计信息是非常简单的. 但是这些信息基本上足够我们判断系统是否有问题了. 

wrk 默认超时时间是1秒. 这个有点短. 我一般设置为30秒. 这个看上去合理一点. 
如果这样执行命令: 

./wrk -t12 -c100 -d30s -T30s http://www.baidu.com 


可以看到超时数就大大降低了, Socket errors 那行没有了: 


  1. Running 30s test @ http://www.baidu.com

  2. 12 threads and 100 connections

  3. Thread Stats Avg Stdev Max +/- Stdev

  4. Latency 1.16s 1.61s 14.42s 86.52%

  5. Req/Sec 22.59 19.31 108.00 70.98%

  6. 4534 requests in 30.10s, 67.25MB read

  7. Requests/sec: 150.61

  8. Transfer/sec: 2.23MB



通过 -d 可以设置测试的持续时间. 一般只要不是太短都是可以的. 看你自己的忍耐程度了. 
时间越长样本越准确. 如果想测试系统的持续抗压能力, 采用 loadrunner 这样的专业测试工具会更好一点. 

想看看响应时间的分布情况可以加上--latency参数: 

./wrk -t12 -c100 -d30s -T30s --latency http://www.baidu.com  


 


  1. Running 30s test @ http://www.baidu.com

  2. 12 threads and 100 connections

  3. Thread Stats Avg Stdev Max +/- Stdev

  4. Latency 1.22s 1.88s 17.59s 89.70%

  5. Req/Sec 14.47 9.92 98.00 77.06%

  6. Latency Distribution

  7. 50% 522.18ms

  8. 75% 1.17s

  9. 90% 3.22s

  10. 99% 8.87s

  11. 3887 requests in 30.09s, 57.82MB read

  12. Socket errors: connect 0, read 2, write 0, timeout 0

  13. Requests/sec: 129.19

  14. Transfer/sec: 1.92MB


可以看到50%在0.5秒以内, %75在1.2s 以内. 看上去还不错. 

看到这里可能有人会说了, HTTP 请求不会总是这么简单的, 通常我们会有 POST,GET 等多个 method, 会有 Header, 会有 body 等. 

在我第一次知道有 wrk 这个工具的时候他确实还不太完善, 要想测试一些复杂的请求还有点难度. 现在 wrk 支持 lua 脚本. 在这个脚本里你可以修改 method, header, body, 可以对 response 做一下自定义的分析. 因为是 lua 脚本, 其实这给了你无限的可能. 但是这样一个强大的功能如果不谨慎使用, 会降低测试端的性能, 测试结果也受到影响. 

一般修改method, header, body不会影响测试端性能, 但是操作 request, response 就要格外谨慎了. 

我们通过一些测试场景在看看怎么使用 lua 脚本. 

POST + header + body. 

首先创建一个 post.lua 的文件: 


  1. wrk.method = "POST"

  2. wrk.body = "foo=bar&baz=quux"

  3. wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"


就这三行就可以了, 当然 headers 可以加入任意多的内容. 
然后执行: 

./wrk -t12 -c100 -d30s -T30s --script=post.lua --latency http://www.baidu.com  


当然百度可能不接受这个 post 请求. 

对 wrk 对象的修改全局只会执行一次. 
通过 wrk 的源代码可以看到 wrk 对象的源代码有如下属性: 


  1. local wrk = {

  2. scheme = "http",

  3. host = "localhost",

  4. port = nil,

  5. method = "GET",

  6. path = "/",

  7. headers = {},

  8. body = nil,

  9. thread = nil,

  10. }


schema, host, port, path 这些, 我们一般都是通过 wrk 命令行参数来指定. 



wrk 提供的几个 lua 的 hook 函数: 

setup 函数 
这个函数在目标 IP 地址已经解析完, 并且所有 thread 已经生成, 但是还没有开始时被调用. 每个线程执行一次这个函数. 
可以通过thread:get(name),  thread:set(name, value)设置线程级别的变量. 

init 函数 
每次请求发送之前被调用. 
可以接受 wrk 命令行的额外参数. 通过 -- 指定. 

delay函数 
这个函数返回一个数值, 在这次请求执行完以后延迟多长时间执行下一个请求. 可以对应 thinking time 的场景. 

request函数 
通过这个函数可以每次请求之前修改本次请求的属性. 返回一个字符串. 这个函数要慎用, 会影响测试端性能.

response函数 
每次请求返回以后被调用. 可以根据响应内容做特殊处理, 比如遇到特殊响应停止执行测试, 或输出到控制台等等. 


  1. function response(status, headers, body)

  2. if status ~= 200 then

  3. print(body)

  4. wrk.thread:stop()

  5. end

  6. end


done函数 
在所有请求执行完以后调用, 一般用于自定义统计结果.


  1. done = function(summary, latency, requests)

  2. io.write("------------------------------\n")

  3. for _, p in pairs({ 50, 90, 99, 99.999 }) do

  4. n = latency:percentile(p)

  5. io.write(string.format("%g%%,%d\n", p, n))

  6. end

  7. end



下面是 wrk 源代码中给出的完整例子: 
 



测试复合场景时, 也可以通过 lua 实现访问多个 url. 
例如这个复杂的 lua 脚本, 随机读取 paths.txt 文件中的 url 列表, 然后访问.: 


  1. counter = 1

  2. math.randomseed(os.time())

  3. math.random(); math.random(); math.random()

  4. function file_exists(file)

  5. local f = io.open(file, "rb")

  6. if f then f:close() end

  7. return f ~= nil

  8. end

  9. function shuffle(paths)

  10. local j, k

  11. local n = #paths

  12. for i = 1, n do

  13. j, k = math.random(n), math.random(n)

  14. paths[j], paths[k] = paths[k], paths[j]

  15. end

  16. return paths

  17. end

  18. function non_empty_lines_from(file)

  19. if not file_exists(file) then return {} end

  20. lines = {}

  21. for line in io.lines(file) do

  22. if not (line == '') then

  23. lines[#lines + 1] = line

  24. end

  25. end

  26. return shuffle(lines)

  27. end

  28. paths = non_empty_lines_from("paths.txt")

  29. if #paths <= 0 then

  30. print("multiplepaths: No paths found. You have to create a file paths.txt with one path per line")

  31. os.exit()

  32. end

  33. print("multiplepaths: Found " .. #paths .. " paths")

  34. request = function()

  35. path = paths[counter]

  36. counter = counter + 1

  37. if counter > #paths then

  38. counter = 1

  39. end

  40. return wrk.format(nil, path)

  41. end



关于 cookie 
有些时候我们需要模拟一些通过 cookie 传递数据的场景. wrk 并没有特殊支持, 可以通过 wrk.headers["Cookie"]="xxxxx"实现. 
下面是在网上找的一个离职, 取 Response的cookie作为后续请求的cookie 

代码:


  1. function getCookie(cookies, name)

  2. local start = string.find(cookies, name .. "=")

  3. if start == nil then

  4. return nil

  5. end

  6. return string.sub(cookies, start + #name + 1, string.find(cookies, ";", start) - 1)

  7. end

  8. response = function(status, headers, body)

  9. local token = getCookie(headers["Set-Cookie"], "token")

  10. if token ~= nil then

  11. wrk.headers["Cookie"] = "token=" .. token

  12. end

  13. end

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012841092/article/details/125924792

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签