性能測試 | 全鏈路壓測方案設計與實施詳解


有贊全鏈路壓測方案設計與實施詳解

每年雙十一,對於買家來說是一年一度的購物狂歡,可是對於電商公司的技術人員來說,卻是一年一次的大考。如何用更少的預算完成指定當前業務規模的流量高峰,是技術的永恆主題。

有贊在雙十一之前完成了全鏈路壓測方案,並把它用於大促的擴容和容量驗證,取得了不錯的成果。

在電商公司待過的技術同學都知道,在大促來臨時,整個集群的最高峰壓力將是正常時間的幾十倍,最高峰持續的時間會特別短,然后回落到正常水平的幾倍。所以,我們可能會自然而然地想到,把整個集群擴容幾十倍的機器,在雙十一當天應對幾十倍的流量,然后第二天減至正常量,就可以完成大促的考驗。事實情況是否真的這么簡單?

大促保障的困難  

用戶購買商品的鏈路是一條很長很復雜的系統集群,中間會涉及到店鋪、商品、會員、營銷、交易、支付等 6 大核心模塊,每個模塊又會涉及到多個不同的服務化系統單元,我們把這一條骨干的鏈路就叫做核心鏈路。

大家都知道,雙十一當天,真正爆增的其實是買家的購買量,像開店 / 商品上架等功能,其實並發量沒什么變化。也就是說,真正的壓力其實是在核心鏈路上面,如果把所有的系統都擴容幾十倍,本身就是一個很大的浪費。正常來說,一個稍有規模的電商公司,日常有幾千台機器維持正常的運轉,本身就是一個較大的開銷,如果突增幾十倍的系統開銷,對於公司的財務也是很大的壓力。所以,一個較理想的方法,是只把核心鏈路的系統擴大幾十倍的系統吞吐量,就可以達到目標。

    困難一

大型的分布式系統其實錯綜復雜,公司需要維持成百上千的服務化系統。理論上來說, 只有少部分系統是核心鏈路的系統。但是在實際情況下,因為公司人員的關系,可能會把某些非核心系統,不知不覺加入到了核心鏈路中。所以,第一件要做的事情,就是把非核心系統從核心鏈路上剔除。

    困難二

一般公司都會在線下搭建性能測試環境,在該環境下,我們的測試同學可 以借助一些測試工具,去壓單機單接口的性能。假如,店鋪的首頁面,我們在性能測試環境下,得出單機單接口的 QPS 峰值是 500,這是否意味着, 要達到 10w 的 QPS,我只需要設置 200 台機器就可以了呢?答案當然是否定的。因為任何的頁面接口都不是單獨存在的,都會受到公共資源的制約,如:DB、Redis、MQ、網絡帶寬等。比如當店鋪首頁達到 10w QPS 的時候,商品詳情頁可能要達到 8w 的 QPS 了,也會消耗公共資源。當公共資源的能力下降時,勢必會影響所有的系統。所以,通過單機性能算出來的理論值,跟實際情況會相差很遠。

    困難三

正常來說,任何大促都會有業務目標,這個目標一般是拿 GMV 進行評估。但是我們在進行系統容量評估的時候,一般會想擴大多少台機器。那么 GMV 跟核心鏈路各個系統之間的機器數量的轉化關系是什么樣的?

    困難四

做過大型分布式系統的同學,可能都知道一個事實,即整個集群的性能其實取決於接口的短板效應。而這個短板的接口,在正常的流量下,是不會顯現出來的。只有集群的整體壓力達到一定值的情況下,才會偶爾顯現, 然后造成雪崩效應,拖累整個系統集群。所以,如何在大促之前找到這些短板,然后把它們一個一個優化,這件事情就顯得非常重要。

    困難五

應用系統的擴容相對而言是比較簡單的,完成大促之后,可以很容易歸還。但是 DB 等核心資源的擴容其實並不容易,而且資源不可能歸還(數據不不可丟失)。

事實是檢驗真理理的唯⼀一標准,上面提到的五個困難,其實都可以用線上真實壓測的辦法去檢驗。業內大型電商公司,會用全鏈路壓測的方案去指導擴容的進程,有贊也不例外。今年雙十一,有贊用該方案完成了對核心鏈路 20 倍的擴容,但是整個集群的規模只是擴大了了一倍多一點。

全鏈路壓測的目標是讓雙十一要發生的事情提前發生,並驗證在該情況下系統表現良好。做線上壓測,有一個很重要的原則:線上系統是不允許有臟數據的。

有贊的壓測設計方案,可以用幾句簡單的話做概括:

  • 壓測流量落影子庫,正常流量落正常庫。

  • 壓測不能把系統壓崩潰。

  • 壓測是模擬雙十一流量最高峰時用戶的購物行為,所以綜合性的流量模型需要跟實際情況相符。

