前言
有贊致力于成為商家服務(wù)領(lǐng)域里最被信任的引領(lǐng)者,因?yàn)楸恍湃危形覀兏枰獮樯碳冶q{護(hù)航,保障系統(tǒng)的穩(wěn)定性。有贊從去年開始通過全鏈路壓測,模擬大促真實(shí)流量,串聯(lián)線上全部系統(tǒng),讓核心系統(tǒng)同時達(dá)到流量峰值:
- 驗(yàn)證大促峰值流量下系統(tǒng)穩(wěn)定性
- 容量規(guī)劃
- 進(jìn)行強(qiáng)弱依賴的劃分
- 降級、報警、容災(zāi)、限流等演練
- ...
通過全鏈路壓測這一手段,對線上系統(tǒng)進(jìn)行最真實(shí)的大促演練,獲取系統(tǒng)在大壓力時的表現(xiàn)情況,進(jìn)而準(zhǔn)確評估線上整個系統(tǒng)集群的性能和容量水平,不辜負(fù)百萬商家的信任。
有贊對于性能測試主要有線下單系統(tǒng)單接口、線上單系統(tǒng)以及線上全鏈路壓測等手段,通過不同維度和顆粒度對接口、系統(tǒng)、集群層面進(jìn)行性能測試,最終保障系統(tǒng)的穩(wěn)定性。這里主要講述一下,有贊全鏈路壓測的相關(guān)設(shè)計和具體的實(shí)施。
整體設(shè)計
說到全鏈路壓測,業(yè)內(nèi)的淘寶、京東都都已有很成熟的技術(shù),主要就是壓測流量的制造、壓測數(shù)據(jù)的構(gòu)造、壓測流量的識別以及壓測數(shù)據(jù)流向的處理;直接看下有贊壓測的整體設(shè)計:
- 大流量下發(fā)器:其實(shí)就是模擬海量的用戶去使用我們的系統(tǒng),提供壓測的流量,產(chǎn)生大促時的場景和流量;
- 數(shù)據(jù)工廠:構(gòu)造壓測鏈路中用戶請求的數(shù)據(jù),以及壓測鋪底的數(shù)據(jù)、數(shù)據(jù)清洗、脫敏等工作;
壓測平臺負(fù)責(zé)管理壓測腳本和壓測請求數(shù)據(jù),從數(shù)據(jù)工廠獲取壓測數(shù)據(jù)集,分發(fā)到每一個壓測 agent 機(jī)器上,agent 根據(jù)壓測腳本和壓力目標(biāo)對線上機(jī)器發(fā)起請求流量,模擬用戶的查看商品-添加購物車-下單-支付等行為,線上服務(wù)集群識別出壓測的流量,對于存儲的讀寫走影子存儲。這里就要說到,線上壓測很重要的一點(diǎn)就是不能污染線上的數(shù)據(jù),不能讓買賣家有感知,比如壓測后,賣家發(fā)現(xiàn)多了好多訂單,買家發(fā)現(xiàn)錢少了。所以,線上服務(wù)需要能夠隔離出壓測的流量,存儲也需要識別出壓測的數(shù)據(jù),下面看一下有贊的壓測流量和壓測數(shù)據(jù)存儲的隔離方案。
流量識別
要想壓測的流量和數(shù)據(jù)不影響線上真實(shí)的生產(chǎn)數(shù)據(jù),就需要線上的集群能識別出壓測的流量,只要能識別出壓測請求的流量,那么流量觸發(fā)的讀寫操作就很好統(tǒng)一去做隔離了,先看一下有贊壓測流量的識別:
3.1 同步請求
全鏈路壓測發(fā)起的都是Http的請求,只需要要請求頭上添加統(tǒng)一的壓測請求頭,具體表現(xiàn)形式為: Header Name:X-Service-Chain;
Header Value:{"zan_test": true}
Dubbo協(xié)議的服務(wù)調(diào)用,通過隱式參數(shù)在服務(wù)消費(fèi)方和提供方進(jìn)行參數(shù)的隱式傳遞,表現(xiàn)形式為:
Attachments:X-Service-Chain;
Attachments Value:{"zan_test": true}
通過在請求協(xié)議中添加壓測請求的標(biāo)識,在不同服務(wù)的相互調(diào)用時,一路透傳下去,這樣每一個服務(wù)都能識別出壓測的請求流量,這樣做的好處是與業(yè)務(wù)完全的解耦,只需要應(yīng)用框架進(jìn)行感知,對業(yè)務(wù)方代碼無侵入
3.2 中間件
NSQ:通過 NSQMessage 中添加 jsonExtHeader 的 KV 拓展信息,讓消息可以從 Producer 透傳到 Consumer 端,具體表現(xiàn)形式為:Key:zan_test;Value:true
Wagon:對來自影子庫的 binlog 通過拓展消息命令(PUBEXT)帶上壓測標(biāo)記{"zantest": true}
3.3 異步線程
異步調(diào)用標(biāo)識透傳問題,可以自行定制 Runnable 或者定制線程池再或者業(yè)務(wù)方自行定制實(shí)現(xiàn)。
四、數(shù)據(jù)隔離
通過流量識別的改造,各個服務(wù)都已經(jīng)能夠識別出壓測的請求流量了,那么如何做到壓測數(shù)據(jù)不污染線上數(shù)據(jù),對于不同的存儲做到壓測數(shù)據(jù)和真實(shí)的隔離呢,有贊主要有客戶端 Client 和 Proxy 訪問代理的方式實(shí)現(xiàn),下面就看一下有贊的數(shù)據(jù)隔離方案:
4.1 Proxy 訪問代理隔離
針對業(yè)務(wù)方和數(shù)據(jù)存儲服務(wù)間已有Proxy代理的情況,可以直接升級 Proxy 層,存儲使用方完全無感知,無侵入,下面以 MySQL 為例,說明 Proxy 訪問代理對于壓測數(shù)據(jù)隔離的方案;
業(yè)務(wù)方應(yīng)用讀寫DB時,統(tǒng)一與 RDS-Proxy (介于 MySQL 服務(wù)器與 MySQLClient 之間的中間件)交互,調(diào)用 RDS-Proxy 時會透傳壓測的標(biāo)記,RDS 識別出壓測請求后,讀寫 DB 表時,自動替換成對應(yīng)的影子表,達(dá)到壓測數(shù)據(jù)和真實(shí)的生產(chǎn)數(shù)據(jù)隔離的目的
ElasticSearch、KV 對于壓測的支持也是通過 Proxy 訪問代理的方式實(shí)現(xiàn)的
4.2 客戶端SDK隔離
業(yè)務(wù)應(yīng)用通過Client調(diào)用存儲服務(wù)時,Client 會識別出壓測的流量,將需要讀寫的 Table 自動替換為影子表,這樣就可以達(dá)到影子流量,讀寫到影子存儲的目的;
Hbase、Redis 等采用此方案實(shí)現(xiàn)
4.3 數(shù)據(jù)偏移隔離
推動框架、中間件升級、業(yè)務(wù)方改造,難免會有遺漏之處,所以有贊對于壓測的數(shù)據(jù)統(tǒng)一做了偏移,確保買賣家 ID 與線上已有數(shù)據(jù)隔離開,這樣即使壓測數(shù)據(jù)由于某種原因?qū)懭肓苏鎸?shí)的生產(chǎn)庫,也不會影響到線上買賣家相關(guān)的數(shù)據(jù),讓用戶無感知;
這里要說一下特殊的周期掃表應(yīng)用的改造,周期性掃表應(yīng)用由于沒有外部觸發(fā),所有無法掃描影子表的數(shù)據(jù),如何讓這樣的 job 集群整體來看既掃描生產(chǎn)庫,也掃描影子庫呢? 有贊的解決思路是,部署一些新的 job 實(shí)例,它們只掃描影子庫,消息處理邏輯不變;老的 job 實(shí)例保持不變(只掃生產(chǎn)庫)
五、壓測平臺
有贊的全鏈路壓測平臺目前主要負(fù)責(zé)壓測腳本管理、壓測數(shù)據(jù)集管理、壓測 job 管理和調(diào)度等,后續(xù)會有重點(diǎn)介紹,這里不做深入
壓測的“硬件”設(shè)施基本已經(jīng)齊全,下面介紹一下有贊全鏈路壓測的具體實(shí)施流程吧
六、壓測實(shí)施流程
廢話不多說,直接上圖:
有贊全鏈路壓測的執(zhí)行流程如上圖所示,下面具體看一下幾個核心步驟在有贊是怎么做的。
6.1 壓測計劃制定
要想模擬大促時線上真實(shí)的流量情況,首先需要確認(rèn)的就是壓測場景、鏈路,壓測的目錄,以及壓測的流量漏斗模型:
壓測的鏈路:根據(jù)公司具體業(yè)務(wù)具體分析,有贊屬于電商類型公司,大促時候的峰值流量基本都是由于買家的購買行為導(dǎo)致的,從宏觀上看,這樣的購買行為主要是店鋪首頁-商品詳情頁-下單-支付-支付成功,我們把這一條骨干的鏈路稱為核心鏈路,其實(shí)大促時主要就是保證核心鏈路的穩(wěn)定性
壓測鏈路的漏斗模型:線上真實(shí)的場景案例是,100個人進(jìn)入了商家的店鋪首頁,可能有50個人直接退出了,有50個人最終點(diǎn)擊進(jìn)入了商品詳情頁面,最終只有10個人下了單,5個人真正付款了,這就是壓測鏈路的漏斗模型,也就是不同的接口的真實(shí)調(diào)用比例;實(shí)際的模型制定會根據(jù)近7天線上真實(shí)用戶的行為數(shù)據(jù)分型分析建模,以及往期同類型活動線上的流量分布情況,構(gòu)建壓測鏈路的漏斗模型
- 壓測的場景:根據(jù)運(yùn)營報備的商家大促活動的計劃,制定大促的壓測場景(比如秒殺、抽獎等),再結(jié)合近七天線上流量的場景情況,綜合確定壓測的場景;
壓測目標(biāo):根據(jù)運(yùn)營報備的商家大促預(yù)估的PV和轉(zhuǎn)換率情況,結(jié)合去年同期線上流量情況和公司業(yè)務(wù)的增長速率,取大值作為壓測的目標(biāo)
6.2 數(shù)據(jù)工廠
前面我們已經(jīng)介紹了如何確定壓測的目標(biāo)、場景、鏈路,那么壓測的數(shù)據(jù)怎么來尼,這就是數(shù)據(jù)工廠登場的時候了,下面就介紹一下有贊壓測的數(shù)據(jù)工廠
有贊的壓測數(shù)據(jù)工廠主要負(fù)責(zé),壓測鋪底數(shù)據(jù)的準(zhǔn)備、壓測請求數(shù)據(jù)塊的生成;
6.3 鋪底數(shù)據(jù)準(zhǔn)備
壓測準(zhǔn)備鋪底的數(shù)據(jù),這個眾所周知的,但是由于有贊壓測的方案采用的是影子庫的設(shè)計,所以對于鋪底數(shù)據(jù)準(zhǔn)備不得不去處理影子庫的數(shù)據(jù)。直接看下鋪底數(shù)據(jù)準(zhǔn)備的流程圖:
數(shù)據(jù)導(dǎo)入 從生產(chǎn)數(shù)據(jù)庫按需過濾,導(dǎo)入壓測鋪底需要的數(shù)據(jù)到大數(shù)據(jù)集群的hive表中。
- 數(shù)據(jù)處理 在 hive 表中,對導(dǎo)入的數(shù)據(jù)進(jìn)行脫敏和清洗,清洗的目的是保證壓測的數(shù)據(jù)可用性,比如保證鋪底商品庫存最大、營銷活動時間無限、店鋪正常營業(yè)等。 - 數(shù)據(jù)導(dǎo)出 對 hive 標(biāo)中已經(jīng)處理完成的數(shù)據(jù),導(dǎo)出到已經(jīng)創(chuàng)建好的影子庫中,需要注意的是同一實(shí)例寫入數(shù)據(jù)的控制(因?yàn)橛白訋旌蜕a(chǎn)庫同實(shí)例),寫入數(shù)據(jù)的 binlog 過濾。
有贊的壓測數(shù)據(jù)準(zhǔn)備目前全部在 DP 大數(shù)據(jù)平臺上操作,基本完成了數(shù)據(jù)準(zhǔn)備操作的自動化,維護(hù)了近千的數(shù)據(jù)準(zhǔn)備 job
壓測請求數(shù)據(jù)數(shù)據(jù)集
gatling 原生支持 json、csv、DB 等方式的數(shù)據(jù)源載入,我們采用的壓測數(shù)據(jù)源是 json 格式的,那么如此海量的壓測源數(shù)據(jù),是通過什么方式生成和存儲的尼,我們的實(shí)現(xiàn)還是依托于 DP 大數(shù)據(jù)平臺,通過 MapReduce 任務(wù)的方式,按需生成我們壓測請求需要的數(shù)據(jù)集:
- 從各個業(yè)務(wù)線的表中獲取壓測場景整個鏈路所以接口請求需要的參數(shù)字段,存到一張創(chuàng)建好的壓測數(shù)據(jù)源寬表中
- 編寫 MapReduce 任務(wù)代碼,讀取壓測數(shù)據(jù)源寬表數(shù)據(jù),按壓測的接口請求參數(shù)情況,生成目標(biāo) json 格式的壓測請求數(shù)據(jù)塊文件到 HDFS
- 壓測時,壓測引擎自動從 HDFS 上拉取壓測的請求數(shù)據(jù)塊
MapReduce 生成的數(shù)據(jù)集 json 示例:
6.4 壓測腳本準(zhǔn)備6.4.1 梳理壓測請求和參數(shù)
壓測就要知道壓測的具體接口和接口參數(shù),所以我們采用統(tǒng)一的 RESTful 風(fēng)格規(guī)范,讓各個業(yè)務(wù)方的人員提交壓測接口的 API 文檔,這樣壓測腳本編寫人員就能根據(jù)這份 API 快速寫出壓測的腳本,以及接口的預(yù)期結(jié)果等
6.4.2 控制漏斗轉(zhuǎn)化率
有贊的壓測引擎用的是公司二次封裝的 gatling,原生就支持漏斗比例的控制,直接看例子
6.4.3 不同場景的配比 setUp( scn0.inject(constantUsersPerSec(10) during (1 minute)).throttle( reachRps(300) in (30 seconds), holdFor(2 minute)).protocols(CustomHttpProtocol.httpProtocol), scn1.inject(constantUsersPerSec(10) during (1 minute)).throttle( reachRps(500) in (10 seconds), holdFor(3 minute)).protocols(CustomHttpProtocol.httpProtocol), scn2.inject(constantUsersPerSec(10) during (1 minute)).throttle( reachRps(200) in (20 seconds), holdFor(1 minute)).protocols(CustomHttpProtocol.httpProtocol) )
對不同的壓測場景鏈路按模塊編寫壓測腳本,這樣的好處就是需要不同場景混合壓測時,只需要在 setUp 時,按需把不同的場景組合到一起即可;需要單獨(dú)壓測某一個場景時,setUp 中只留一個場景就好,做到一次編寫,處處可壓。
6.5 壓測執(zhí)行
壓測的鋪底數(shù)據(jù)、壓測腳本、壓測請求的數(shù)據(jù)集都已經(jīng)介紹完了,可謂是萬事俱備只欠東風(fēng),那這個東風(fēng)就是我們自建的壓測平臺 maxim,這里不對壓測平臺的設(shè)計展開介紹,展示一下 maxim 在壓測執(zhí)行過程中所承擔(dān)的工作。
maxim平臺主要的功能模塊有:
測試腳本:負(fù)責(zé)測試腳本的管理
數(shù)據(jù)集:負(fù)責(zé)壓測請求數(shù)據(jù)集的管理,目前主要有兩種數(shù)據(jù)集上傳模式:直接上傳數(shù)據(jù)包和 hadoop 集群數(shù)據(jù)源路徑上傳。第二種上傳模式,只需要填寫數(shù)據(jù)源所在的 hadoop 集群的路徑,maxim 平臺會自動去所在路徑獲取壓測數(shù)據(jù)集文件
測試 job:負(fù)責(zé)測試任務(wù)的管理,指定壓測 job 的腳本和腳本入口,以及壓測數(shù)據(jù)集等
壓測注入器:負(fù)責(zé)展示壓測注入機(jī)器的相關(guān)信息
壓測報告生成:壓測報告的生成,直接用的 gatling 原生的報告生成功能
maxim 平臺壓測結(jié)果報告
下面看一下壓測執(zhí)行的頁面功能:
- 壓力注入器數(shù)量:指定本次壓測執(zhí)行,需要多少臺壓測機(jī)去執(zhí)行
- 重復(fù)場景測試:一個虛擬用戶重復(fù)幾次壓測場景
- 并發(fā)用戶數(shù):可執(zhí)行壓測時,按需填寫需要的每秒加載的并發(fā)用戶數(shù)和持續(xù)時間,無需每次變更壓測腳本
- 目標(biāo) RPS:可執(zhí)行壓測時,按需填寫壓測的目標(biāo) RPS,爬坡時間,目標(biāo)持續(xù)時間,達(dá)到限流的作用,可同時指定多個目標(biāo) RPS,達(dá)到分梯度壓測的目的;
七、最后
到這里有贊全鏈路壓測方案已經(jīng)介紹完了,因?yàn)槠脑蜻€有很多實(shí)施細(xì)節(jié)部分并沒有完整表述,同時有贊的全鏈路壓測也才初具雛形,歡迎有興趣的同學(xué)聯(lián)系我們一起探討,有表述錯誤的地方也歡迎大家聯(lián)系我們糾正。
|