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