面向開發(fā)的測(cè)試技術(shù)(二):性能測(cè)試

引子:自上世紀(jì)末Kent Beck提出TDD(Test-Driven Development)開發(fā)理念以來爆侣,開發(fā)和測(cè)試的邊界變的越來越模糊,從原本上下游的依賴關(guān)系雪猪,逐步演變成你中有我、我中有你的互賴關(guān)系,甚至很多公司設(shè)立了新的QE(Quality Engineer)職位纤泵。和傳統(tǒng)的QA(Quality Assurance)不同,QE的主要職責(zé)是通過工程化的手段保證項(xiàng)目質(zhì)量镜粤,這些手段包括但不僅限于編寫單元測(cè)試捏题、集成測(cè)試,搭建自動(dòng)化測(cè)試流程肉渴,設(shè)計(jì)性能測(cè)試等公荧。可以說同规,QE身上兼具了QA的質(zhì)量意識(shí)和開發(fā)的工程能力循狰。我會(huì)從開發(fā)的角度分三期聊聊QE這個(gè)亦測(cè)試亦開發(fā)的角色所需的基本技能,這篇是第二篇券勺。

前情概要:

1 什么是性能測(cè)試绪钥?

先來看一下維基百科里對(duì)性能測(cè)試的定義,

In software engineering, performance testing is in general, a testing practice performed to determine how a system performs in terms of responsiveness and stability under a particular workload. - Wikipedia

注意上述定義中有三個(gè)關(guān)鍵詞:

  • responsiveness关炼,即響應(yīng)時(shí)間程腹,請(qǐng)求發(fā)出去之后,服務(wù)端需要多久才能返回結(jié)果儒拂,顯然響應(yīng)時(shí)間越短寸潦,性能越好。
  • stability社痛,即穩(wěn)定性甸祭,同樣的請(qǐng)求,不同時(shí)刻發(fā)出去褥影,響應(yīng)時(shí)間差別越小池户,穩(wěn)定性越好,性能也越好凡怎。
  • workload校焦,即負(fù)載,同一時(shí)刻服務(wù)端收到的請(qǐng)求數(shù)量统倒,其中單位時(shí)間內(nèi)成功處理的請(qǐng)求數(shù)量即吞吐量寨典,吞吐量越大,性能越好房匆。

響應(yīng)時(shí)間和吞吐量是衡量應(yīng)用性能好壞最重要的兩個(gè)指標(biāo)耸成。對(duì)于絕大多數(shù)應(yīng)用报亩,剛開始的時(shí)候,響應(yīng)時(shí)間最短井氢;隨著負(fù)載的增大弦追,吞吐量快速上升,響應(yīng)時(shí)間也逐漸變長花竞;當(dāng)負(fù)載超過某一個(gè)值之后劲件,響應(yīng)時(shí)間會(huì)突然呈指數(shù)級(jí)放大,同時(shí)吞吐量也應(yīng)聲下跌约急,應(yīng)用性能急劇下降零远,整個(gè)過程如下:

圖片出處:性能測(cè)試應(yīng)該怎么做?

2 性能測(cè)試的目的

了解了應(yīng)用性能變化的普遍規(guī)律厌蔽,性能測(cè)試的目的也就有了答案:針對(duì)某一應(yīng)用牵辣,找出響應(yīng)時(shí)間和吞吐量的量化關(guān)系,找到應(yīng)用性能變化的臨界點(diǎn)奴饮。你可能會(huì)問服猪,知道了這些有什么用呢?在我看來拐云,至少有3個(gè)層面的好處:

第一,有的放矢近她,提高資源利用率叉瘩。性能測(cè)試的過程就是量化性能的過程,有了各種性能數(shù)據(jù)粘捎,你才能對(duì)應(yīng)用性能進(jìn)行定量分析薇缅,找到并解決潛在的性能問題,從而提高資源利用率攒磨。

