WRK+fabric進行叢集部署和壓測
一、 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
指令碼執行完成後檢視是否報錯,如果報錯根據錯誤資訊修正後,再執行指令碼。
在控制機上執行上面的命令,顯示出版本說明安裝成功
執行下面命令即可
python
>>>import_hashlib
第一步:將wrk-master.zip上傳到控制機的/home目錄下,執行解壓縮命令
cd/home
第二步:進入/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:['[email protected]:22', '[email protected]:22']
def GetHostList(hostfile):
with open(hostfile,'r') as f:
iplist = f.readlines()
iplist = [ '[email protected]' + s[0] + ':22' for s in [(ip.split('\t')) for ip in iplist]]
return iplist
#read client host password list from clienthost file
#format:{ '[email protected]:22': 'c3E#6Jt(fB6PPj','[email protected]: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['[email protected]' + 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.164Rsf!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、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/” 請求傳送的地址
執行過程監控是否有報錯
第四步:檢視測試結果,執行完成後控制機上會列印每臺壓力機的測試結果和總體統計結果
結果格式:壓機機ip => [百分之90響應時間][TPS] [每秒網路IO] [測試地址]
測試結果同時儲存在/home/test_result/目錄下面,檔名格式為:測試場景名稱_年月日_時分秒.txt