流量錄製與回放在vivo的落地實踐

vivo網際網路技術發表於2022-02-15

一、為什麼要使用流量錄製與回放?

1.1 vivo業務狀況

近幾年,vivo網際網路領域處於高速發展狀態,同時由於vivo手機出貨量一直在國內名列前茅,經過多年積累,使用者規模非常龐大。因此,vivo手機出廠內建很多應用,如瀏覽器、短視訊、直播、資訊、應用商店等都是直面使用者的高併發、複雜系統。這些面向使用者的系統對使用體驗要求非常高,對這些業務的質量保障是重中之重。

1.2 測試痛點

隨著我們業務規模和複雜度不斷提高,各種問題和挑戰隨之而來。其中“在業務迭代升級甚至重構時,如何保證系統修改後的原有業務正確性?”是我們正在著手解決的其中一大難題。

簡單的業務系統通過常規的自動化測試工具加上人工測試即可解決,對於複雜系統,迴歸測試將變成一項艱難的工程。以我們推薦系統為例,一個推薦系統承擔了數十個推薦場景。如何在修改某個推薦場景的情況下保證不影響其他場景呢?

之前,我們是通過編寫自動化測試用例去解決,但是通過人工編寫的測試用例存在較多痛點:

  • 測試用例編寫難,資料構造難,使用者真實的使用行為不容易模擬。

  • 部分程式碼邏輯通過測試指令碼難以驗證。例如傳送訊息無法驗證訊息內容沒有問題。

  • 依靠人工構造用例難以考慮到系統所有場景,容易造成用例遺漏。

  • 隨著系統部署複雜度上升,環境維護成本也比較高。

針對這些複雜業務系統在迭代過程中迴歸測試效率低的問題,我們進行了一些持續性探索。

1.3 方案探索

我們結合vivo網際網路體系特色對業界一些方案進行了廣泛調研和參考並列舉了如下要求:新方案要能簡單高效,使用者無需過多理解就能輕鬆上手;業務接入成本足夠低,能夠快速進行迴歸測試;新方案通用性、擴充套件性要足夠好,能適應不斷變更的系統架構。

我們參考了一些頭部網際網路公司的技術方案,發現流量錄製與回放是一個非常好的選擇。業界內有不少頭部公司基於這種技術取得了不錯的進展和落地價值,為我們帶來了一些參考和信心。因此,對於流量錄製回放,我們進行了一些更加深入的探索和落地,也就是我們的月光寶盒平臺。

二、什麼是流量錄製與回放?

在介紹具體實踐之前,先簡單介紹一下什麼是流量錄製與回放?

流量錄製回放是通過複製線上真實流量(錄製)然後在測試環境進行模擬請求(回放)驗證程式碼邏輯正確性。通過採集線上流量在測試環境回放逐一對比每個子呼叫差異和入口呼叫結果來發現介面程式碼是否存在問題。

利用這種機制進行迴歸測試具備許多優勢:首先,通過錄制流量取代測試用例簡單高效,易於形成豐富的測試用例;其次,回放線上流量能完美模擬使用者真實行為,避免人工編寫存在的差異性;另外通過對錄製資料和回放資料採用物件對比方式能更深入、細微驗證系統邏輯;最後錄製的流量無需維護,隨取隨用,非常方便。

三、月光寶盒平臺

流量錄製與回放這種創新性的機制理論上是非常優秀的,但是實現起來卻不太容易,裡面有諸多難題需要解決。下面將給大家介紹流量錄製與回放在vivo網際網路體系的落地方案和遇到的問題以及我們是如何解決這些問題的。

3.1 底層架構

vivo月光寶盒平臺借鑑了開源Jvm-Sandbox-Repeater專案經驗,在Jvm-Sandbox-Repeater基礎上做了二次開發和改造。月光寶盒平臺包括了服務端和Java Agent兩大模組,整體架構如下圖所示。

3.1.1 業務架構

下圖是我們服務端整體業務架構,整個服務端可以劃分成任務管理、資料管理、覆蓋率分析、配置管理、監控告警等模組。

  • 任務管理模組管理使用者的錄製和回放任務,包括任務啟停、任務進度、任務狀態等;

  • 資料管理模組用來管理使用者錄製與回放的流量資料、以及分析資料;

  • 覆蓋率分析模組用來統計使用者迴歸覆蓋率指標;

  • 配置管理模組用來配置系統與應用的全域性引數;

  • 監控模組用來分析Agent各方面效能指標;

此外還有一些訊息通知模組。

3.1.2 Agent架構

下圖是Agent模組整體架構圖,Agent是流量錄製回放過程的核心。Agent是基於位元組碼機制實現,整體包括了四層結構:

  • 底層是基礎容器層,這一層是標準的Java-Agent實現;

  • 容器層上面是依賴層,這一層引入了我們需要的第三方資源、實現了位元組碼插樁機制、類載入隔離、class後設資料管理能力。

  • 依賴層之上是基礎能力層,在這一層實現了基本的原子功能,如錄製回放外掛的管理、資料管理、資料對比、子呼叫Mokc、執行監控、配置載入等能力。

  • 最上層是業務邏輯層,這一層可以將基礎邏輯功能組合在一起形成一個完整的業務單元。目前月光寶盒除了支援流量錄製與回放外,還支援了類似依賴分析、資料Mock等功能。

3.2 月光寶盒的啟動流程

錄製回放任務啟動最重要是能無侵入的將我們Agent下發到指定業務機器上並且自動將Agent Attach到我們業務程式上去。

月光寶盒的啟動流程如下圖所示,使用者首先在月光寶盒平臺配置錄製回放任務。完成配置後,配置資訊會入庫並同時通過VCS(vivo自研的作業排程平臺)將啟動指令碼、vivo-repeater-agent包下發至使用者配置的機器上。然後會執行shell指令碼並拉起sandbox,將agent attach至目標的JVM。隨後agent便可以在目標JVM上通過反射建立jvm sandbox,sandbox會通過spi拉起多個模組。

其中最重要是vivo repeater module,它會通過spi載入多個外掛,這些外掛最終會以ASM的方式增強目標JVM上的程式碼,從而實現位元組碼插樁,而流量的錄製與回放便是使用這些增強的外掛進行流量攔截、下發儲存完成的。

上述的執行流程允許使用者僅憑在控制檯配置少量資訊就能完成複雜的流量錄製與回放功能,下面我們將對錄製與回放的詳細過程進行說明。

3.3 流量錄製過程

下面是一個流量錄製的過程。一條流量的呼叫鏈路包括入口呼叫和若干次子呼叫,流量的錄製過程就是把入口呼叫和子呼叫通過一個唯一ID繫結成一次完整的呼叫記錄。月光寶盒找到入口呼叫和子呼叫合適的程式碼點(關鍵入口和出口),基於位元組碼插樁技術在該程式碼點進行程式碼增強,實現呼叫攔截,記錄呼叫的入參和返回值,然後根據相應的呼叫型別(如dubbo、http)生成一個錄製標識。當呼叫完成時,月光寶盒就採集到了整個流量的呼叫記錄,之後月光寶盒進行資料脫敏、序列化等操作,最後加密傳送到服務端進行儲存。

錄製是一個比較複雜的過程,在這個過程中我們持續踩了一些坑和遇到了一些問題,下面我列舉幾個比較重要的問題和大家分享一下。

3.3.1 難點一:Full GC

初期,vivo內部系統在使用月光寶盒時發生了Full GC的現象。經過分析得知是錄製的介面對guava呼叫非常多,導致錄製的請求流量太大從而造成了FULL GC。這是因為在完成一條介面流量的錄製前,錄製到的所有資料都在記憶體中,流量或者子呼叫一旦過大便容易導致頻繁Full GC。另外還有一些高併發系統介面比較多,同時錄製多個高併發介面存在效能壓力。因此,我們當時針對月光寶盒的效能問題進行了如下優化:

  • 嚴格限制併發錄製數量、限制單條流量子呼叫數量;

  • 對錄製過程進行監控、異常降級;

  • 合併相同的子呼叫錄製過程以減少子呼叫數量。

  • 對錄製快取佔用進行實時監控,超出警戒線及時進行降級處理。

