參與了我們業務的全鏈路壓測,雖然過程磕磕絆絆,壓測的當天晚上還在寫壓測腳本,但是核心鏈路的壓測還是做了起來,效果也不錯,當前晚上就爆出了一個P1級的bug。這篇文章就總結下如何做核心鏈路的全鏈路壓測。

時機

首先要清楚的一點就是,什么時候開始做全鏈路壓測?我們有另外一個業務線,現在就沒有打算做,那個業務線的日均單不到十萬,而要壓測的業務線的日均單到了200萬,但這並不意味着200萬是一個標准,我覺得可以從下面幾點考慮:

  • 業務發展速度。在可以預期的一段時間(最好是半年,一個季度有點晚)內,業務會有較快速的發展,線上機器必須要大幅度擴容;但是,擴容有的時候並不是線性的,從兩台擴展到四台,你得服務能力或者能提高兩倍,但是在繼續擴容,服務能力就有可能提高不上去了,因為要受限於其他的模塊,比如,DB,公共組建,中間件等等
  • 鏈路的復雜程度在擴張。一般而言,隨着業務的發展,我們的接口會越來越多,系統會逐漸的做分布式,業務線內部的模塊越抽象越多,業務線跟其他業務線的交互也也越來越多,我們無法單純的根據自己系統的處理能力來評估接口的服務能力。
  • 對單機壓測結果越來越沒有自信。這也是一個很好的指標,一般而言,我們都會壓一下我們自己的模塊,但是身為模塊的owner,自己越來越清楚,單機的壓測不代表真實的場景,內心會越來越虛,這個時候,就要考慮全鏈路了。

方法

下面具體看看要做全鏈路需要哪些工作。

梳理核心鏈路的流程和邊界

因為全鏈路一定會設計多個流程,多種技術,多個依賴,所以,要做全鏈路壓測,首先要梳理核心鏈路的流程,明確鏈路的邊界,我覺得梳理這個是比較簡單的,因為一個業務再復雜,它的核心鏈路肯定有限,例如,我們的核心鏈路就包括:

  • 創建訂單
  • 開始形成
  • 獲取行程費用
  • 結束訂單
  • 支付訂單
  • 完單

核心鏈路是一個業務的核心,這一塊應該可以很快梳理清楚,但是,難點在於梳理清楚鏈路的邊界。例如:

  • 開始訂單要做風控
  • 結束訂單要發券
  • 結束訂單要通知用戶費用
  • 完單后要通知營銷
  • 。。。

在核心鏈路的基礎上,我們會有很多的分支業務,而這些分支業務有的可以參與壓測,有的不能參與壓測:原因多種多樣,比如,這個分支業務不是我們自己公司的,或者這個分支業務本身就不怎么重要,可以降級掉,甚至有的業務就是不能壓測,比如給用戶下放push消息。

在具體實施的時候,業務反復跟整個鏈路的每個業務owner反復確認,哪些是核心業務,哪些是分支業務,哪些參與壓測,哪些不參與壓測,把這些形成文檔,逐個跟進。

提供全鏈路壓測的底層支持

要做全鏈路,要實現非核心鏈路的降級,就必須對底層的產品,例如中間件,數據庫訪問,MQ等做改動,讓這些中間件支持全鏈路壓測。我們整體看看,一般需要哪些改動。

我們把模型簡化一下,如下圖,雖然是簡化的,但是基本上包括主流的分布式業務的技術棧。

