http://blog.csdn.net/ronghuanye/article/details/72955739
一、 wrk部署
1、部署控制机
需要一台机器安装fabric和wrk作为控制机。
第一步:将fabric.rar解压缩后把整个目录上传到控制机的/home目录下
安装包:
cffi-1.9.1.tar.gz
cryptography-1.6.tar.gz
ecdsa-0.13.tar.gz
enum34-1.1.6.tar.gz
Fabric-1.12.0.tar.gz
gmp-6.0.0a.tar.bz2
idna-2.1.tar.gz
install.sh
ipaddress-1.0.17.tar.gz
libffi-devel-3.0.5-3.2.el6.x86_64.rpm
openssl-1.0.2.tar.gz
paramiko-1.15.2.tar.gz
pyasn1-0.1.9.tar.gz
pycparser-2.17.tar.gz
pycrypto-2.6.1.tar.gz
Python-2.7.11.tgz
setuptools-30.2.0.tar.gz
six-1.10.0.tar.gz
zlib-1.2.3-29.el6.x86_64.rpm
zlib-devel-1.2.3-29.el6.x86_64.rpm
自动安装脚本install.sh
#!/bin/bash
#将python环境升级到2.7.11
rpm -ivh zlib-1.2.3-29.el6.x86_64.rpm
rpm -ivh zlib-devel-1.2.3-29.el6.x86_64.rpm
tar -xvf Python-2.7.11.tgz
cd Python-2.7.11
./configure
make all
make install
make clean
make distclean
mv /usr/bin/python /usr/bin/python_old
ln -s /usr/local/bin/python2.7 /usr/bin/python
cd ..
#安装fabric模块
tar -xvf gmp-6.0.0a.tar.bz2
cd gmp-6.0.0
./configure
make
make check
make install
cd ..
tar -xvf setuptools-30.2.0.tar.gz
cd setuptools-30.2.0
python setup.py build
python setup.py install
cd ..
tar -xvf pycrypto-2.6.1.tar.gz
cd pycrypto-2.6.1
export ac_cv_func_malloc_0_nonnull=yes
python setup.py build
python setup.py install
cd ..
tar -xvf pyasn1-0.1.9.tar.gz
cd pyasn1-0.1.9
python setup.py build
python setup.py install
cd ..
rpm -ivh libffi-devel-3.0.5-3.2.el6.x86_64.rpm
tar -xvf pycparser-2.17.tar.gz
cd pycparser-2.17
python setup.py build
python setup.py install
cd ..
tar -xvf cffi-1.9.1.tar.gz
cd cffi-1.9.1
python setup.py build
python setup.py install
cd ..
tar -xvf openssl-1.0.2.tar.gz
cd openssl-1.0.2
./config --prefix=/usr/local/openssl-1.0.2 shared zlib-dynamic enable-camellia
make && make install
ln -s /usr/lib64/libssl.so.1.0.1e /usr/lib64/libssl.so
ln -s /usr/lib64/libcrypto.so.1.0.1e /usr/lib64/libcrypto.so
cd ..
tar -xvf ipaddress-1.0.17.tar.gz
cd ipaddress-1.0.17
python setup.py build
python setup.py install
cd ..
tar -xvf enum34-1.1.6.tar.gz
cd enum34-1.1.6
python setup.py build
python setup.py install
cd ..
tar -xvf six-1.10.0.tar.gz
cd six-1.10.0
python setup.py build
python setup.py install
cd ..
tar -xvf idna-2.1.tar.gz
cd idna-2.1
python setup.py build
python setup.py install
cd ..
tar -xvf cryptography-1.6.tar.gz
cd cryptography-1.6
export C_INCLUDE_PATH=/usr/local/openssl-1.0.2/include
export CPLUS_INCLUDE_PATH=/usr/local/openssl-1.0.2/include
python setup.py build
python setup.py install
cd ..
tar -xvf ecdsa-0.13.tar.gz
cd ecdsa-0.13
python setup.py build
python setup.py install
cd ..
tar -xvf paramiko-1.15.2.tar.gz
cd paramiko-1.15.2
python setup.py build
python setup.py install
cd ..
tar -xvf Fabric-1.12.0.tar.gz
cd Fabric-1.12.0
python setup.py build
python setup.py install
cd ..
第二步:进入/home/fabric目录,给install.sh文件赋执行权限,然后执行
cd/home/fabric
./install.sh
脚本执行完成后查看是否报错,如果报错根据错误信息修正后,再执行脚本。
第三步:验证fabric是否安装成功
python -c "from fabric.api import * ; print env.version"
在控制机上执行上面的命令,显示出版本说明安装成功
如果报错:ERROR:root:code for hash md5 was not found
执行下面命令即可
python
>>>import_hashlib
第一步:将wrk-master.zip上传到控制机的/home目录下,执行解压缩命令
cd/home
unzipwrk-master.zip
第二步:进入/home/wrk-master目录,执行安装命令
cdwrk-master
编译完成之后会在/home/wrk-master目录中生成wrk二进制文件。
第三步:上传delayx.lua文件到控制机的/home/wrk-master/scripts目录下
delayx.lua文件
function delay()
return math.random(${thinktime}, ${thinktime})
end
第四步:上传controller.py、ReadHost.py、clienthosts.txt三个文件到控制机的/home目录下
controller.py文件
#!/usr/bin/python
# -*- coding:utf-8 -*-
from ReadHost import *
from fabric.api import *
from fabric.colors import *
from fabric.context_managers import *
from fabric.state import env
import re
import os
import sys
import datetime
#run test entrance,defin necessary parameter
def runtest():
test_name="test_001" #test case name
threads=4 #numbers of thread of every client host
connections=4 #numbers of connection of every client host
durations=10 #time of test case running
thinktime=2000 #the time interval between requests
url="http://10.41.150.52:8082/job/tcep/" #request URL
dt = datetime.datetime.now()
res_file = "/home/test_result/%s_%s.txt"%(test_name,dt)
res_file = res_file.replace(" ","_")
if os.path.exists("/home/test_result"):
with settings(hide('warnings', 'running', 'stdout', 'stderr'), warn_only=True):
local("touch %s"%res_file)
else:
with settings(hide('warnings', 'running', 'stdout', 'stderr'), warn_only=True):
local("mkdir /home/test_result&&touch %s"%res_file)
with settings(hide('warnings', 'running', 'stdout', 'stderr'), warn_only=True):
execute(runwrk,threads,connections,durations,url,test_name,thinktime,res_file)
with open(res_file,'r') as f:
counts = f.readlines()
if counts:
ltc = CountLTC(res_file)
tps = CountTPS(res_file)
io = CountIO(res_file)
print yellow('Total => [90Percent Latancy:%s] [TPS:%s] [IO:%s]'%(ltc,tps,io))
with settings(hide('warnings', 'running', 'stdout', 'stderr'), warn_only=True):
local("echo 'Total => [90Percent Latancy:%s] [TPS:%s] [IO:%s]' >> %s"%(ltc,tps,io,res_file))
#get client host IP list
env.roledefs['wrk'] = HostList
#get client host password list
env.passwords = HostPswList
#get result function
def GetWrkResult(text):
p1 = '.+?90%\s+(?P<latancy90>\d+\.?\d+\w+)'
p2 = 'Requests/sec:\s+(?P<tps>\d+\.?\d+)'
p3 = 'Transfer/sec:\s+(?P<tps_io>\d+\.?\d+\w+)'
ret = {}
m1 = re.search(p1,text)
m2 = re.search(p2,text)
m3 = re.search(p3,text)
if m1:
ret['latancy90'] = m1.group("latancy90")
ret['tps'] = m2.group("tps")
ret['io'] = m3.group("tps_io")
return ret
#deploy wrk to all client host
@roles("wrk")
@parallel(pool_size=30)
def deploywrk():
with settings(hide('warnings', 'running'), warn_only=True):
run("mkdir -p /home/wrk-master/scripts")
put("/home/wrk-master/wrk","/home/wrk-master/")
run("chmod u+x /home/wrk-master/wrk")
put("/home/wrk-master/scripts/*","/home/wrk-master/scripts/")
#begin to run wrk command in all client host
@roles("wrk")
@parallel
def runwrk(threads,connections,durations,url,test_name,thinktime,res_file):
if threads>connections:
print red("%s:number of connections must be >= threads"%env.host)
return
if thinktime:
CMD = "./wrk -t{th} -c{con} -d{dur}s -T30s --script=./delay.lua --latency {test_url}".format(th=threads,con=connections,dur=durations,test_url=url)
else:
CMD = './wrk -t{th} -c{con} -d{dur}s -T30s --latency {test_url}'.format(th=threads,con=connections,dur=durations,test_url=url)
host_speed_type = list(host_speed_type_define.keys())[list(host_speed_type_define.values()).index(env.host)]
thinktime = speed_type_define[host_speed_type]
WRKDIR = '/home/wrk-master/'
with cd(WRKDIR):
print green('%s:start testing with wrk ...'%env.host)
run("export thinktime=%d&&envsubst '${thinktime}'<./scripts/delayx.lua >delay.lua"%thinktime)
run(CMD + ">%s_%s.result"%(test_name,env.host))
run("rm -f delay.lua")
wrk_ret = GetWrkResult(run("cat %s_%s.result"%(test_name,env.host)))
if wrk_ret:
tmp = '{wrkhost} => [90Percent Latancy:{latancy}] [TPS:{tps}] [IO:{io}] [URL:{test_url}]'.format(wrkhost = env.host,latancy = wrk_ret["latancy90"],tps = wrk_ret["tps"],io = wrk_ret["io"],test_url = url)
local("echo '%s' >> %s"%(tmp,res_file))
print yellow('{wrkhost} => [90Percent Latancy:{latancy}] [TPS:{tps}] [IO:{io}] [URL:{test_url}]'.format(wrkhost = env.host,latancy = wrk_ret["latancy90"],tps = wrk_ret["tps"],io = wrk_ret["io"],test_url = url))
else:
print red("%s:test result is empty!"%env.host)
#count 90Percent Latancy average
def CountLTC(resultfile):
with open(resultfile,'r') as f:
reslist = f.readlines()
reslist = [ s[0] for s in [(res.split('Latancy:')[1].split('] [TPS')) for res in reslist]]
total = 0
for time in reslist:
if time.count('us'):
total = total + float(time.split('.')[0])/1000
else:
if time.count('ms'):
total = total + float(time.split('ms')[0])
else:
total = total + float(time.split('m')[0])*1000
return str(round(total/len(reslist),2)) + 'ms'
#count total TPS
def CountTPS(resultfile):
with open(resultfile,'r') as f:
reslist = f.readlines()
reslist = [ s[0] for s in [(res.split('[TPS:')[1].split('] [IO')) for res in reslist]]
total = 0
for tps in reslist:
total = total + float(tps)
return total
#count total IO
def CountIO(resultfile):
with open(resultfile,'r') as f:
reslist = f.readlines()
reslist = [ s[0] for s in [(res.split('[IO:')[1].split('] [URL')) for res in reslist]]
total = 0
containMB = False
for io in reslist:
if io.count('MB'):
containMB = True
if containMB:
for io in reslist:
if io.count('MB'):
total = total + float(io.split('MB')[0])
else:
if io.count('KB'):
total = total + float(io.split('KB')[0])/1024
else:
for io in reslist:
if io.count('KB'):
total = total + float(io.split('KB')[0])
if containMB:
return str(round(total,2)) + 'MB'
else:
return str(round(total,2)) + 'KB'
ReadHost.py文件
#!/usr/bin/python
# -*- coding:utf-8 -*-
#read client host IP list from clienthost file
#format:['root@10.41.150.177:22', 'root@10.41.139.175:22']
def GetHostList(hostfile):
with open(hostfile,'r') as f:
iplist = f.readlines()
iplist = [ 'root@' + s[0] + ':22' for s in [(ip.split('\t')) for ip in iplist]]
return iplist
#read client host password list from clienthost file
#format:{ 'root@10.41.150.208:22': 'c3E#6Jt(fB6PPj','root@10.41.139.175:22':'TNScP56m#nr2*K'}
def GetHostPswList(hostfile):
with open(hostfile,'r') as f:
iplist = f.readlines()
iplist = [(ip.split('\t')) for ip in iplist]
psw_dic = {}
for s in iplist:
psw_dic['root@' + s[0] + ':22'] = s[1].strip()
return psw_dic
HostList = GetHostList("clienthosts.txt")
HostPswList = GetHostPswList("clienthosts.txt")
if __name__ == '__main__':
print HostList
print HostPswList
clienthosts.txt文件
10.41.26.162 QEn68(Bmy$k7PW
10.41.26.164 Rsf!QB7Qgj7A!3
2、部署压力机
使用多台机器作为压力机,可以使用已经部署好的控制机来部署wrk到所有的压力机。
(此步骤执行一次即可,如果要添加压力机,需要再执行一次)
第一步:远程登录控制机,进入/home 目录
第二步:修改clienthosts.txt文件,添加压力机IP地址和对应的root登录密码,格式如下:
10.41.150.50 AWd(g8hW(QYs62
10.41.150.51 ViLjBp858_H#yB
注意:1、IP和密码之间用tab符隔开
2、最后一条记录不要换行,即不能存在空行
第三步:执行命令fab -fcontroller.py deploywrk
执行命令过程检查是否有报错
二、 Wrk集群压测
使用1台机器作为控制机(部署fabric,控制其他压机机并行执行wrk脚本,收集其他压力机执行结果并在控制机显示测试结果),使用多台机器作为机器压力测试机(部署wrk工具,执行wrk命令向服务器发送http/https请求);在所有压力测试机上部署wrk工具或者执行wrk命令都是通过控制机的python脚本controller.py 实现。
2、执行集群并发测试
第一步:远程登录控制机,进入/home 目录
第二步:修改controller.py脚本,根据需要修改下面的参数:
test_name=”test_001” 测试场景名称,可以自定义
threads=4 每台压力机启动线程数,最好和机器的CPU个数保持一致
connections=1000 每台压力机创建的连接数,必须大于或者等于启动线程数
durations=60 测试脚本运行时长,单位秒
thinktime= 2000 思考时间,每次请求的时间间隔,单位毫秒
url=”https://www.test.com/” 请求发送的地址
第三步:启动集群并发测试,执行命令fab -f controller.py runtest
执行过程监控是否有报错
第四步:查看测试结果,执行完成后控制机上会打印每台压力机的测试结果和总体统计结果
结果格式:压机机ip => [百分之90响应时间][TPS] [每秒网络IO] [测试地址]
测试结果同时保存在/home/test_result/目录下面,文件名格式为:测试场景名称_年月日_时分秒.txt