流量回放平臺 AREX 在攜程的大規(guī)模落地實踐
作者簡介
攜程AREX團隊,機票質(zhì)量工程組,主要負責(zé)開發(fā)自動化測試工具和技術(shù),以提升質(zhì)量和能效。
導(dǎo)語
AREX 是一款由攜程開源的流量回放平臺,孵化于機票BU內(nèi)部。聚焦錄制回放核心鏈路的建設(shè),從基礎(chǔ)方案建設(shè)到核心事業(yè)線的深入落地驗證,在集團復(fù)雜業(yè)務(wù)場景下不斷迭代和優(yōu)化下,積累了大量經(jīng)驗,取得了可見的成果。在攜程落地至今已有 4000+ 應(yīng)用接入,交付率和缺陷數(shù)均有所改善。
本篇文章主要介紹AREX在攜程內(nèi)部落地實踐過程中遇到的一系列挑戰(zhàn)和解決方案,以及如何通過AREX快速部署一站式流量錄制回放解決方案來降低接入成本,快速落地。
一、背景
流量錄制回放技術(shù)在性能測試、回歸測試、自動化測試以及線上問題快速修復(fù)方面有廣泛的應(yīng)用前景,可以幫助技術(shù)團隊解決復(fù)雜業(yè)務(wù)場景和系統(tǒng)架構(gòu)下的穩(wěn)定性保障及研發(fā)過程中的效率問題。
然而在技術(shù)方案落地時,會面臨很多的挑戰(zhàn),比如基礎(chǔ)設(shè)施建設(shè)難度大、前期投入成本和收益不成正比、落地場景模糊不清等。
二、方案
目前市場上已知的開源解決方案大部分都是在Jvm-Sandbox-Repeater基礎(chǔ)上進行二次開發(fā)和改造,核心原理也都是通過錄制線上真實流量然后在測試環(huán)境進行回放,驗證代碼邏輯正確性。那么可能有人會問:既然已有成熟的解決方案,為什么還要“重復(fù)造輪子”?
首先,JVM SandBox支持的組件有限,遠不能滿足攜程內(nèi)部廣泛使用的中間件和框架。且JDK底層的支持也不夠徹底,比如異步線程上下文傳遞,需要依賴其他第三方組件。
其次,Jvm-Sandbox-Repeater雖然提供了基本的錄制和回放功能,但若要構(gòu)建一個完整的業(yè)務(wù)回歸測試解決方案,我們還需要一個完善的后臺支持系統(tǒng),負責(zé)數(shù)據(jù)的采集、存儲和比對工作。
最后,官方文檔的缺乏以及社區(qū)活躍度的不足,使得我們在后續(xù)的二次開發(fā)過程中可能面臨無法及時獲得官方支持的風(fēng)險。
基于這些考慮,我們決定自主研發(fā)流量錄制回放平臺AREX:
1)支持更廣泛的中間件和組件錄制與回放,而且能夠模擬各種復(fù)雜的業(yè)務(wù)場景,如本地緩存、當(dāng)前時間等。
2)作為一個全面的解決方案,還要配備有完善的配套設(shè)施,如前端界面、回放服務(wù)和報告分析等,實現(xiàn)從流量采集、流量回放,到比對驗證、生成報告的一站式工作流程(如下圖所示)。
下面,我們將深入探討實施過程中遭遇的挑戰(zhàn)、針對性的解決策略,以及攜程內(nèi)部的應(yīng)用實例,希望可以為大家的實踐提供實質(zhì)性的幫助和指導(dǎo)。
三、技術(shù)挑戰(zhàn)
3.1 跨線程、異步場景下的流量采集
流量錄制需要把一次業(yè)務(wù)請求里涉及到的所有鏈路節(jié)點采集下來,不僅是主入口的,還有內(nèi)部調(diào)用各種框架的請求和響應(yīng),如Mybatis、Redis、Dubbo等。然而公司很多項目會使用到線程池,異步編程的場景,比如在一次請求中主流程會Fork出很多子任務(wù)/線程并行工作,有些任務(wù)查詢Redis,有些會調(diào)用RPC接口、有些去操作數(shù)據(jù)庫等完成不同的業(yè)務(wù)場景,底層也會牽涉到大量線程的切換。
這樣就需要保證在一次請求中把這些在不同線程里執(zhí)行的操作都采集下來,我們是通過Trace傳遞的思路解決這個問題的,即通過修飾各種線程池和異步框架,使用一個recordId在線程間傳遞的方式串聯(lián)起來,完成一次完整的用例錄制。比如Java里的CompletableFuture、ThreadPoolExecutor、ForkJoinPool、第三方的Tomcat、Jetty、Netty使用的線程池,以及異步框架Reactor、RXJava等,實現(xiàn)不同線程間的傳遞。
3.2 非冪等接口回放不產(chǎn)生臟數(shù)據(jù)
例如,在訂單落庫和調(diào)用第三方支付接口等關(guān)鍵場景中,流量回放時需確保利用Mock來避免實際數(shù)據(jù)交互。這樣做可以防止在測試過程中產(chǎn)生不必要的數(shù)據(jù),從而避免對正常業(yè)務(wù)流程造成干擾。流量回放的核心機制在于攔截并Mock框架調(diào)用,使用錄制的數(shù)據(jù)來替代真實的數(shù)據(jù)請求,確保測試過程中不會發(fā)生任何真實的外部交互,如數(shù)據(jù)庫寫入操作或第三方服務(wù)調(diào)用,從而有效防止回放測試中臟數(shù)據(jù)的寫入。
目前我們的Java Agent已支持Spring、Dubbo、Redis、Mybatis等開源框架,完整列表請參考下方。
3.3 因登錄鑒權(quán)、token過期問題引起的回放失敗
在實際的流量回放過程中,我們經(jīng)常遇到這樣的問題:許多Web應(yīng)用在接口訪問前實施了登錄鑒權(quán)校驗。如果鑒權(quán)失敗或登錄的token已經(jīng)過期,接口訪問將被拒絕,這可能導(dǎo)致大量用例在回放時失敗。雖然可以通過配置白名單來解決部分問題,但我們尋求的是一種更為通用的解決方案。
理想的方案是在回放過程中,能夠Mock如Spring Security、Apache Shiro、JWT等鑒權(quán)框架,從而繞過鑒權(quán)和token校驗步驟,確保接口能夠在回放環(huán)境中正常執(zhí)行。
3.4 時間敏感業(yè)務(wù),如支付超時場景回放
如果錄制時的當(dāng)前時間和回放時的當(dāng)前時間不一致,可能會導(dǎo)致一些超時判斷邏輯出現(xiàn)預(yù)期外的差異。例如,在判斷訂單是否超時未支付的場景中,我們通常會使用 currentTime - orderCreateTime > 30 分鐘 作為判斷依據(jù)。如果在錄制時訂單尚未超時,但在半小時后進行回放時,由于系統(tǒng)當(dāng)前時間的變化,可能會錯誤地觸發(fā)支付超時的處理邏輯。
為了解決這一問題,我們提出了一種解決方案:在錄制過程中,同時記錄下當(dāng)時的當(dāng)前時間,并僅錄制一次。在回放過程中,通過Mock與當(dāng)前時間相關(guān)的類,如 Date、Calendar、LocalTime、joda.time 等,使得回放時使用的當(dāng)前時間實際上是錄制時記錄的時間。這樣可以保證在回放過程中,與時間相關(guān)的邏輯判斷能夠與錄制時保持一致,從而確保測試結(jié)果的準(zhǔn)確性和可靠性。
3.5 本地緩存問題
在應(yīng)用中,為了提高性能,通常會將一些常用數(shù)據(jù)存儲在本地緩存中以供快速訪問。然而,在流量錄制回放的場景中,緩存的行為可能會對回放結(jié)果產(chǎn)生影響。
在錄制過程中,如果請求的數(shù)據(jù)已經(jīng)被緩存,那么系統(tǒng)會直接從緩存中提供數(shù)據(jù),而不會觸發(fā)對數(shù)據(jù)庫或外部接口的查詢。但在回放環(huán)境中,由于缺乏預(yù)先加載的緩存數(shù)據(jù),相同的請求可能會導(dǎo)致應(yīng)用程序去查詢數(shù)據(jù)庫或調(diào)用外部接口,產(chǎn)生新的調(diào)用(new call),導(dǎo)致回放失敗。
為了解決這一問題,我們實現(xiàn)了對流行緩存框架的支持,如 Guava Cache 和 Caffeine Cache,確保在回放時能夠模擬緩存的行為并保持一致性。這樣一來,在回放過程中,即使是對緩存的請求也能按照錄制時的狀態(tài)返回預(yù)期的結(jié)果,避免了不必要的新調(diào)用。
對于那些使用自定義緩存框架的情況,AREX 平臺提供了靈活的配置選項,允許通過動態(tài)類的方式進行適配。這意味著即使是非標(biāo)準(zhǔn)的緩存實現(xiàn),也能夠被 AREX 平臺兼容并正確地進行流量回放。
以上解決方案都是默認支持,基本不需要額外處理,另外如果是公司內(nèi)部研發(fā)的框架也需要錄制回放的話,可以以插件的方式擴展。
四、落地挑戰(zhàn)
4.1 安裝部署要做到簡單便捷,快速上手,減少接入成本
AREX是一套完整的解決方案,除基本的錄制回放功能外,還有前端、調(diào)度、報告分析、存儲等配套服務(wù)。本著開箱即用、快速接入的原則,AREX提供了多種部署方式:一鍵部署、非容器部署、私有云部署的方式,安裝完成后只需配置一些基礎(chǔ)參數(shù)即可自動采集流量和進行回放對比差異:
此外AREX還支持單機模式,可以在本地不需要安裝的情況下快速上手體驗。
4.2 符合公司風(fēng)控、數(shù)據(jù)安全要求
錄制生產(chǎn)上真實流量時,在涉及安全或者一些商業(yè)性敏感數(shù)據(jù)的情況下,還需要針對某些敏感信息通過脫敏規(guī)則進行數(shù)據(jù)的變形,實現(xiàn)敏感隱私數(shù)據(jù)的可靠保護。
AREX選擇在進行數(shù)據(jù)落庫時對數(shù)據(jù)進行脫敏,以保護敏感信息的安全性。具體實現(xiàn)方式是通過 SPI 機制,加載外掛 JAR 包,動態(tài)加載加密方式。
4.3 提高用戶體驗,快速定位問題
在實際使用過程中,錄制和回放的用例數(shù)量巨大,為了減輕使用者分析差異時的工作量,AREX對存在相同差異的場景用例進行了聚合,加快排查問題的速度。
通過調(diào)用鏈可以快速定位問題所在范圍,并且對時間戳、uuid、ip等噪音節(jié)點進行降噪,減少干擾。
如果是一些業(yè)務(wù)比較復(fù)雜的應(yīng)用線上問題本地難以復(fù)現(xiàn)時,AREX也支持在本地進行調(diào)試快速排查問題。
4.4 技術(shù)方案是否成熟、安全、可靠
AREX基于Java Agent技術(shù),采用業(yè)界成熟的字節(jié)碼修飾框架ByteBuddy,安全穩(wěn)定,代碼隔離,帶有自我保護機制,在系統(tǒng)繁忙時會智能降低或關(guān)閉數(shù)據(jù)采集頻率。且在攜程集團內(nèi)部已穩(wěn)定運行2年有余,線上得到充分驗證。
五、最佳實踐
目前流量錄制回放服務(wù)作為獨立的選項集成到公司的CI/CD系統(tǒng)中:
1)首次接入流程:在首次接入流量錄制回放時,只需在 CI Pipeline 選擇 Flight AREX Agent 服務(wù),這樣在應(yīng)用打包成鏡像的過程中,會把 AREX 啟動腳本 arex-agent.sh 包含在發(fā)布包內(nèi)。
2)發(fā)布與 Agent 加載:在應(yīng)用發(fā)布過程中,先前的腳本啟動后會拉取最新的 arex-agent.jar,并通過修改 JVM Options 掛載 AREX Agent(-javaagent:/arex-agent.jar)。
3)版本控制與灰度發(fā)布:啟動腳本后會根據(jù)應(yīng)用的 AppId 拉取與之匹配的 arex-agent.jar 版本,實現(xiàn)灰度發(fā)布和按需加載,比如只有某些特定的應(yīng)用會加載 Agent 新功能。
同樣,如果是首次回放,操作也很簡單:
1)創(chuàng)建Pipeline:在 Gitlab 或 Jenkins 中,創(chuàng)建一個 Pipeline,在 ArexTest Job 腳本中調(diào)用 AREX 提供的回放地址,定時執(zhí)行流水線。
2)自動觸發(fā)流量回放:研發(fā)人員在提交代碼后會自動觸發(fā)流量回放。
3)回放結(jié)果推送與發(fā)布控制:回放完成后 AREX 會把回放用例數(shù)、通過率、失敗率等指標(biāo)推送給相關(guān)人員做統(tǒng)計和分析,只有當(dāng)通過率達到預(yù)定標(biāo)準(zhǔn)時,代碼才被允許發(fā)布到生產(chǎn)環(huán)境。
下圖是 AREX 流量錄制回放平臺在公司研發(fā)測試發(fā)布各個環(huán)節(jié)如何發(fā)揮作用的,供大家參考:
針對每次迭代,代碼提交后測試自動執(zhí)行,并反饋測試報告,開發(fā)和測試人員只需要關(guān)注在新業(yè)務(wù)的研發(fā)、驗證上即可,脫離那些繁瑣的數(shù)據(jù)和腳本,通過流量回放在軟件研發(fā)全生命周期內(nèi)進行多環(huán)節(jié)針對性優(yōu)化、合力賦能,形成一個自動化測試和持續(xù)集成的閉環(huán)。
六、落地成果
在攜程集團復(fù)雜業(yè)務(wù)場景不斷迭代和優(yōu)化下,目前已有 4000+ 應(yīng)用接入,交付率和缺陷數(shù)均有所改善:
七、擁抱開源
在攜程內(nèi)部經(jīng)過長期穩(wěn)定運行并驗證其可靠性后,我們在2023年將AREX平臺開源(https://github.com/arextest),希望能夠幫助更多企業(yè)高效、低成本地把流量錄制回放技術(shù)解決方案落地。
過去一年,我們致力于開源社區(qū)的建設(shè),目前已有上千個外部用戶接入使用AREX。
AREX的愿景是是在需求快速迭代的同時保障質(zhì)量,降低成本,提升效能。這一愿景已在攜程及眾多開源用戶的實踐中得到驗證,帶來了顯著的業(yè)務(wù)價值。
展望未來,我們將持續(xù)依托活躍的社區(qū)力量,響應(yīng)并解決用戶的疑問,不斷優(yōu)化AREX。在此誠邀每一位開發(fā)者加入社區(qū)并試用,共同見證AREX的成長與進步。