Apache Bench做壓力測(cè)試


前言

Apache Bench是一個(gè)簡(jiǎn)單易用的壓力測(cè)試工具讽膏,在這里我不想多講抒抬。今天主要說(shuō)的是寫(xiě)一個(gè)py腳本來(lái)自動(dòng)化測(cè)試過(guò)程,以及中間遇到的一些奇葩問(wèn)題杜跷。

測(cè)試腳本

#!/usr/bin/env python
# encoding: utf-8
import sys
import subprocess as sub
import json
import re
import time
store=open(sys.argv[1],'w')
if len(sys.argv)>2:
    total=sys.agrv[2]
else:
    total=10000
if len(sys.argv)>3:
    hostPath=sys.argv[3]
else:
    hostPath='http://127.0.0.1:3000/'
#url=['index','str','json','read','write','chain']
#cocurrency=[8,16,32,64,128,256]
url=['str','json','chain'];cocurrency=[16]
result=dict.fromkeys(url,{})
def parseAB(src,dst):
    src=src.split('\n')
    pattern=re.compile(r'\d+\.{0,1}\d{0,10}')
    for i in range(15,len(src)-10):
        if(src[i].count(':')==0):
            continue
        tmp=src[i].split(':')
        key=tmp[0]
        data=pattern.findall(tmp[1])
        if not data:
            continue
        elif(len(data)>1):
            dst[key]=[]
            for j in data:
                dst[key]=dst[key]+[float(j)]
        else:
            dst[key]=float(data[0])
        dst['percentage']={}
    for i in range(len(src)-10,len(src)):
        tmp=pattern.findall(src[i])
        if(len(tmp)!=2):
            continue
        dst['percentage'][int(tmp[0])]=int(tmp[1])
    return dst

for item in url:
    for c in cocurrency:
        child=sub.check_output('ab -k -n '+str(total)+' -c '+str(c)+' '+hostPath+item,shell=True,close_fds=True)
        #child=sub.Popen('ab -k -n '+str(total)+' -c '+str(c)+' '+hostPath+item,shell=True,close_fds=True,stdout=sub.PIPE)
        result[item][c]={}
        parseAB(child,result[item][c])
        time.sleep(5)

store.write(json.dumps(result));
store.close()

最終得到了一個(gè)包含該框架所有測(cè)試信息的json文件涣旨,之所以采用json這種數(shù)據(jù)格式歪架,是為了方便下一步處理。

解析腳本

#!/usr/bin/env python
# encoding: utf-8

import sys
import json

basePath=''
frame=['express']
data={}

for f in frame:
    data[f]=json.loads(open(basePath+f+'.json','r').read())
url=data[frame[0]].keys()
cocurrency=data[frame[0]][url[0]].keys()
keyList=data[frame[0]][url[0]][cocurrency[0]].keys()
print 'you can get these key:   '+str(keyList)
compare=dict.fromkeys(frame,dict.fromkeys(url,{}))
for f in frame:
    for u in url:
        for k in keyList:
            dataType=type(data[f][u][cocurrency[0]][k])
            if dataType==int or dataType==float:
                tmp=[]
                for c in cocurrency:
                    tmp=tmp+[dataType(data[f][u][c][k])]
                compare[f][u][k]=tmp
            elif dataType==dict:
                percent=data[f][u][cocurrency[0]][k].keys()
                tmp=dict.fromkeys(percent,[])
                for p in percent:
                    for c in cocurrency:
                        tmp[p]=tmp[p]+[data[f][u][c][k][p]]
                compare[f][u][k]=tmp
            elif dataType==list:
                sta=['min','mean','sd','median','max']
                tmp=dict.fromkeys(sta,[])
                for i in range(len(sta)):
                    for c in cocurrency:
                        s=sta[i]
                        tmp[s]=tmp[s]+[data[f][u][c][k][i]]
                compare[f][u][k]=tmp

def get(f,u,k,index=None):
    if k=='percentage':
        if not index:
            return compare[f][u][k]['95']
        else:
            return compare[f][u][k][str(index)]
    elif type(compare[f][u][k])==dict:
        if not index:
            return compare[f][u][k]['mean']
        else:
            return compare[f][u][k][index]
    else:
        return compare[f][u][k]

最終暴露出一個(gè)API接口

import handle
handle.get('express','json','Time per request')
//return an array for all cocurrency you choose

遇到的問(wèn)題

在測(cè)試過(guò)程中(開(kāi)始的腳本不是這個(gè)樣子的霹陡,有略微的改變)到16000+請(qǐng)求的時(shí)候會(huì)卡主和蚪,并最終拋出socket timeout的錯(cuò)誤,錯(cuò)誤碼60.為什么會(huì)這樣子呢烹棉?