可以看到,底層主要需要提供下面的支持:

  • 全鏈路透傳壓測標志:必須有一種在全鏈路透傳壓測標志的能力,並且必須基於一次請求,也就是同一個traceId,現在,大部分分布式業務都會接入trace系統,例如,google的dapper,阿里的鷹眼等,對trace系統進行改造,使其能夠透傳壓測標志,需要透傳的路徑大概有:
    • HTTP,RPC(DUBBO),MQ,線程池等
  • 影子表:參與壓測的業務,要逐個排查自己依賴的數據庫,然后創建影子表,影子表必須跟正常表的schema保持一致,可以在每次壓測時候手動創建,也可以推動DBA自動創建。創建好影子表后,如果當前流量是壓測流量,那么寫入和讀取都走影子表。如果有自己的數據庫中間件最好,沒有的話可以借助於Mybatis的Interceptor機制。
  • 日志-影子目錄:為了防止壓測流程的日志對正常日志造成干擾,需要改造日志組件,將壓測流量產生的日志落入到影子目錄。影子目錄可以有日志組件自動創建。
  • MQ支持是否消費壓測流量:有的時候,全鏈路會通過MQ進行傳遞,所以,必須在消費MQ的時候進行選擇:是否選擇消費壓測流量的MQ消息。這就需要對MQ系統進行改造,一方面使其可以透傳壓測流量,另一方面,需要支持配置是否消費壓測的MQ消息
  • 緩存,大數據隔離:還有一些場景,比如,緩存層,大數據層對壓測流量的處理也要考慮隔離。緩存可以使用不同的集群;大數據可以直接不收集壓測的數據。
思考全鏈路壓測的數據怎么mock

流程支持之后,還有關鍵的一步,就是考慮如何構造壓測的mock數據。在使用影子表之后,可以比較輕松的實現跟正常數據隔離,那剩下的就是好構造好mock數據,有幾點需要考慮:

  • 用戶數據要提前做好認證等准備工作
  • Mock數據要盡可能跟真實數據保持一致,比如,價格水平,圖片數量,地址信息等等
  • Mock數據有些限制需要放開,比如,庫存,一些運營性質的活動可以取消等
  • 千萬不要污染正常數據:認真梳理數據處理的每一個環節,確保mock數據的處理結果不會寫入到正常庫里面
做好壓測流量的降級預案

這一點尤其重要,特別當業務特別的復雜的時候,一定要確認好,第三方依賴能不能接收壓測流量,所以,只要依賴第三方的服務,我們都要接入壓測流量降級的開關,防止對第三方服務的污染。實現上,可以集成到RPC機制上,也可以提供類似於單獨的限流組件。

梳理監控體系

確認好流程的技術支持和Mock數據的支持后,還要讓每個業務梳理自己的監控,確保壓測時候能夠准確,及時的發現問題。

  • 核心接口和核心依賴的流量和耗時監控
  • 中間件組件,緩存,數據庫的監控報警
  • 機器的指標報警
線下做好預演

真實的壓測之前,肯定要進行預演,預演主要確認:

  • 壓測流程是否寫入到了正確的目的地,例如,寫入到影子表,影子目錄,壓測cache等等
  • 壓測流量的降級是否完備和有效
  • 進一步確保監控都已到位
盡量模擬現實

我們壓測的腳步要盡可能的模擬現實,比如:

  • 購買的行為:不是下單后立即購買,而是要等一下子
  • 騎車子的行為:開鎖后並不是里面換車,而是騎一會
  • 用戶付款的行為:壓測時候肯定不會真的讓用戶付款,所以我們得模擬用戶付款
  • 購買商品的數據
  • 。。。

壓測的腳步要跟各個業務確認,盡量跟線上真實的用戶行為保持一致

逐步平滑加壓

壓測的時候,逐步加壓,並且要保持平滑加壓,不要把一秒的流量都在前面幾毫秒內都壓出去。

形成報告

每次壓測后進行復盤,總結壓測中的問題,壓測結果,機器的指標等數據形成報告發給大家,制訂好后續的Action以及跟進的負責人。

推進

全鏈路壓測的技術難點不多,除了要花時間梳理流程和思考如何處理數據之外,最難的就是整個鏈路跨多個業務,甚至部門,需要跟進每個業務線的進度,確保大家能夠在給定的時間點進行聯調以及進行壓測。在推進的時候,按照核心鏈路所在的模塊進行跟進,每個模塊出一個owner,各個owner跟進核心的接口和依賴,每周大家碰一下同步下總體的進度。