有圖有真相,我們先上圖。

在上述圖中,我們明顯可以看到,全鏈路壓測有幾個關鍵部分:

  1. 數據工廠,負責造請求數據。

  2. 大流量下發器,產生很大的壓力去壓系統。

  3. 線上服務集群同時處理壓測請求 + 正常請求。

  4. 壓測流量落影子存儲,正常流量落正常存儲。

  5. 壓測流量對於外部的依賴走 mock 服務器,正常流量走正常外部集群。

  6. 水位檢測,需要檢測存儲 + 線上應用服務器的健康度,並且能夠干預流量下發。

 

數據工廠是壓測的一個核心部件,主要由 Hive 表的集合 + 各種導入、導出腳本組成。

數據工廠的目的是保存壓測需要准備的所有數據,數據需要做清洗,比如:

  • 商品未下架

  • 商品的庫存無限

  • 營銷活動的信息有效,未過期

  • 店鋪未關閉等等

場景的定義:場景的定義關系到數據的准備,正常來說,壓測只會壓隨着買家人數暴增、系統的壓力立即增加的場景,我們把這個場景涉及到的系統叫做“核心鏈路”。

 

  1. DB、路由方式由 RDS 提供,存儲可以有兩種方式:

    • 影子表與正常表存在同樣的 instance、不同的 schema 中。這個方案不需要增加額外的存儲開銷,相對更便宜,但是風險較高(把庫壓死了會影響線上業務)。

    • 影子表與正常表存在不同的 instance、相同的 schema 中。這個方案相對較貴,需要額外搭建 DB 集群,但是安全性較高。

      我們選擇的是第一個方案。

  2. Redis:通過 key 值來區分。壓測流量的 key 值加統一前綴,通過 Redis-Client 做路由。

  3. HBase:通過命名空間做隔離。影子空間加前綴,提供統一的 HBase Client 做數據訪問,由該 Client 做路由。

  4. ES:通過 index 名字來區分。影子的索引統一加前綴,提供統一的 ES Client 做數據訪問,由該 Client 做路由。

  1. 統一線上應用對於數據的訪問(DB+ES+HBase+Redis),提供統一的 Client。

  2. 由於線上的應用都是服務化工程,遠程調用時,必須具備壓測流量的標記透傳能力。

  3. 線上的少部分應用,需要訪問第三方服務,比如:物流、支付。這些應用需要改造為壓測的流量直接訪問 mock 服務器。

我們選用 gatling 作為我們的流量下發器實現。

數據文件的內容

每一種場景都有不同的數據文件,數據文件由場景相對應的多種 url 組合而成。比如:我們本次壓測會壓“無優惠的場景、秒殺場景、滿減場景、拼團場景” 等等。無優惠的場景分為“店鋪首頁、商品詳情頁、加購物車頁、下單頁、支付頁、支付成功頁”等等。這個文件不涉及漏斗轉化率。一般來說,一個數據文件很大(至少是 G 級別的)。所以我們的數據文件內容格式為:

  • 所有的數據⽂文件

    • 場景集合 1

    • 場景集合 2

    • 店鋪首頁 URL

    • 商品詳情頁 URL

    • 加購物車頁 URL

    • 下單頁 URL

    • 支付頁 URL

    • 支付成功頁 URL

    • 店鋪首頁 URL

    • 商品詳情頁 URL

    • 加購物車頁 URL

    • 下單頁 URL

    • 支付頁 URL

    • 支付成功頁 URL

    • 無優惠的場景數據文件

    • 秒殺場景數據文件

    • 滿減場景數據文件

    • 拼團場景

流量下發腳本的內容

流量下發腳本的核心是控制漏斗轉化率:

  1. 不同場景的流量配比。

  2. 每個場景下面,url 從上往下的漏斗轉化率。

gatling 提供天然的轉化率配置腳本,用起來非常方便。有興趣的同學可以自行 Google。

這個是一個很重要的模塊,在項目啟動之初,我們希望以實時計算的方式,一邊采集各個應用系統的資源使用情況 + 接口耗時 + 業務正確率,一邊向 gatling 發送流量干預信號,以做到自動保護系統的目的。由於時間關系,我們並未實現這一方案。取而代之的是人肉查看實時監控界面的方式,人為去干預 gatling 的流量下發情況。

如果實施過全鏈路壓測的項目,大家都會有一個共同的感受:做基礎的組件容易,讓核心業務去完成相關的升級與驗證工作很難。原因只有一個:需要用全鏈路壓測的公司,業務規模都很大,涉及的團隊會特別多。梳理理清楚龐大的業務,讓所有的業務團隊一起發力,本身就是一件很難的事情。