經過不斷優化後,錄製過程非常平穩,再也沒有出現因為流量過大或者其他問題導致的Full GC現象。

3.3.2 難點二:呼叫鏈路串聯

流量錄製和回放存線上程上下文標識,vivo有不少系統有自定義業務執行緒池或者使用第三方框架自帶了執行緒池(例如Hystrix)會導致標識丟失導致無法串聯整個呼叫鏈路問題。

月光寶盒最開始是依賴Jvm-Sandbox-Repeater的基礎能力,在未使用執行緒池時,可以將錄製標識存放於ThreadLocal中串聯整個呼叫鏈路;而使用執行緒池時,我們利用自身Agent對Java 執行緒池進行自動增強透傳我們錄製回放標識,但這麼做會和公司的呼叫鏈Agent對執行緒池的增強產生衝突從而導致JVM異常崩潰,這種方式沒有辦法進行。

最終我們決定與公司呼叫鏈團隊合作,藉助呼叫鏈的Tracer上下文進行傳遞錄製標識,雙方都進行了一定程度改造特別是兩個Agent對HTTP、Dubbo埋點位置進行了一定調整。目前我們還沒有解決ForkJoinPoool這種執行緒池框架傳遞標識問題,後續會繼續對這類執行緒池做支援。

3.3.3 難點三:資料安全

第三個是錄製的流量如何保證資料安全,不少系統有一些銘感資料。對此,我們針對錄製的資料進行了可配置化的脫敏處理,使用者可以在月光寶盒平臺配置待脫敏欄位,Agent在錄製流量的時候後會根據配置資訊在記憶體中對這些欄位進行脫敏處理,保證傳輸過程和儲存過程的資料安全。另外,月光寶盒會嚴格控制流量詳情的檢視許可權,防止跨專案的資料查詢行為。

3.3.4 難點四:流量去重

第四個是流量去重問題。有時業務方在使用月光寶盒平臺時可能錄製到非常多的相同流量,造成後續回放耗時較長和問題排查效率低下。因此我們針對該現象思考如何能在保證介面覆蓋率的情況下儘可能減少相同流量的數量。目前的方案是根據流量入參和執行呼叫棧作去重操作。在錄製時,Agent會根據去重配置資訊進行流量去重操作,保證入庫的流量資料是唯一的。通過這種機制在一些場景大幅度減少了錄製流量數量,提高了流量的使用效率。

3.4 流量回放過程

下圖是流量回放的過程。流量回放是通過獲取錄製流量的入口呼叫,再次對迭代後的系統發起呼叫,然後去驗證系統邏輯正確性的過程。和錄製不一樣的是,回放對於外部的呼叫都是Mock的,這個過程不會真正的去訪問資料庫。回放過程會將錄製子呼叫和回放子呼叫的入參進行對比,如果引數不一致那麼會阻斷回放流量,如果引數一致會使用錄製子呼叫的結果進行Mock返回。回放完成同樣會產生一個響應結果,這個時候我們會對比原始錄製結果和回放響應結果,根據該對比結果和子呼叫的對比結果就能得出被測試系統的正確性了。

回放是一個更加複雜的過程,因為錄製和回放一般在不同環境的不同版本系統執行,可能存在較大差異,如果處理不當回放成功率會比較低。起初接入月光寶盒的應用成功率都比較低,後來經過長期優化和精細化運營,月光寶盒的回放成功率不斷提升。下面將分享幾個遇到的難點以及一些應對策略。

3.4.1 難點一:時間差異