是由于系統(tǒng)資源的限制攒霹,socket在unix系統(tǒng)下也是利用文件描述符的,socket的數(shù)量是有限制的浆洗,對(duì)于本人的MAC是16387催束,據(jù)說(shuō)對(duì)于linux系統(tǒng)是32000+,好伏社,找到了問(wèn)題所在抠刺,看來(lái)是子進(jìn)程退出時(shí)沒(méi)有關(guān)閉socket。在python的bug報(bào)告里提到了這個(gè)問(wèn)題摘昌,在subprocess的調(diào)用中加一句close_fds=True可以在子進(jìn)程執(zhí)行之前關(guān)閉除了0速妖,1,2的所有文件描述符聪黎,自然就關(guān)閉了上次操作的所有sockets罕容。

不過(guò),這樣依舊不行稿饰。锦秒。。為什么呢湘纵?因?yàn)椴灰朔?wù)器是localhost脂崔,關(guān)閉這些文件描述符只是客戶端的socket.close()滤淳,意味著文件描述符可以被再次分配梧喷,但服務(wù)端依然保有socket,它的資源沒(méi)有被釋放,限制依舊存在铺敌。想要立即釋放汇歹,我們應(yīng)該用socket.shutdown(),不過(guò)這樣恐怕需要改寫(xiě)subprocess偿凭,顯然蛋疼产弹。

然后我就發(fā)現(xiàn)了我的測(cè)試語(yǔ)句

ab -c 8 -n 10000 http://127.0.0.1:3000/json

對(duì),木有用-k弯囊,keep-alive選項(xiàng)允許socket被復(fù)用痰哨,不只是用于一個(gè)http請(qǐng)求。同時(shí)我還在循環(huán)末尾加了一句sleep以等待資源被釋放匾嘱。剩下的就只能聽(tīng)天由命了斤斧。

還有一個(gè)非常常見(jiàn)的錯(cuò)誤。

ab -c 8 -n 10000 http://localhost:3000/json

寫(xiě)成這樣也會(huì)報(bào)錯(cuò)哦霎烙!

結(jié)語(yǔ)

最后向大家提一個(gè)問(wèn)題撬讽,為什么用Jmeter做壓力測(cè)試的時(shí)候,吞吐量會(huì)一開(kāi)始很高悬垃,然后一直在下降游昼?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市尝蠕,隨后出現(xiàn)的幾起案子烘豌,更是在濱河造成了極大的恐慌,老刑警劉巖看彼,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扇谣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡闲昭,警方通過(guò)查閱死者的電腦和手機(jī)罐寨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)序矩,“玉大人鸯绿,你說(shuō)我怎么就攤上這事◆さ恚” “怎么了瓶蝴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)租幕。 經(jīng)常有香客問(wèn)我舷手,道長(zhǎng),這世上最難降的妖魔是什么劲绪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任男窟,我火速辦了婚禮盆赤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘歉眷。我一直安慰自己牺六,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布汗捡。 她就那樣靜靜地躺著淑际,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扇住。 梳的紋絲不亂的頭發(fā)上春缕,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音艘蹋,去河邊找鬼淡溯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛簿训,可吹牛的內(nèi)容都是我干的咱娶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼强品,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼膘侮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起的榛,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤琼了,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后夫晌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雕薪,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年晓淀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了所袁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凶掰,死狀恐怖燥爷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情懦窘,我是刑警寧澤前翎,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站畅涂,受9級(jí)特大地震影響港华,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜午衰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一立宜、第九天 我趴在偏房一處隱蔽的房頂上張望冒萄。 院中可真熱鬧,春花似錦赘理、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蜘澜,卻和暖如春施流,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鄙信。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工瞪醋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人装诡。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓银受,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鸦采。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宾巍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測(cè)試 ...
    KeKeMars閱讀 6,312評(píng)論 0 6
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)渔伯,斷路器顶霞,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 第一章 Nginx簡(jiǎn)介 Nginx是什么 沒(méi)有聽(tīng)過(guò)Nginx?那么一定聽(tīng)過(guò)它的“同行”Apache吧锣吼!Ngi...
    JokerW閱讀 32,646評(píng)論 24 1,002
  • 家鄉(xiāng)玄叠,滾滾的秋意 文/一笑(長(zhǎng)春) 當(dāng)?shù)谝宦曄x(chóng)鳴 在某個(gè)不經(jīng)意的午后 忽然響起 當(dāng)?shù)谝豢|涼風(fēng) 在某個(gè)沒(méi)來(lái)由的清晨 ...
    一笑塵囂遠(yuǎn)高宏宇閱讀 199評(píng)論 0 0
  • 第57天 姓名:董蘊(yùn)英 公司:沈陽(yáng)建筑裝飾裝修有限公司 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》大綱1遍 共156遍 《大學(xué)》開(kāi)...
    董生活閱讀 178評(píng)論 0 0