第二泳桦,科學(xué)的進(jìn)行容量規(guī)劃。找到了應(yīng)用性能變化的臨界點(diǎn)娩缰,也就很容易找到單節(jié)點(diǎn)的性能極限灸撰,這是進(jìn)行容量規(guī)劃的重要決策依據(jù)。比如某一應(yīng)用在單節(jié)點(diǎn)下的極限吞吐量是2000 QPS拼坎,那么面對(duì)10000 QPS的流量浮毯,至少需要部署5個(gè)節(jié)點(diǎn)。

第三泰鸡,改善QoS(Quality of Service)债蓝。很多時(shí)候,資源是有限的盛龄,面對(duì)超出服務(wù)能力的流量饰迹,為了保證QoS芳誓,必須做出取舍(比如限流降級(jí),開關(guān)預(yù)案等)啊鸭,應(yīng)用性能數(shù)據(jù)是設(shè)計(jì)QoS方案的重要依據(jù)锹淌。

3 性能測(cè)試的三個(gè)常見誤區(qū)

誤區(qū)1:只看平均值,不懂TP95/TP99

用平均值來衡量響應(yīng)時(shí)間是性能測(cè)試中最常見的誤區(qū)莉掂。從第1小節(jié)的插圖可以看出葛圃,隨著吞吐量的增大,響應(yīng)時(shí)間會(huì)逐漸變長憎妙,當(dāng)達(dá)到最大吞吐量之后库正,響應(yīng)時(shí)間會(huì)開始加速上升,尤其是排在后面的請(qǐng)求厘唾。在這個(gè)時(shí)刻褥符,如果只看平均值,你往往察覺不到問題抚垃,因?yàn)榇蟛糠终?qǐng)求的響應(yīng)時(shí)間還是很短的喷楣,慢請(qǐng)求只占一個(gè)很小的比例,所以平均值變化不大鹤树。但實(shí)際上铣焊,可能已經(jīng)有超過1%,甚至5%的請(qǐng)求的響應(yīng)時(shí)間已經(jīng)超出設(shè)計(jì)的范圍了罕伯。

更科學(xué)曲伊、更合理的指標(biāo)是看TP95或者TP99響應(yīng)時(shí)間。TP是Top Percentile的縮寫追他,是一個(gè)統(tǒng)計(jì)學(xué)術(shù)語坟募,用來描述一組數(shù)值的分布特征。以TP95為例邑狸,假設(shè)有100個(gè)數(shù)字懈糯,從小到大排序之后,第95個(gè)數(shù)字的值就是這組數(shù)字的TP95值单雾,表示至少有95%的數(shù)字是小于或者等于這個(gè)值赚哗。

以一次具體的性能測(cè)試為例,

總共有1000次請(qǐng)求硅堆,平均響應(yīng)時(shí)間是58.9ms蜂奸,TP95是123.85ms(平均響應(yīng)時(shí)間的2.1倍),TP99是997.99ms(平均響應(yīng)時(shí)間的16.9倍)硬萍。假設(shè)應(yīng)用設(shè)計(jì)的最大響應(yīng)時(shí)間是100ms扩所,單看平均時(shí)間是完全符合要求的,但實(shí)際上已經(jīng)有超過50個(gè)請(qǐng)求失敗了朴乖。如果看TP95或者TP99祖屏,問題就很清楚了助赞。

誤區(qū)2:只關(guān)注響應(yīng)時(shí)間和吞吐量,忽視請(qǐng)求成功率

雖說衡量應(yīng)用性能好壞最主要是看響應(yīng)時(shí)間和吞吐量袁勺,但這里有個(gè)大前提雹食,所有請(qǐng)求(如果做不到所有,至少也要絕大多數(shù)請(qǐng)求期丰,比如99.9%)都被成功處理了群叶,而不是返回一堆錯(cuò)誤碼。如果不能保證這一點(diǎn)钝荡,那么再低的響應(yīng)時(shí)間街立,再高的吞吐量都是沒有意義的。

誤區(qū)3:忘了測(cè)試端也存在性能瓶頸