第一個難點是時間差異的影響,一些系統業務邏輯裡面存在和時間有關邏輯,由於錄製和回放時間不一樣導致不少場景有時間相關邏輯導致回放失敗。針對這個問題我們進行了一些研究,並最終將回放時間和錄製時間保持一致。

對於System.currentTimeMillis() 這種native方法,Agent會動態修改方法體的位元組碼,代理掉業務對該方法的呼叫,動態替換為平臺事先定義的獲取時間方法從而保證時間替換。解決了這個問題對於Date這些類也就迎刃而解了。另外,JDK8中的LocalDateTime等非native時間方法就比較簡單了,直接Mock掉時間方法呼叫即可。使用這些機制基本上消除了業務邏輯裡面的時間差異問題,消除了因為時間導致的回放失敗問題。

3.4.2 難點二:系統降噪

第二個難點是如何處理系統噪音。很多系統裡面存在一些traceId、sequenceId等通用噪音欄位,這些噪音欄位也是導致回放失敗的因素。初期業務接入時需要逐個排查,整體效率比較低。後來月光寶盒支援了全域性級別、應用級別、介面級別的噪音欄位配置,很多通用的噪音欄位可以直接通過全域性配置解決,業務接入只需要個性化配置噪音欄位即可,通過這種分層次的降噪配置大幅提升業務接入效率。

3.4.3 難點三:環境統一

第三個難點是環境差異。以vivo網際網路體系為例,一般線上上環境進行錄製,在測試環境和預發環境進行回放,剛開始因為環境不一致導致回放失敗的案例非常多,影響了整體回放成功率。針對這個問題,我們進行了一系列探索和解決。月光寶盒線上上錄製時會同時錄製一份線上環境配置,線下回放時會利用線上配置自動替換掉線下的環境配置,通過這種機制保證了配置中心資料一致性。另外對於一些系統記憶體性質的配置資料,月光寶盒支援配置介面同步記憶體資料。通過這些解決方案,我們基本上保證了線上、線下環境的一致性,大幅度減少了因為環境配置導致的回放失敗數量。

3.4.4 難點四:子呼叫匹配

第四個難點是子呼叫匹配問題。最開始指定的匹配策略無法滿足複雜業務場景,經常出現匹不到流量或者匹配錯誤導致回放難以成功。後面我們針對不同的回放子呼叫指定不同的匹配策略:快取型別按照快取Key去匹配;HTTP型別按照URI匹配;Dubbo按照介面、方法名、引數型別匹配等。另外,如果匹配到多條相同子呼叫,我們會比較系統呼叫棧和入參請求引數,結合呼叫棧和請求引數兩個維度尋找最可能匹配流量,通過這些精細化匹配策略提升了匹配成功率。

3.4.5 難點五:問題排查

第五個難點是問題排查了,錄製和回放是非常複雜的過程,由於Agent執行在業務端機器出現任何問題去分析排查難度都很大。為了提升排查效率我們支援了若干手段:

1)、支援回放分析呼叫鏈路圖,下面會詳細講解;

2)、任務啟動詳細命令和引數輸出,通過輸出任務啟動命令引數,我們在本地非常方便啟動和模擬線上執行的錄製和回放任務,提高了排查效率。

3)、本地一鍵安裝Agent,在本地修改了Agent程式碼後我們一鍵就可以將新的Agent在本地遠端測試環境安裝。

除了這些功能外我們還開發了很多效率工具,這裡就不一一展開說明了。

3.5 豐富的協議支援

vivo業務種類非常多,不同業務技術棧有差異。這些系統接入我們平臺需要針對性的適配相應外掛。通過我們不斷完善外掛,目前我們已經支援了下面數十種外掛,基本已經覆蓋了各種常見的中介軟體。

3.6 月光寶盒平臺其它特點

3.6.1 視覺化呼叫鏈路

起初,業務回放失敗只能依靠平臺開發人員協助排查,整個排查過程費時費力。針對這種情況,我們提供了一些視覺化的運維工具。其中一個就是鏈路呼叫分析圖。我們對錄製和回放過程進行詳細跟蹤和記錄,通過呼叫鏈路圖幫助使用者分析執行過程。出現問題時,使用者可以清晰看到具體異常位置和根本原因,提高了排查效率。