我們把鏈路壓測的實施分為以下幾個階段:

  1. 基礎中間件開發,各種框架升級開發,壓測器研究與腳本開發。

  2. 業務升級與線下驗證(人工點擊,數據落影子庫)

  3. 業務升級與線上驗證(人工點擊,數據落影子庫)

  4. 數據工廠數據准備。

  5. 小流量下發驗證(用 gatling 下發,數據落影子庫)

  6. 大流量量壓測與系統擴容

第 2、3、5 階段,需要借助業務測試同學的力量;第 4 階段,需要借助業務開發同學的力量;第 6 階段,則需要借助業務團隊 + 運維同學的力量。

由於每個階段人員都不太一樣,所以需要每一個階段都組織不同成員的虛 擬小組,借助各個團隊的力量完成相應的工作。

正常來說,在大促之前做壓測,目的一般是給擴容 / 優化做方向性的指導。

假設我們雙十一需要擴大 20 倍的容量以應對高峰,那我一定不會一開始 就拿 20 倍的流量去壓我們的系統,因為這樣做的話,所有的系統都會在一瞬間就掛掉,這樣沒有任何意義。我們的做法是,階段性的爬坡打流量,然后把系統的能力一段一段提升上去。

例如:

  1. 第一天,我們會以日常流量的最高峰為起始流量,然后爬坡到一個流量高峰 A,記為第一天的目標。在壓測之前先做一次擴容。在壓測中,碰到了某個瓶頸了,通過增加該系統的機器來提升能力。

  2. 第二天,我們以 A 為起始流量,然后再次爬坡到 B。同樣壓測前做擴容 + 壓測中碰到瓶頸加機器。

  3. 以此類推,一直到最終流量達到目標流量為止。

  4. 每一天的壓測,也需要以慢慢爬坡的方式提升流量。在爬坡的某個高度穩定 5 分鍾,然后再次爬坡。穩定時間 5 分鍾,爬坡時間 30 秒。

    

發現並解決這個問題,本身就是壓測的目的之一。

正常來說,非核心鏈路,在大促來臨時不會擴大多少容量。當壓測的壓力增大時,很容易通過系統報警查到。

當發現這個問題的時候,一定要堅決要求業務方做系統改造,把非核心系 統的強依賴去掉。解耦的技術有很多,需要根據不同的業務規則來選擇方案。比如:業務降級、通過中間件解耦、異步化等。

一般來說,在壓測的過程中,當碰到壓測流量不能再升高的時候,會有很多原因,我們碰到的情況有以下幾種:

  1. 下游的某些服務化工程的能力達到瓶頸了,導致網關 RT 值升高,拖累整個集群的 QPS 上不去。

  2. 網關應用自身的能力達到瓶頸。

  3. 中間件 /DB 能力達到瓶頸。

  4. job 的能力達到瓶頸,導致數據處理不夠及時。

  5. 流量集中的頁面,消耗了集群大量資源,如:店鋪首頁、商品詳情頁等。

針對 2、3、4 這樣的情況,我們的選擇是毫不猶豫地加機器,代碼優化的性價比較低。

針對第 1 種情況,需要做一些分析,如果這樣的能力是在系統設計者的預期之內的,可以選擇加機器,如果完全超乎意料的,一定需要通過程序優化來提升能力,否則加了資源,可能還是瓶頸。

針對第 5 種情況,一定要做的事情是靜態化。因為這些流量集中頁面,一般都是展示性質的。不管如何做應用內的優化,獲得的能力提升遠不如做靜態化的收益大。

全鏈路壓測的方案有贊只是初試牛刀,我們已經看到了這個方案在提升 + 驗證集群處理能力方面巨大的價值。當前,這個方案做得還較粗糙,存在一些問題:

  1. 壓測只能在夜間做。

  2. 壓測中需要有很多業務開發人員陪同。

  3. 鏈路規划復雜度太高。

  4. 壓測控制台的穩定性還不夠高。

  5. 水位檢測與流量干預是通過肉眼觀察監控來實現。

后續我們團隊會繼續投入大量精力去完善整個方案。希望可以將壓測方案變成:

  1. 線上測試鏈路的機器人,實時檢測線上系統的正確性,同時沒有臟數據干擾。

  2. 測試同學手里的工具,做到流量壓測常規化,開發同學不用陪同。

  3. 壓測可以在白天進行,晚上熬夜畢竟不利於健康。

  4. 鏈路規划圖形化,並與數據工廠結合,完成數據的准備工作。

  5. 通過水位檢測與流量干預來保護系統,讓業務系統不會被壓崩潰。

 

 

轉自:https://blog.51cto.com/11009785/2412177


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM