有贊致力於成爲商家服務領域裏最被信任的引領者,由於被信任,全部咱們更須要爲商家保駕護航,保障系統的穩定性。有贊從去年開始經過全鏈路壓測,模擬大促真實流量,串聯線上所有系統,讓核心系統同時達到流量峯值:數據庫
經過全鏈路壓測這一手段,對線上系統進行最真實的大促演練,獲取系統在大壓力時的表現狀況,進而準確評估線上整個系統集羣的性能和容量水平,不辜負百萬商家的信任。json
有贊對於性能測試主要有線下單系統單接口、線上單系統以及線上全鏈路壓測等手段,經過不一樣維度和顆粒度對接口、系統、集羣層面進行性能測試,最終保障系統的穩定性。這裏主要講述一下,有贊全鏈路壓測的相關設計和具體的實施。服務器
說到全鏈路壓測,業內的淘寶、京東都都已有很成熟的技術,主要就是壓測流量的製造、壓測數據的構造、壓測流量的識別以及壓測數據流向的處理;直接看下有贊壓測的總體設計:併發
壓測平臺負責管理壓測腳本和壓測請求數據,從數據工廠獲取壓測數據集,分發到每個壓測 agent 機器上,agent 根據壓測腳本和壓力目標對線上機器發起請求流量,模擬用戶的查看商品-添加購物車-下單-支付等行爲,線上服務集羣識別出壓測的流量,對於存儲的讀寫走影子存儲。這裏就要說到,線上壓測很重要的一點就是不能污染線上的數據,不能讓買賣家有感知,好比壓測後,賣家發現多了好多訂單,買家發現錢少了。因此,線上服務須要可以隔離出壓測的流量,存儲也須要識別出壓測的數據,下面看一下有讚的壓測流量和壓測數據存儲的隔離方案。框架
要想壓測的流量和數據不影響線上真實的生產數據,就須要線上的集羣能識別出壓測的流量,只要能識別出壓測請求的流量,那麼流量觸發的讀寫操做就很好統一去作隔離了,先看一下有贊壓測流量的識別:異步
全鏈路壓測發起的都是Http的請求,只須要要請求頭上添加統一的壓測請求頭,具體表現形式爲:
Header Name:X-Service-Chain;
Header Value:{"zan_test": true}oop
Dubbo協議的服務調用,經過隱式參數在服務消費方和提供方進行參數的隱式傳遞,表現形式爲:
Attachments:X-Service-Chain;
Attachments Value:{"zan_test": true}性能
經過在請求協議中添加壓測請求的標識,在不一樣服務的相互調用時,一路透傳下去,這樣每個服務都能識別出壓測的請求流量,這樣作的好處是與業務徹底的解耦,只須要應用框架進行感知,對業務方代碼無侵入測試
異步調用標識透傳問題,能夠自行定製 Runnable 或者定製線程池再或者業務方自行定製實現。大數據
經過流量識別的改造,各個服務都已經可以識別出壓測的請求流量了,那麼如何作到壓測數據不污染線上數據,對於不一樣的存儲作到壓測數據和真實的隔離呢,有贊主要有客戶端 Client 和 Proxy 訪問代理的方式實現,下面就看一下有讚的數據隔離方案:
針對業務方和數據存儲服務間已有Proxy代理的狀況,能夠直接升級 Proxy 層,存儲使用方徹底無感知,無侵入,下面以 MySQL 爲例,說明 Proxy 訪問代理對於壓測數據隔離的方案;
業務方應用讀寫DB時,統一與 RDS-Proxy (介於 MySQL 服務器與 MySQLClient 之間的中間件)交互,調用 RDS-Proxy 時會透傳壓測的標記,RDS 識別出壓測請求後,讀寫 DB 表時,自動替換成對應的影子表,達到壓測數據和真實的生產數據隔離的目的
ElasticSearch、KV 對於壓測的支持也是經過 Proxy 訪問代理的方式實現的
業務應用經過Client調用存儲服務時,Client 會識別出壓測的流量,將須要讀寫的 Table 自動替換爲影子表,這樣就能夠達到影子流量,讀寫到影子存儲的目的;
Hbase、Redis 等採用此方案實現
推進框架、中間件升級、業務方改造,不免會有遺漏之處,因此有贊對於壓測的數據統一作了偏移,確保買賣家 ID 與線上已有數據隔離開,這樣即便壓測數據因爲某種緣由寫入了真實的生產庫,也不會影響到線上買賣家相關的數據,讓用戶無感知;
這裏要說一下特殊的週期掃表應用的改造,週期性掃表應用因爲沒有外部觸發,全部沒法掃描影子表的數據,如何讓這樣的 job 集羣總體來看既掃描生產庫,也掃描影子庫呢?
有讚的解決思路是,部署一些新的 job 實例,它們只掃描影子庫,消息處理邏輯不變;老的 job 實例保持不變(只掃生產庫)
有讚的全鏈路壓測平臺目前主要負責壓測腳本管理、壓測數據集管理、壓測 job 管理和調度等,後續會有重點介紹,這裏不作深刻
壓測的「硬件」設施基本已經齊全,下面介紹一下有贊全鏈路壓測的具體實施流程吧
廢話很少說,直接上圖:
有贊全鏈路壓測的執行流程如上圖所示,下面具體看一下幾個核心步驟在有贊是怎麼作的。
要想模擬大促時線上真實的流量狀況,首先須要確認的就是壓測場景、鏈路,壓測的目錄,以及壓測的流量漏斗模型:
前面咱們已經介紹瞭如何肯定壓測的目標、場景、鏈路,那麼壓測的數據怎麼來尼,這就是數據工廠登場的時候了,下面就介紹一下有贊壓測的數據工廠
有讚的壓測數據工廠主要負責,壓測鋪底數據的準備、壓測請求數據塊的生成;
壓測準備鋪底的數據,這個衆所周知的,可是因爲有贊壓測的方案採用的是影子庫的設計,因此對於鋪底數據準備不得不去處理影子庫的數據。直接看下鋪底數據準備的流程圖:
從生產數據庫按需過濾,導入壓測鋪底須要的數據到大數據集羣的hive表中。
在 hive 表中,對導入的數據進行脫敏和清洗,清洗的目的是保證壓測的數據可用性,好比保證鋪底商品庫存最大、營銷活動時間無限、店鋪正常營業等。
對 hive 標中已經處理完成的數據,導出到已經建立好的影子庫中,須要注意的是同一實例寫入數據的控制(由於影子庫和生產庫同實例),寫入數據的 binlog 過濾。
有讚的壓測數據準備目前所有在 DP 大數據平臺上操做,基本完成了數據準備操做的自動化,維護了近千的數據準備 job
gatling 原生支持 json、csv、DB 等方式的數據源載入,咱們採用的壓測數據源是 json 格式的,那麼如此海量的壓測源數據,是經過什麼方式生成和存儲的尼,咱們的實現仍是依託於 DP 大數據平臺,經過 MapReduce 任務的方式,按需生成咱們壓測請求須要的數據集:
MapReduce 生成的數據集 json 示例:
壓測就要知道壓測的具體接口和接口參數,因此咱們採用統一的 RESTful 風格規範,讓各個業務方的人員提交壓測接口的 API 文檔,這樣壓測腳本編寫人員就能根據這份 API 快速寫出壓測的腳本,以及接口的預期結果等
有讚的壓測引擎用的是公司二次封裝的 gatling,原生就支持漏斗比例的控制,直接看例子
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 時,按需把不一樣的場景組合到一塊兒便可;須要單獨壓測某一個場景時,setUp 中只留一個場景就好,作到一次編寫,到處可壓。
壓測的鋪底數據、壓測腳本、壓測請求的數據集都已經介紹完了,可謂是萬事俱備只欠東風,那這個東風就是咱們自建的壓測平臺 maxim,這裏不對壓測平臺的設計展開介紹,展現一下 maxim 在壓測執行過程當中所承擔的工做。
maxim平臺主要的功能模塊有:
maxim 平臺壓測結果報告
下面看一下壓測執行的頁面功能:
到這裏有贊全鏈路壓測方案已經介紹完了,由於篇幅的緣由還有不少實施細節部分並無完整表述,同時有讚的全鏈路壓測也才初具雛形,歡迎有興趣的同窗聯繫咱們一塊兒探討,有表述錯誤的地方也歡迎你們聯繫咱們糾正。