性能測(cè)試的第三個(gè)誤區(qū)是只關(guān)注服務(wù)端埠通,而忽略了測(cè)試端本身可能也存在限制赎离。比如測(cè)試用例設(shè)置了10000并發(fā)數(shù),但實(shí)際運(yùn)行用例的機(jī)器最大只支持5000并發(fā)數(shù)端辱,如果只看服務(wù)端的數(shù)據(jù)梁剔,你可能會(huì)誤以為服務(wù)端最大就只支持5000并發(fā)數(shù)。如果遇到這種情況舞蔽,或者換用更高性能的測(cè)試機(jī)器荣病,或者增加測(cè)試機(jī)器的數(shù)量。

4 如何進(jìn)行性能測(cè)試渗柿?

介紹完性能測(cè)試相關(guān)的一些概念之后个盆,再來看一下有哪些工具可以進(jìn)行性能測(cè)試。

4.1 JMeter

JMeter可能是最常用的性能測(cè)試工具做祝。它既支持圖形界面,也支持命令行鸡岗,屬于黑盒測(cè)試的范疇混槐,對(duì)非開發(fā)人員比較友好,上手也非常容易轩性。圖形界面一般用于編寫声登、調(diào)試測(cè)試用例,而實(shí)際的性能測(cè)試建議還是在命令行下運(yùn)行揣苏。

image.png

并發(fā)設(shè)置

image.png

請(qǐng)求參數(shù)

image.png

結(jié)果報(bào)表

命令行下的常用命令:

  • 設(shè)置JVM參數(shù):JVM_ARGS="-Xms2g -Xmx2g"
  • 運(yùn)行測(cè)試:jmeter -n -t <jmx_file>
  • 運(yùn)行測(cè)試同時(shí)生成報(bào)表:jmeter -n -t <jmx_file> -l <log_file> -e -o <report_dir>

除了JMeter悯嗓,其他常用的性能測(cè)試工具還有ab, http_load, wrk以及商用的LoaderRunner

4.2 JMH

如果測(cè)試用例比較復(fù)雜卸察,或者負(fù)責(zé)性能測(cè)試的人員具有一定的開發(fā)能力脯厨,也可以考慮使用一些框架編寫單獨(dú)的性能測(cè)試程序。對(duì)于Java開發(fā)人員而言坑质,JMH是一個(gè)推薦的選擇合武。類似于JUnit临梗,JMH提供了一系列注解用于編寫測(cè)試用例,以及一個(gè)運(yùn)行測(cè)試的引擎稼跳。事實(shí)上盟庞,即將發(fā)布的JDK 9默認(rèn)就會(huì)包含JMH。

下面是我GitHub上的示例工程里的一個(gè)例子汤善,

@BenchmarkMode(Mode.Throughput)
@Fork(1)
@Threads(Threads.MAX)
@State(Scope.Benchmark)
@Warmup(iterations = 1, time = 3)
@Measurement(iterations = 3, time = 3)
public class VacationClientBenchmark {

    private VacationClient vacationClient;

    @Setup
    public void setUp() {
        VacationClientConfig clientConfig = new VacationClientConfig("http://localhost:3000");
        vacationClient = new VacationClient(clientConfig);
    }

    @Benchmark
    public void benchmarkIsWeekend() {
        VacationRequest request = new VacationRequest();
        request.setType(PERSONAL);
        OffsetDateTime lastSunday = OffsetDateTime.now().with(TemporalAdjusters.previous(SUNDAY));
        request.setStart(lastSunday);
        request.setEnd(lastSunday.plusDays(1));

        Asserts.isTrue(vacationClient.isWeekend(request).isSuccess());
    }

    // 僅限于IDE中運(yùn)行
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(VacationClientBenchmark.class.getSimpleName())
                .build();

        new Runner(opt).run();
    }
}