3.6.2 迴歸程式碼覆蓋率

月光寶盒的優勢之一是具備很高的流量覆蓋率很容易形成高覆蓋率。如何去驗證回放的流量確實覆蓋了業務系統的各個場景,讓使用人員使用了月光寶盒就不存在疑慮放心大膽的上線。

針對這個問題,月光寶盒提供了程式碼迴歸覆蓋率的統計能力,我們利用內部的CoCo-Server平臺統計了系統全量覆蓋率和增量程式碼覆蓋率。為了識別覆蓋率資料來自流量回放,我們在回放前需要呼叫介面清理機器記憶體裡面的覆蓋率資料,這種方式可能存在和其他流量衝突可能性,後續等CoCo-Server平臺完成流量染色區分流量來源就沒有這方面擔憂了。

3.6.3 定時錄製與回放

雖然流量錄製和回放的操作流程已經非常簡便了,但對於一些頻繁使用的業務人員來說仍然較為繁瑣,特別是有些版本涉及了過多的系統,同時錄製回放多個系統效率比較低下。為了提高使用效率,月光寶盒支援了使用者自定義定時錄製、回放任務的能力。通過定時任務可以批量定時錄製和回放,減小了人工操作成本,提高了平臺使用體驗。

3.7 月光寶盒其他應用

除了自動化測試,我們在其他方面也進行了一些探索和應用。第一個是流量壓測,使用者可以通過月光寶盒平臺分析錄製的流量生成的壓測模型。第二個是問題定位,使用月光寶盒平臺線上下回放重現線上問題,幫助測試、開發人員復現問題現場。最後一個是安全分析,常態化錄製測試環境流量可以幫助安全工程師提供流量素材,識別業務系統安全風險等。

四、核心指標

月光寶盒平臺的接入非常簡單,業務初次接入基本上10分鐘內就可以完成。平臺上線不到一年就累計接入了近200個業務系統,很多都是vivo網際網路體系中最為核心的應用。一年以來累計完成1W+次錄製與回放。接入月光寶盒後,平臺提前發現了不同業務的累計數十個線上問題,有效減少線上事故發生次數。在很多場景下,使用月光寶盒平臺的流量錄製回放功能可以提升測試、開發人員80%以上的工作效率,總體來看超出了我們的預期目標。

五、未來規劃

在未來規劃上我們主要聚焦在兩方面,一個是功能規劃,第二個是協同開源。

5.1、功能規劃

目前我們完成了平臺基礎功能建設,但是還存在使用效率等問題,後續我們重點會在下面兩個方向去優化:

1)希望能夠實現精準化測試,避免每次全量回放錄製資料,進一步降低迴放耗時。精準化測試需要分析變更程式碼,獲得變更程式碼的影響範圍,然後基於此篩選出對應的流量進行回放,這樣就能減小回放覆蓋範圍。

2)是希望能夠與vivo網際網路體系下的CI/CD結合,當業務系統釋出到了預發環境後,能夠自動觸發錄製和回放任務。這樣在上線前能給系統進行一些風險識別同時提升使用者使用效率。

5.2 開源共創

開源是未來軟體的發展趨勢,對於開源,我們一直是受益者,我們也期望能積極參與到開源專案為社群貢獻力量。我們參與了開源https://github.com/alibaba/jvm-sandbox-repeater專案,成為了社群核心貢獻者。第一期累計貢獻了5個社群沒有但是比較重要的外掛。後續我們準備繼續按照下面規劃逐步向社群回饋月光寶盒的一些核心能力。

作者:vivo網際網路伺服器團隊-Liu YanJiang、Xu Weiteng

本文根據Liu YanJiang老師在“2021 vivo開發者大會"現場演講內容整理而成。公眾號回覆【2021VDC】獲取網際網路技術分會場議題資料。

相關文章