工具選型全解析:從并發(fā)模型到容量評(píng)估的實(shí)戰(zhàn)指南)
很多做后端和運(yùn)維的朋友遲早都會(huì)碰到同一個(gè)問(wèn)題系統(tǒng)上線前到底抗不扛得住真實(shí)流量尤其電商大促、整點(diǎn)秒殺、月末結(jié)算這類場(chǎng)景留給測(cè)試的時(shí)間窗口很短但壓測(cè)結(jié)論卻直接決定了要不要再加機(jī)器、要不要砍功能、能不能按時(shí)上線。壓測(cè)本身不是新鮮事真正的難點(diǎn)在于選哪把工具去壓以及怎么理解壓測(cè)出來(lái)的那一堆數(shù)字。這么多年下來(lái)我先后在團(tuán)隊(duì)里引入過(guò)好幾套壓測(cè)方案從早期拿命令行工具臨時(shí)頂一下到后來(lái)搭建統(tǒng)一的壓測(cè)平臺(tái)踩過(guò)不少坑也沉淀了些比較成熟的經(jīng)驗(yàn)。這篇就把壓測(cè)工具選型這件事完完整整拆開(kāi)聊一遍。1. 選型之前先想清楚壓測(cè)到底要回答什么問(wèn)題1.1 性能測(cè)試不只是壓一壓看掛不掛很多人對(duì)壓測(cè)有個(gè)誤解覺(jué)得壓測(cè)就是拿工具狠命打接口打到報(bào)錯(cuò)為止看哪個(gè)接口先扛不住修好再打。如果只是為了這個(gè)目的那用什么工具差別不大ab、wrk都?jí)蛴昧?。但真?shí)項(xiàng)目里壓測(cè)要回答的問(wèn)題遠(yuǎn)不止掛不掛而是要做三件事第一評(píng)估系統(tǒng)當(dāng)前容量天花板也就是最大能支撐多少并發(fā)、多少Q(mào)PS、多少吞吐第二定位性能瓶頸到底在哪一層是數(shù)據(jù)庫(kù)慢查詢、Redis連接耗盡、線程池排隊(duì)還是網(wǎng)絡(luò)帶寬打滿第三驗(yàn)證容量規(guī)劃是否合理比如預(yù)估要支撐2000 QPS用現(xiàn)在的集群配置到底能不能扛住差多少量級(jí)。想清楚這三個(gè)問(wèn)題你會(huì)發(fā)現(xiàn)壓測(cè)工具選型根本不是哪個(gè)工具比較火的問(wèn)題而是哪個(gè)工具能幫你把這三個(gè)問(wèn)題回答完整的問(wèn)題。舉個(gè)例子如果你只想知道單接口最高能承受多少Q(mào)PS那ab就足夠但如果你想分析一個(gè)下單鏈路里商品查詢、庫(kù)存扣減、優(yōu)惠計(jì)算、訂單落庫(kù)各環(huán)節(jié)的耗時(shí)分布那ab這種只報(bào)一個(gè)總吞吐、一個(gè)平均延遲的工具就完全不夠看了。1.2 壓測(cè)腳本本質(zhì)上是用戶行為的建模第二個(gè)容易忽略的點(diǎn)是壓測(cè)腳本不是請(qǐng)求發(fā)送腳本而是用戶行為模型。你寫(xiě)壓測(cè)腳本的過(guò)程本質(zhì)上是把真實(shí)用戶的操作路徑抽象成可量化的請(qǐng)求序列和參數(shù)分布。真實(shí)場(chǎng)景里沒(méi)有用戶會(huì)一秒鐘點(diǎn)十次下單按鈕也沒(méi)有用戶會(huì)平均分布在每個(gè)接口上。所以腳本里要體現(xiàn)的是用戶的思考時(shí)間think time、操作比例比如瀏覽和下單大概是多少比、數(shù)據(jù)分布比如用戶ID集中在幾個(gè)大號(hào)還是均勻分布這些都會(huì)直接影響壓測(cè)結(jié)論的參考價(jià)值。這也是選型時(shí)的關(guān)鍵分水嶺有些工具天然適合做輕量級(jí)并發(fā)測(cè)試腳本就是一個(gè)URL加幾個(gè)參數(shù)有些工具則內(nèi)置了比較完整的事務(wù)、斷言、關(guān)聯(lián)、參數(shù)化能力能把一個(gè)多步驟的業(yè)務(wù)流程模擬得比較像樣。選型之前先問(wèn)問(wèn)你團(tuán)隊(duì)里負(fù)責(zé)寫(xiě)腳本的人是誰(shuí)他準(zhǔn)備把用戶行為模型建模到什么程度這決定了你需要的是請(qǐng)求生成器還是壓測(cè)平臺(tái)。2. 主流壓測(cè)工具橫向能力摸底2.1 老牌勁旅與后起之秀的定位差異現(xiàn)在市面上能叫得上名字的壓測(cè)工具大致可以分成四類。第一類是老牌重量級(jí)工具比如JMeter它憑借豐富的插件生態(tài)和超長(zhǎng)的歷史沉淀依然是很多公司的默認(rèn)選擇第二類是面向大規(guī)模模擬的新生代工具比如Gatling、k6這類工具在腳本表達(dá)力、資源開(kāi)銷(xiāo)和報(bào)表展示上做了大量現(xiàn)代化改進(jìn)第三類是開(kāi)發(fā)者友好型的工具比如Locust用Python寫(xiě)壓測(cè)腳本對(duì)研發(fā)團(tuán)隊(duì)來(lái)說(shuō)上手門(mén)檻很低第四類是輕量級(jí)命令行工具比如ab、wrk、hey適合快速驗(yàn)證、臨時(shí)壓測(cè)和性能基準(zhǔn)對(duì)比。這幾類工具不是同一個(gè)賽道上的競(jìng)品用哪一個(gè)最好來(lái)選型是誤區(qū)。更合理的思路是先把它們放進(jìn)同一個(gè)能力坐標(biāo)系里去看腳本表達(dá)能力、分布式擴(kuò)展能力、性能數(shù)據(jù)采集豐富度、與CI/CD集成便捷度、報(bào)表與結(jié)果分析能力、團(tuán)隊(duì)學(xué)習(xí)成本。把這六個(gè)維度擺出來(lái)工具之間的差異就非常直觀了。維度JMeterGatlingk6Locustwrk/ab/hey腳本方式GUI配置為主Scala DSLJavaScript/GoPython命令行參數(shù)分布式壓測(cè)支持需配置Agent支持架構(gòu)較重支持云原生友好內(nèi)置Master/Slave單機(jī)為主指標(biāo)采集強(qiáng)支持二次開(kāi)發(fā)強(qiáng)圖表精美強(qiáng)內(nèi)置豐富指標(biāo)中依賴InfluxDB/Grafana弱僅基礎(chǔ)吞吐指標(biāo)CI/CD集成一般需插件配合一般優(yōu)秀為CI而生一般簡(jiǎn)單但作用有限學(xué)習(xí)成本低GUI深用則高高需懂Scala中需懂JS低Python極低報(bào)告呈現(xiàn)一般需插件增強(qiáng)優(yōu)秀良好依賴外部組件簡(jiǎn)陋2.2 各工具的適用邊界要?jiǎng)澢宄﨡Meter的優(yōu)勢(shì)在于它的生態(tài)幾乎你能想到的協(xié)議都有對(duì)應(yīng)的插件HTTP、JDBC、JMS、TCP、FTP一應(yīng)俱全很多老項(xiàng)目的性能測(cè)試用例是用它沉淀下來(lái)的新同學(xué)接手也方便。但它有幾個(gè)比較難受的點(diǎn)一是線程模型不高效模擬千級(jí)并發(fā)時(shí)本機(jī)資源消耗很大通常需要拆到多臺(tái)壓力機(jī)做分布式二是腳本維護(hù)偏重一旦業(yè)務(wù)流程變動(dòng)改腳本的工作量不小三是指標(biāo)在GUI里看還行想輸出給團(tuán)隊(duì)或接監(jiān)控平臺(tái)還得自己寫(xiě)插件。Gatling是好東西Scala DSL寫(xiě)出來(lái)的腳本可讀性很強(qiáng)天生異步架構(gòu)單機(jī)就能模擬很高的并發(fā)量生成的HTML報(bào)告非常漂亮有響應(yīng)時(shí)間分布圖、并發(fā)用戶隨時(shí)間變化圖這些對(duì)做匯報(bào)和性能分析特別有用。但問(wèn)題也很直接團(tuán)隊(duì)里得有愿意寫(xiě)Scala的人否則腳本維護(hù)就是個(gè)大坑。k6這幾年很火它的設(shè)計(jì)哲學(xué)很現(xiàn)代腳本用JavaScript寫(xiě)把壓測(cè)腳本當(dāng)作代碼工程管理內(nèi)置的指標(biāo)系統(tǒng)非常完善還支持將壓測(cè)結(jié)果輸出到InfluxDB、Prometheus等主流監(jiān)控體系。它也是目前做CI/CD集成的第一梯隊(duì)選擇能在流水線里作為質(zhì)量門(mén)禁跑冒煙壓測(cè)。代價(jià)是它的UI能力比較弱復(fù)雜場(chǎng)景編排不支持畫(huà)流程圖那種點(diǎn)選設(shè)計(jì)。Locust如果團(tuán)隊(duì)Python基礎(chǔ)好用起來(lái)是很舒服的純粹用代碼定義用戶行為支持自定義請(qǐng)求函數(shù)、動(dòng)態(tài)參數(shù)關(guān)聯(lián)、運(yùn)行中實(shí)時(shí)修改并發(fā)數(shù)。它的短板是性能和指標(biāo)采集相對(duì)偏弱單機(jī)大規(guī)模模擬時(shí)Python的協(xié)程優(yōu)勢(shì)能撐住不少并發(fā)但數(shù)據(jù)采集和圖表往往需要自己搭一套時(shí)序存儲(chǔ)加可視化工作量都轉(zhuǎn)移給了使用者。wrk、ab這類輕量工具我的定位是探針型工具適合開(kāi)發(fā)自測(cè)、上線前快速驗(yàn)證、或者做基準(zhǔn)性能參考。它們安裝簡(jiǎn)單、命令直觀、結(jié)果出得快但幾乎沒(méi)有場(chǎng)景建模能力也沒(méi)有分布式能力。拿它們做正式的容量評(píng)估報(bào)告說(shuō)服力是不夠的。3. 決定選型成敗的四個(gè)技術(shù)細(xì)節(jié)3.1 并發(fā)模型決定資源開(kāi)銷(xiāo)的上限選型時(shí)最容易被忽視的是壓測(cè)機(jī)的資源開(kāi)銷(xiāo)。壓測(cè)工具本身也要消耗CPU、內(nèi)存、文件描述符。輕量級(jí)工具比如wrk用的是基于epoll的事件驅(qū)動(dòng)模型單線程能扛幾萬(wàn)個(gè)連接Gatling、k6也是異步引擎資源利用效率很高但JMeter每個(gè)線程用戶虛擬用戶都要占用一個(gè)Java線程模擬500個(gè)并發(fā)時(shí)壓測(cè)機(jī)資源就已經(jīng)明顯吃緊想要模擬幾千并發(fā)就得堆多臺(tái)壓測(cè)機(jī)。這里有個(gè)非常經(jīng)典的選型判斷方法估算你的場(chǎng)景規(guī)模再估算壓測(cè)機(jī)資源。比如你想模擬3000并發(fā)用戶JMeter跑在4核8G的節(jié)點(diǎn)上線程數(shù)開(kāi)3000只的話你自己的壓測(cè)機(jī)可能先被GC拖垮出來(lái)的數(shù)據(jù)本身就不可信了換成Gatling或k6同樣一臺(tái)機(jī)器也許能撐住這個(gè)量級(jí)。所以先算清楚資源賬再定工具不要等壓測(cè)壓到一半發(fā)現(xiàn)壓測(cè)機(jī)才是瓶頸。3.2 腳本表達(dá)能力決定能模擬多復(fù)雜的場(chǎng)景第二個(gè)技術(shù)細(xì)節(jié)是腳本表達(dá)力。真實(shí)業(yè)務(wù)壓測(cè)里幾乎必然會(huì)遇到這些問(wèn)題請(qǐng)求之間有關(guān)聯(lián)上一個(gè)接口返回的token要帶進(jìn)下一個(gè)接口、參數(shù)有業(yè)務(wù)約束比如訂單號(hào)不能重復(fù)、用戶ID要落在指定范圍、不同請(qǐng)求的權(quán)重需要調(diào)整比如95%流量是查商品詳情5%流量是提交訂單、甚至某些請(qǐng)求要依賴前面請(qǐng)求的數(shù)據(jù)分布。這些能不能方便地寫(xiě)出來(lái)直接決定你的壓測(cè)腳本是玩具還是生產(chǎn)可用。用JMeter做關(guān)聯(lián)要加正則表達(dá)式提取器、JSON提取器配合BeanShell或JSR223腳本用Locust做關(guān)聯(lián)就是寫(xiě)Python函數(shù)邏輯怎么復(fù)雜都能寫(xiě)用k6做關(guān)聯(lián)就是JavaScript代碼內(nèi)置API豐富處理響應(yīng)數(shù)據(jù)、生成動(dòng)態(tài)參數(shù)都很順手。如果你要壓測(cè)的是一個(gè)鏈路很長(zhǎng)的核心接口腳本表達(dá)能力不夠最后只能退化成只測(cè)單個(gè)接口那壓測(cè)結(jié)論的價(jià)值就要打折扣。3.3 指標(biāo)采集完備度決定能不能精準(zhǔn)定位問(wèn)題壓測(cè)跑完如果只有平均延遲和QPS并不能告訴你系統(tǒng)瓶頸在哪。完整指標(biāo)應(yīng)該至少包括TPS/QPS、響應(yīng)時(shí)間分布的P50/P95/P99、錯(cuò)誤率、線程池活躍度、隊(duì)列深度、數(shù)據(jù)庫(kù)慢查詢數(shù)、Redis命中率、CPU/內(nèi)存/磁盤(pán)IO/網(wǎng)絡(luò)帶寬。這里面的關(guān)鍵是壓測(cè)工具指標(biāo)準(zhǔn)不準(zhǔn)、全不全、能不能和監(jiān)控體系打通。JMeter的指標(biāo)項(xiàng)比較完整但多曲折很多指標(biāo)要靠監(jiān)聽(tīng)器采樣再二次計(jì)算Gatling的報(bào)告直接把常見(jiàn)性能指標(biāo)做成圖表非常直觀k6則把所有指標(biāo)都結(jié)構(gòu)化輸出天然適合對(duì)接時(shí)序數(shù)據(jù)庫(kù)做持久化存儲(chǔ)和自定義看板Locust基本只給你原始數(shù)據(jù)想要完整的性能看板得自己上InfluxDBTelegrafGrafana組合。選型前建議先畫(huà)一條想看的指標(biāo)清單反向檢查工具能否滿足這一步省得后面做分析時(shí)到處找數(shù)據(jù)。3.4 與CI/CD和團(tuán)隊(duì)工作流的貼合度常被低估第三個(gè)容易被低估的是壓測(cè)工具和工作流的貼合度?,F(xiàn)在的團(tuán)隊(duì)基本都走GitLab或類似的代碼平臺(tái)加流水線壓測(cè)最好能變成CI流水線里的一個(gè)階段。那么問(wèn)題就來(lái)了這個(gè)工具能不能命令行跑能不能在容器里跑能不能在流水線里面接收參數(shù)能不能以非零退出碼標(biāo)識(shí)性能測(cè)試失敗把壓測(cè)固化成每次發(fā)布前自動(dòng)跑冒煙壓測(cè)這種最佳實(shí)踐選型必須支持這一環(huán)。k6在這方面是目前做得最徹底的它從設(shè)計(jì)之初就想好了要跑在CI里腳本可以放在代碼倉(cāng)庫(kù)里走版本管理命令行參數(shù)、閾值判定、環(huán)境變量注入都支持得很好。JMeter跑CI也能做到要借助Maven或Ant插件、命令行模式、再配合threshhold斷言插件但配置鏈路很長(zhǎng)。Locust也能用命令行方式跑無(wú)界面模式但結(jié)果判定和CI集成基本要靠自己用shell或Python腳本去串。4. 按真實(shí)業(yè)務(wù)場(chǎng)景給壓測(cè)方案4.1 場(chǎng)景一開(kāi)發(fā)自測(cè)、接口聯(lián)調(diào)階段開(kāi)發(fā)階段推薦大家用輕量級(jí)工具快速做冒煙壓測(cè)。比如后端開(kāi)發(fā)寫(xiě)完一個(gè)接口想知道自己寫(xiě)的查詢邏輯有沒(méi)有明顯的性能問(wèn)題不需要搞一套完整的壓測(cè)工程直接wrk壓一下看QPS和P99是否在一個(gè)正常量級(jí)就能快速發(fā)現(xiàn)比如沒(méi)有走索引或者循環(huán)發(fā)SQL這種低級(jí)事故。我自己的習(xí)慣是準(zhǔn)備一個(gè)標(biāo)準(zhǔn)的基準(zhǔn)壓測(cè)命令。比如wrk壓GET接口就寫(xiě)wrk -t4 -c200 -d30s --latency http://localhost:8080/api/v1/goods/list其中-t是線程數(shù)-c是連接數(shù)-d是持續(xù)時(shí)間--latency會(huì)輸出延遲分布。跑完看兩點(diǎn)平均QPS數(shù)量級(jí)是否合理P99延遲是否在預(yù)期內(nèi)。如果P99比平均值高好幾倍說(shuō)明存在明顯的長(zhǎng)尾效應(yīng)接口里八成有全表掃描或者鎖競(jìng)爭(zhēng)。4.2 場(chǎng)景二核心鏈路全鏈路壓測(cè)如果說(shuō)開(kāi)發(fā)自測(cè)是拿放大鏡看單點(diǎn)那么全鏈路壓測(cè)就是拿CT機(jī)掃全身。這種場(chǎng)景一般發(fā)生在業(yè)務(wù)上線前或者大促前目標(biāo)是驗(yàn)證核心鏈路的整體容量。比如一個(gè)交易場(chǎng)景鏈路涉及網(wǎng)關(guān)、鑒權(quán)、商品服務(wù)、庫(kù)存服務(wù)、訂單服務(wù)、支付回調(diào)至少四五個(gè)服務(wù)節(jié)點(diǎn)。這時(shí)候需要完整的腳本建模要有動(dòng)態(tài)token關(guān)聯(lián)、多組用戶數(shù)據(jù)、不同業(yè)務(wù)動(dòng)作的權(quán)重配比。這種場(chǎng)景我最推薦Gatling或k6。Gatling的優(yōu)勢(shì)是腳本結(jié)構(gòu)清晰Scenario就是鏈路定義Exec是動(dòng)作Pace是思考時(shí)間一眼就能看出業(yè)務(wù)流程長(zhǎng)什么樣報(bào)告也漂亮適合把結(jié)論同步給產(chǎn)品和管理層。k6的優(yōu)勢(shì)是工程化更好把腳本做成代碼工程后可以自由地用JavaScript組織復(fù)雜邏輯配合內(nèi)置的SharedArray、場(chǎng)景執(zhí)行器能把多階段壓測(cè)逐步加壓、持續(xù)保持、逐步釋放描述得很干凈。4.3 場(chǎng)景三海量并發(fā)下的容量探測(cè)當(dāng)需要探測(cè)系統(tǒng)極限容量比如預(yù)估大促峰值流量是日常的幾倍這時(shí)候比拼的就是壓測(cè)機(jī)的資源利用效率和分布式能力了。把3000并發(fā)平均分給三臺(tái)壓力機(jī)和在一臺(tái)機(jī)器上用異步引擎頂住3000并發(fā)后者的結(jié)果可比性更好因?yàn)樯倭藟毫C(jī)之間的調(diào)度偏差也省了運(yùn)維成本。Gatling和k6的單機(jī)性能在同等硬件條件下明顯優(yōu)于JMeter這是由并發(fā)模型決定的。如果還想追求更大的模擬規(guī)模k6是云原生友好型選擇支持把壓測(cè)機(jī)動(dòng)態(tài)部署到云端用Kubernetes作業(yè)的方式拉起幾十個(gè)Pod同時(shí)施壓配合內(nèi)置的實(shí)時(shí)指標(biāo)聚合整體體驗(yàn)非常順滑。這一能力對(duì)臨時(shí)需要千萬(wàn)級(jí)別虛擬用戶的場(chǎng)景至關(guān)重要。4.4 場(chǎng)景四線上流量回放與常態(tài)巡檢除了傳統(tǒng)的并發(fā)壓測(cè)現(xiàn)在很多團(tuán)隊(duì)還引入了流量回放。思路很簡(jiǎn)單把線上真實(shí)流量錄制下來(lái)經(jīng)過(guò)脫敏后重新打給測(cè)試環(huán)境或新版本環(huán)境觀察系統(tǒng)的性能表現(xiàn)和正確性。這類需求已經(jīng)超出了傳統(tǒng)壓測(cè)工具的能力范圍需要專門(mén)的流量錄制回放工具或者自建流量采集和回放系統(tǒng)通常和網(wǎng)關(guān)配合實(shí)現(xiàn)。如果團(tuán)隊(duì)還沒(méi)有能力自建流量回放平臺(tái)一個(gè)折中方案是用線上訪問(wèn)日志統(tǒng)計(jì)出的接口訪問(wèn)比例和參數(shù)分布來(lái)逆向構(gòu)建壓測(cè)模型。比如從日志統(tǒng)計(jì)出查商品詳情占比60%、搜索占比20%、加購(gòu)占比10%、下單占比5%、支付占比5%再把參數(shù)分布表導(dǎo)出來(lái)灌進(jìn)壓測(cè)腳本做參數(shù)化這樣壓測(cè)的流量模型就比人人都在下單靠譜得多。5. 工具選定后落地時(shí)容易踩的坑5.1 并發(fā)數(shù)和線程數(shù)、連接數(shù)根本不是一回事我見(jiàn)過(guò)太多次這樣的場(chǎng)景領(lǐng)導(dǎo)拍腦袋說(shuō)壓測(cè)目標(biāo)要達(dá)到5000并發(fā)執(zhí)行同學(xué)把壓測(cè)工具里的線程數(shù)或并發(fā)連接數(shù)設(shè)置為5000壓完就報(bào)告系統(tǒng)達(dá)標(biāo)。這是最容易產(chǎn)生誤導(dǎo)的做法。并發(fā)數(shù)是指同時(shí)處于業(yè)務(wù)處理中的用戶數(shù)不是工具里配置的線程數(shù)。壓測(cè)工具配置的并發(fā)值反映的是同時(shí)有幾個(gè)虛擬用戶在發(fā)請(qǐng)求如果每個(gè)請(qǐng)求耗時(shí)只有50毫秒那么5000并發(fā)里實(shí)際上同時(shí)在飛的在途請(qǐng)求可能只有幾百個(gè)系統(tǒng)的真實(shí)吞吐壓力遠(yuǎn)沒(méi)有5000那么高。要正確理解并發(fā)和吞吐的關(guān)系需要看“小流量高并發(fā)”和“大流量低并發(fā)”的差異。比如同樣目標(biāo)是支撐1萬(wàn)QPS如果每個(gè)請(qǐng)求平均耗時(shí)10ms那同時(shí)處理中的請(qǐng)求大約100個(gè)這是高吞吐低并發(fā)如果每個(gè)請(qǐng)求平均耗時(shí)500ms那同時(shí)處理中的請(qǐng)求就是5000個(gè)這是低吞吐高并發(fā)。兩種場(chǎng)景對(duì)線程池、連接池、緩存設(shè)計(jì)的要求截然不同壓測(cè)腳本里設(shè)置的并發(fā)值要配合平均響應(yīng)時(shí)間反推出來(lái)才合理。5.2 數(shù)據(jù)污染和緩存擊穿掩蓋了真實(shí)問(wèn)題壓測(cè)新手最容易忽略的是數(shù)據(jù)環(huán)境。比如你反復(fù)壓測(cè)同一個(gè)查詢接口第一次跑完后數(shù)據(jù)進(jìn)了緩存第二次再壓測(cè)時(shí)接口直接從緩存返回?cái)?shù)據(jù)P99性能極其亮眼但這個(gè)數(shù)據(jù)完全不可信。還有種情況是壓測(cè)產(chǎn)生的臟數(shù)據(jù)堆積在數(shù)據(jù)庫(kù)里比如每次都生成同樣的訂單號(hào)還能插入成功說(shuō)明唯一性約束根本沒(méi)被觸發(fā)這種情況下的寫(xiě)入性能參考價(jià)值低。我的建議是壓測(cè)前先明確數(shù)據(jù)準(zhǔn)備方案。只讀接口場(chǎng)景要預(yù)先準(zhǔn)備足夠大的數(shù)據(jù)集壓測(cè)過(guò)程中要有意識(shí)地繞過(guò)緩存或每隔一段時(shí)間清一下緩存測(cè)出真實(shí)的DB查詢能力寫(xiě)接口場(chǎng)景要么每次壓測(cè)后清表并重置自增ID要么用參數(shù)化方式保證每輪數(shù)據(jù)不重復(fù)。數(shù)據(jù)庫(kù)里的基準(zhǔn)數(shù)據(jù)量也要符合生產(chǎn)實(shí)際一個(gè)只有幾萬(wàn)條數(shù)據(jù)的表和幾千萬(wàn)條數(shù)據(jù)的表同樣一條SQL的壓測(cè)結(jié)果完全不是一個(gè)量級(jí)。5.3 只盯著平均值而忽略P95和長(zhǎng)尾平均響應(yīng)時(shí)間這個(gè)指標(biāo)說(shuō)實(shí)話意義有限。假設(shè)100個(gè)請(qǐng)求里99個(gè)都返回10ms1個(gè)因?yàn)镚C停頓返回了10秒平均響應(yīng)時(shí)間大約是110ms看起來(lái)系統(tǒng)還挺好但實(shí)際體驗(yàn)已經(jīng)崩了。線上用戶不會(huì)感受到平均體驗(yàn)用戶感受到的是自己那一次請(qǐng)求的體驗(yàn)所以必須重點(diǎn)關(guān)注P95和P99延遲也就是最慢的5%和1%的用戶體驗(yàn)。把P99指標(biāo)放到壓測(cè)結(jié)論里能推動(dòng)問(wèn)題真正被解決。比如壓測(cè)某商品列表接口平均RT是88msP99是320ms說(shuō)明有長(zhǎng)尾趨勢(shì)。進(jìn)一步排查發(fā)現(xiàn)320ms的長(zhǎng)尾里有相當(dāng)一部分集中在緩存過(guò)期后的緩存擊穿回源解決辦法就變成了加分布式鎖保護(hù)緩存重建或者預(yù)加載熱點(diǎn)key。如果沒(méi)有P99指標(biāo)這種問(wèn)題很容易被平均值平均過(guò)去。5.4 壓測(cè)環(huán)境和生產(chǎn)環(huán)境差異被低估經(jīng)常有團(tuán)隊(duì)在測(cè)試環(huán)境壓測(cè)出完美數(shù)據(jù)一到線上就出事然后懷疑壓測(cè)工具不準(zhǔn)。其實(shí)大概率是環(huán)境差異導(dǎo)致的。測(cè)試環(huán)境和生產(chǎn)環(huán)境的硬件配置不同是顯性的更多的差異是隱性的生產(chǎn)環(huán)境有真實(shí)流量干擾、有其他業(yè)務(wù)批量任務(wù)搶占資源、有多個(gè)更細(xì)粒度的服務(wù)發(fā)現(xiàn)和配置中心交互、有更完整的日志采集和鏈路追蹤組件哪怕多了一個(gè)trace-agent對(duì)性能的影響也可能有5%到15%的浮動(dòng)。所以我的原則是壓測(cè)結(jié)論要注明環(huán)境上下文包括機(jī)器規(guī)格、版本、依賴的中間件版本、數(shù)據(jù)規(guī)模、壓測(cè)機(jī)所在網(wǎng)絡(luò)位置。條件允許的情況下盡量在預(yù)發(fā)環(huán)境或者生產(chǎn)環(huán)境的低峰期做一次真實(shí)環(huán)境壓測(cè)這和測(cè)試環(huán)境壓測(cè)完全是兩個(gè)量級(jí)的工作收獲也完全是兩個(gè)量級(jí)。如果實(shí)在不方便在生產(chǎn)壓測(cè)至少要做到測(cè)試環(huán)境的硬件規(guī)格不能比生產(chǎn)低太多否則容量評(píng)估數(shù)據(jù)就是自欺欺人。6. 工具是起點(diǎn)完整的壓測(cè)體系才是終點(diǎn)6.1 從壓一下看看到壓測(cè)資產(chǎn)管理成熟團(tuán)隊(duì)的壓測(cè)工作不應(yīng)該是一次性的臨時(shí)活動(dòng)而應(yīng)該把壓測(cè)腳本、場(chǎng)景、數(shù)據(jù)、報(bào)告都當(dāng)作資產(chǎn)沉淀下來(lái)。每次大促前壓測(cè)完腳本里哪些參數(shù)需要調(diào)整、業(yè)務(wù)上哪些邏輯變化了都應(yīng)該同步更新到壓測(cè)工程里。KPI口徑也要固定下來(lái)什么樣的P99算達(dá)標(biāo)什么樣的錯(cuò)誤率可接受什么樣的資源水位屬于健康這些做成團(tuán)隊(duì)的性能基準(zhǔn)。這里就體現(xiàn)出了k6或者Gatling這類腳本即代碼的工具的價(jià)值壓測(cè)腳本可以進(jìn)代碼倉(cāng)庫(kù)、走Code Review、打版本標(biāo)簽新同學(xué)照著倉(cāng)庫(kù)里的文檔和腳本就能復(fù)現(xiàn)一次壓測(cè)。而用JMeter的GUI文件來(lái)管理壓測(cè)資產(chǎn)版本對(duì)比和Review永遠(yuǎn)是最痛苦的環(huán)節(jié)一個(gè).jmx文件幾千行XML肉眼Review幾乎不可行。6.2 壓測(cè)報(bào)告是給決策看的數(shù)據(jù)產(chǎn)品技術(shù)團(tuán)隊(duì)內(nèi)部看壓測(cè)報(bào)告關(guān)心的是哪里慢、為什么慢、怎么改管理層看壓測(cè)報(bào)告關(guān)心的是能不能上線、要不要加機(jī)器、風(fēng)險(xiǎn)多大。一份好的壓測(cè)報(bào)告要同時(shí)滿足這兩種讀者。工具選型時(shí)也要把這個(gè)因素考慮進(jìn)去Gatling的自帶報(bào)告精美直接適合對(duì)外展示k6的指標(biāo)結(jié)構(gòu)化程度高適合自建看板JMeter則通了插件也能做不錯(cuò)的圖就是默認(rèn)的美觀度和交互性比較弱。我現(xiàn)在的做法是把壓測(cè)報(bào)告沉淀成兩部分一部分是自動(dòng)化的實(shí)時(shí)看板展示壓測(cè)執(zhí)行過(guò)程中的QPS、RT、錯(cuò)誤率、系統(tǒng)資源方便技術(shù)人員盯現(xiàn)場(chǎng)另一部分是壓測(cè)結(jié)束后生成的總結(jié)報(bào)告包含結(jié)論、瓶頸分析、優(yōu)化建議、風(fēng)險(xiǎn)等級(jí)推送給相關(guān)決策人。能做到這一層壓測(cè)才真正參與到了發(fā)布決策里。6.3 漸進(jìn)式落地的個(gè)人路線建議如果團(tuán)隊(duì)現(xiàn)在還是零狀態(tài)我的建議是不要一口氣上完整的平臺(tái)那樣容易翻車(chē)。按照能用—好用—平臺(tái)化三步走。第一步先選定一款主力工具在試點(diǎn)項(xiàng)目里用起來(lái)把腳本和采集指標(biāo)的標(biāo)準(zhǔn)定下來(lái)第二步把壓測(cè)接入CI流水線做成發(fā)布前的質(zhì)量門(mén)禁第三步沉淀歷史數(shù)據(jù)和基準(zhǔn)報(bào)告逐漸形成性能容量基線。走到第二步團(tuán)隊(duì)的壓測(cè)能力就已經(jīng)超過(guò)很多公司了?;仡^看看自己這些年用過(guò)的工具早期用ab和wrk應(yīng)付開(kāi)發(fā)自測(cè)中期用JMeter搭了一套分布式壓測(cè)后來(lái)為了把壓測(cè)做進(jìn)流水線換成了k6同時(shí)保留Gatling做復(fù)雜鏈路的容量評(píng)估。工具換來(lái)?yè)Q去的核心驅(qū)動(dòng)始終是當(dāng)前的壓測(cè)方法能不能支撐業(yè)務(wù)決策。最后再分享一點(diǎn)個(gè)人心得選壓測(cè)工具時(shí)別被哪個(gè)測(cè)試工具最主流帶節(jié)奏。貴的不一定適合你功能多的不一定用得上腳本難寫(xiě)的也不一定學(xué)不會(huì)。把你自己團(tuán)隊(duì)的痛點(diǎn)列出來(lái)——是缺資源模擬能力、缺CI集成、缺指標(biāo)采集還是缺報(bào)告說(shuō)服力然后讓工具去匹配這些痛點(diǎn)遠(yuǎn)比到處復(fù)制別人的選型方案靠譜得多。工具本身不能給你答案但正確的工具能幫你發(fā)現(xiàn)真正的問(wèn)題后面的優(yōu)化才有方向和依據(jù)。