安装
1 | sudo yum groupinstall 'Development Tools' |
环境要求:Linux、Mac
特性:很少的线程压出大并发量
原理:使用操作系统特定高性能 IO 机制,select、epoll、kquue等,复用 redis 的 ae 异步事件驱动框架
缺点:仅支持单机压测
同类型测试工具:JMeter, LoadRunner
测试结果
./wrk -c 1 -t 1 -d 1 http://www.baidu.com
将可执行文件移动到 /usr/local/bin 位置
sudo cp wrk /usr/local/bin
wrk 参数说明
- -t 需要模拟的线程数
- -c 需要模拟的连接数
- -timeout 超时时间
- -d 测试持续时间
结果说明
- Latency
响应时间
- Req/Sec
每个线程每秒完成的请求数
- Avg
平均
- Max
最大
- Stdev
标准差
- +/- Stdev
正负一个标准差占比
高级用法
搭配 lua 使用:启动阶段、运行阶段和结束阶段,对压测进行个性化
setup()
这个函数在目标 IP 地址已经解析完, 并且所有 thread 已经生成, 但是还没有开始时被调用. 每个线程执行一次这个函数.
可以通过thread:get(name), thread:set(name, value)设置线程级别的变量.
init()
每次请求发送之前被调用.
可以接受 wrk 命令行的额外参数. 通过 – 指定.
delay()
这个函数返回一个数值, 在这次请求执行完以后延迟多长时间执行下一个请求. 可以对应 thinking time 的场景.
request()
通过这个函数可以每次请求之前修改本次请求的属性. 返回一个字符串. 这个函数要慎用, 会影响测试端性能.
response()
每次请求返回以后被调用. 可以根据响应内容做特殊处理, 比如遇到特殊响应停止执行测试, 或输出到控制台等等.
done()
在所有请求执行完以后调用, 一般用于自定义统计结果.
自定义 Lua 脚本中可访问的变量以及方法
1 | wrk = { |
Lua
安装
1 | wget http://www.lua.org/ftp/lua-5.3.4.tar.gz |
winodw 安装 Lua
本站下载地址 LuaForWindows_v5.1.4-46
执行 lua
方式①
1 | lua xxx.lua |
方式②
1 | --xxx.lua 起始位置 |
为脚本添加可执行权限,执行脚本:
cd 脚本目录 -> ./xxx.lua
退出交互式编程
Ctrl+D、Ctrl+C、os.exit()
基本语法
Lua 是一个区分大小写的编程语言
注释
- - 单行注释
- -[[
多行注释
- -]]
*推荐使用
- -[=[多行注释]=]
标识符
定义变量,[a-Z_] + [a-Z_0-9],不建议使用 _ + [A-Z]
,Lua 保留字
全局变量
默认情况下,变量总认为是全局的,删除全局变量,将变量设为 nil
1 | b = nil |
数据类型
nil、boolean、number、string、userdata、function、thread、table
nil:空,任何值设为 nil,等价于删除
boolean:(false、nil) => false,其余都是 true
number:双精度实浮点数
string:‘...’
“...”
[[...]]
function:C、Lua编写函数
userdata:C数据结构
thread:最主要的线程是协同程序(coroutine)
table:关联数组,数组的索引(数字、字符串、表类型),创建通过’构造表达式’完成,索引从’1’开始,长度会自动增长,没初始的 table 都是 nil
类型检查:type(
print)
[注意
]数字字符串
和 数字
做运算,优先转数值类型
字符串相连:'..'
#
:计算字符串的长度,其实是字符串所占的字节数长
table
1 | tbl = {'apple', 'pear', 'orange', 'banana'} |
注意
:#table 返回第一个 nil 前值的下标
线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停
变量
全局变量、局部变量、表达式中的域
local:声明局部变量,生命周期(从声明位置 -> 语句块结束)
多变量赋值:a, b = 10, 2*x
,同时赋值,不会进行变量传递
局部变量的好处:
- 避免命名冲突
- 访问局部变量的速度比全局变量更快
函数
可变参数: '...'
1 | function add(...) |
获取可变参数数量的方式:
- #{…}
- select(“#”, …)
多返回值的函数赋值时,只有最后一个函数才会展开:local b,c,d,e = add(),add()
运算符优先级
1 | ^ |
字符串操作方法
upper、lower
string.gsub(操作的字符串,被替换的字符,要替换的字符,替换次数)
string.gsub("aaaa","a","z", 3)
string.find(操作的字符串,要查找的字符,从何位置开始):返回第一次符合要求的索引
string.char(arg):整型数字转字符连接
string.byte(arg,int[返回第几个,默认第一个]):字符转整数值
string.rep(操作字符串,重复次数)
string.match
string.sub
字符串格式化
string.format()
%c:数字,转ascii码
%d,%i:数字,转有符号整数
%o:数字,转8进制
%u:数字,转无符号整数
%x:数字,转十六进制,使用小写字母
%X:数字,转十六进制,使用大写字母
%e:数字,转科学计数,小写字母e
%E:数字,转科学计数,大写字母E
%f:数字,转浮点数
%q:字符串,转可被Lua编译器读入的格式
%s:字符串,按照给定参数格式转
迭代器
Lua中迭代器支持指针类型,分为无状态、有状态两种迭代器
- pairs 和 ipairs 区别
pairs:迭代 table,可以遍历表中所有key,可以返回 nil
ipairs:迭代数组,不能返回 nil,遇到则退出
三个值:迭代器,状态常量,控制变量
Table 常用操作
table.concat(数据,连接符,起始位置,结束位置)
table.insert(数据,插入位置,插入值)
table.maxn
table.remove
table.sort
模块及包
Lua 模块是由变量、函数等已知元素组成的 table
1 | module = {} |
加载模块
1 | require("module") |
加载机制
- 自定义的模块,不是放在哪个文件目录都行
- require 有自己的文件路径加载策略
- require 用于搜索 Lua 文件的路径存放在全局变量 package.path,Lua 启动时,环境变量 LUA_PATH 初始化,如果找不到环境变量,编译时定义的默认路径初始化
LUA_PATH:根目录 .profile.bashrc
1 | #LUA_PATH |
C包
使用前必须先加载并连接,实现方式通过动态连接库机制(loadlib()
)
local f = loadlib(path【绝对地址】, “luaopen_socket”【初始化函数】)
- 使用 require 函数加载 C 库
修改 stub 文件对应二进制库的实际路径,将 stub 文件所在的目录加入到 LUA_PATH
元表 Metatable
支持多 table 操作
setmetatable(tbale, metatable):设置元表,存在‘__metatable ’
,则报错
getmetatable(table):获取元表
__index
__index = [tbale, function(table, key)]
Lua 查找元素的规则步骤:
- 表中查找,& 返回 | 继续
- 判断表中是否有元表,& 继续| 返回 nil
- 判断元表有没有 __index 方法,& (表,重复1,2,3;函数,返回值) | 返回 nil
__newindex
为表添加操作符
1 | function table_maxn(t) |
__add => +
__sub => -
__mul => *
__div => /
__mod => %
__unm => -
__concat => ..
__eq => ==
__lt => <
__le => <=
__Call 调用值时调用该方法
__tostring 修改表的输出行为
协同程序
Lua 协同程序与线程比较类似:拥有独立的堆栈、独立的局部变量、独立的指令指针,与其它协同程序,共享全局变量等
线程、协同程序的区别:
- 拥有多线程的程序可以同时运行几个线程,协同程序需要彼此协作运行
- 任一指定时候,只有一个协同程序运行,运行中的协同程序只有被挂起的时候才会挂起
- 协同程序类似同步的多线程,在等待同一个线程锁的多线程类似协同
语法
coroutine.create() suspended
coroutine.resume() running
返回值 boolean
coroutine.yield():挂起 suspended
coroutine.status():状态【dead、suspended、running】
coroutine.wrap()
coroutine.running()
return dead
1 | local npro |
coroutine.creat、coroutine.wrap 区别
create 返回协同程序,类型 thread,使用 resume 调用
wrap 返回普通函数,类型 function,不可以使用 resume 调用
1 | function yieldReturn(arg) return arg end |
I/O 操作
读取、处理文件
简单模式:
单输入文件 -> 单输出文件
安全模式:
文件句柄,面向对象的形式
打开文件
file = io.open(filename, [mode])
mode 值:
r、r+:只读,文件必须存在
w、w+:只写,文件存在则内容清空,文件不存在则创建
a、a+:追加,文件存在则追加内容,文件不存在则创建
b:二进制模式
+:可读模式
常用方法
io.open
io.input
io.close
io.output
io.write
io.tmpfile
io.type
io.flush
io.lines
1 | file = io.input('path', 'r') |
完全模式
1 | file = io.open('path', 'r') |
file:seek() 设置、获取文件位置
file:flush() 向文件写入缓冲中的所有数据
1 | for line in io.lines('path') do |
- *n 读取一个数字返回
- *a 从当前位置读取整个文件
- *| 读取下一行
- number 返回指定个数的字符串
错误处理
- 语法错误
- 运行错误
处理错误
assert()、error()
pcall()、xpcall()、debug()
1 | function myfunction () |
Debug
debug()
getfenv()
gethook()
getinfo()
debug.getlocal()
getmetatable()
getregistry()
getupvalue()
sethook()
setlocal()
setmetatable()
setupvalue()
trackback()
调试类型
命令行调试器有:RemDebug、clidebugger、ctrace、xdbLua、LuaInterface - Debugger、Rldb、ModDebug
图形界调试器有:SciTE、Decoda、ZeroBrane Studio、akdebugger、luaedit
垃圾回收
collectgarbage(‘collect|count|restart|setpause|setstepmul|setp|stop’)
一次完整的垃圾收集循环、以K字节数返回使用总内参数、重启垃圾收集器、将arg设为收集器的间歇率、单步运行垃圾收集器、停止
面向对象
1 |
|
数据库访问
支持的数据库有:ODBC, ADO, Oracle, MySQL, SQLite 和 PostgreSQL
LuaRocks 安装方法
1 | wget http://luarocks.org/releases/luarocks-2.2.1.tar.gz |
安装数据库
1 | luarocks install luasql-sqlite3 |
*安装 mysql 报错*
luarocks install luasql-mysql MYSQL_INCDIR=/usr/include/mysql MYSQL_LIBDIR=/usr/local/mysql/lib
1 |
|
luarocks几个常用命令
build
download
help
list
install
make
pack
path
remove
search
show
unpack