其中:

  • @BenchmarkMode: 性能測(cè)試模式什猖,支持Throughput,AverageTime红淡,SingleShotTime等多種模式不狮。
  • @Fork: 設(shè)置運(yùn)行性能測(cè)試的Fork進(jìn)程數(shù),默認(rèn)是0锉屈,表示共用JMH主進(jìn)程荤傲。
  • @Threads: 并發(fā)數(shù),Threads.MAX表示同系統(tǒng)的CPU核數(shù)颈渊。
  • @Warmup和@Measurement: 分別設(shè)置預(yù)熱和實(shí)際性能測(cè)試的運(yùn)行輪數(shù)遂黍,每輪持續(xù)的時(shí)間等
  • @Setup和@Benchmark: 等同于JUnit里的@BeforeClass和@Test

在命令行下,使用JMH框架編寫的性能測(cè)試程序只能以Jar包的形式運(yùn)行(Main函數(shù)固定為org.openjdk.jmh.Main)俊嗽,因此一般會(huì)針對(duì)每個(gè)JMH程序單獨(dú)維護(hù)一個(gè)項(xiàng)目雾家。如果是Maven項(xiàng)目,可以使用官方提供的jmh-java-benchmark-archetype绍豁,如果是Gradle項(xiàng)目芯咧,可以使用jmh-gradle-plugin插件。

4 小結(jié)

以上就是我對(duì)性能測(cè)試的一些見解竹揍,歡迎你到我的留言板分享敬飒,和大家一起過過招。下一篇我將聊一下Web的自動(dòng)化測(cè)試芬位,敬請(qǐng)期待无拗。

5 參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市被饿,隨后出現(xiàn)的幾起案子四康,更是在濱河造成了極大的恐慌,老刑警劉巖狭握,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闪金,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡论颅,警方通過查閱死者的電腦和手機(jī)毕泌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門喝检,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人撼泛,你說我怎么就攤上這事挠说。” “怎么了愿题?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵损俭,是天一觀的道長。 經(jīng)常有香客問我潘酗,道長杆兵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任仔夺,我火速辦了婚禮琐脏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缸兔。我一直安慰自己日裙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布惰蜜。 她就那樣靜靜地躺著昂拂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抛猖。 梳的紋絲不亂的頭發(fā)上格侯,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音财著,去河邊找鬼联四。 笑死,一個(gè)胖子當(dāng)著我的面吹牛撑教,可吹牛的內(nèi)容都是我干的朝墩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼驮履,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼鱼辙!你這毒婦竟也來了廉嚼?” 一聲冷哼從身側(cè)響起玫镐,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怠噪,沒想到半個(gè)月后恐似,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傍念,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年矫夷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了葛闷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡双藕,死狀恐怖淑趾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忧陪,我是刑警寧澤扣泊,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站嘶摊,受9級(jí)特大地震影響延蟹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叶堆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一阱飘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧虱颗,春花似錦沥匈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辨萍,卻和暖如春棋恼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锈玉。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工爪飘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拉背。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓师崎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親椅棺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子犁罩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • 本文翻譯自 Thinking Clearly About Performance 這是我三年前讀到的一篇關(guān)于性能問...
    mindwind閱讀 1,288評(píng)論 1 8
  • 主要文體來自 CDNS:https://www.cnblogs.com/ceshisanren/p/5639895...
    Amano閱讀 10,992評(píng)論 3 27
  • 在使用Jmeter進(jìn)行接口的性能測(cè)試時(shí),由于Jmeter 是JAVA應(yīng)用两疚,對(duì)于CPU和內(nèi)存的消耗比較大床估,所以,當(dāng)需...
    燕京博士閱讀 4,166評(píng)論 0 16
  • 1. JMeter 測(cè)試計(jì)劃 測(cè)試計(jì)劃 使用JMeter進(jìn)行測(cè)試的起點(diǎn)诱渤,是其它JMeter測(cè)試元件的容器丐巫。 線程組...
    alamZheng閱讀 3,355評(píng)論 0 7
  • js計(jì)時(shí)器 time{ } mytime{ } dd{ } 代碼已完畢有不懂聯(lián)系我。
    李仁平閱讀 7,058評(píng)論 0 3