一、為什么要使用流量錄制與回放?
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】獲取互聯網技術分會場議題資料。