簡化后端服務的 A/B/n 測試
A/B/n 測試,或拆分測試,是一種測試過程,用戶流量通過該過程隨機分布在應用程序(或應用程序組件)的兩個或多個版本之間。評估業務指標以確定獲勝版本——產生更大利潤或業務價值的版本。例如,購物應用程序可能使用收入和用戶參與度作為業務指標。
我們專注于部署在 Kubernetes 中的后端服務的 A/B/n 測試。例如,在下圖中,前端可能是一個基于Node.js的在線商店。它依靠后端推薦服務向用戶提供產品建議。我們有興趣對推薦服務的多個版本進行 A/B/n 測試。在圖中,我們有兩個版本,v1(當前或默認版本)和v2 (候選版本)。
計算業務指標
A/B/n 測試依賴于對業務指標的評估。這些指標衡量應用程序特定版本的好處或價值。例如,在在線商店應用程序中,相關指標可能是銷售收入或用戶參與度。業務指標是特定于應用程序的;它們不能由基礎設施計算,而必須由應用程序本身計算。當銷售收入等指標由應用程序組件(如上面的前端在線商店)計算時,間接包括了后端推薦引擎的貢獻。但是,前端組件無法將度量值與特定版本的后端相關聯,因為它通常不知道使用了哪個版本的后端服務。
Iter8 SDK
為了正確地將指標歸因于后端版本,前端有必要知道每個用戶會話正在使用哪個后端版本。為了協助前端服務,可以使用 Iter8 SDK。Iter8是一個開源的Kubernetes發布優化器,可以幫助您在幾秒鐘內開始測試 Kubernetes 應用程序。使用 Iter8,您可以執行各種實驗,例如 SLO 驗證、金絲雀測試、混沌注入測試,以及現在的 A/B/n 測試。Iter8 SDK 提供了兩個接口:
- Lookup(component, user_session),它標識一個組件的版本,調用者應該使用該版本向給定的用戶會話發送請求。
- WriteMetric(metric_value, component, user_session),它將度量與組件的推薦版本相關聯。
下面的序列圖顯示了我們的購物應用程序對這些接口的使用:
為響應用戶請求,前端組件調用Lookup()以確定要使用哪個版本的后端組件。Lookup()返回固定數量的用戶定義曲目標簽之一。Lookup()保證為相同的用戶會話推薦相同的曲目標簽,確保后續對后端的調用將發送到相同的版本。然后,前端服務將其請求發送到推薦的后端,使用軌道作為路由的關鍵。當前端稍后為用戶會話計算業務指標時,它可以安全地與推薦的后端版本相關聯。WriteMetric()可用于執行此操作,從而無需前端跟蹤到后端版本的映射。
由于Lookup()返回一組固定的軌道標簽中的一個,前端服務必須配置為將流量路由到一組固定的服務——每個軌道一個。要跟蹤的版本的映射隨時間變化,并且作為候選版本部署的一部分使用已部署的 Kubernetes 對象上的標簽完成。
顯然,SDK 的引入對應用程序前端組件的開發人員提出了要求。此外,該方法依賴于前端應用程序可以根據一組軌道標識符路由后端請求的假設。這意味著對應用程序配置的要求。我們通過示例演示使用 Iter8 SDK 是多么容易。
Iter8 SDK 使用 gRPC 實現。該協議緩沖區文檔中描述了這些接口。可以從中為各種語言生成特定于語言的代碼。接口本身由 A/B/n 服務實現。
A/B/n 測試的應用程序開發
我們將考慮一個簡單的兩層應用程序。用 Node.js 編寫的前端代表一個在線商店。 用Go編寫的后端表示由前端調用的推薦引擎,用于向用戶展示替代產品。可以在此處找到此應用程序的完整源代碼。
前端組件支持兩個接口:
- /getRecommendation要求產品推薦。
- /buy完成購買。
作為購買(請求)的副作用,/buy計算用戶會話的業務指標。接口的實現/getRecommendation依賴于后端推薦服務。我們想在此后端推薦服務上運行 A/B/n 測試。
Iter8 SDK 使用 gRPC 實現。這些接口在協議緩沖區文檔中進行了描述。可以從中為各種語言生成特定于語言的代碼。我們生成的代碼在示例應用程序中,可以直接復制以用于您自己的應用程序。
要使用 Iter8 SDK,需要 gRPC 和生成的庫:
并實例化一個客戶端:
此客戶端用于兩種用例:調用后端服務之前和寫入指標值時。
調用后端服務
在調用后端推薦服務之前,需要Lookup()先調用該方法。返回的軌道標識符應該用作索引來選擇發送請求的路線。在我們的示例前端中,這可以按如下方式實現:
在此實現中,用戶會話是從請求標頭中提取的X-User。請注意,如果與 Iter8 SDK 交互出現任何問題,將選擇默認路由。可以在此處找到完整的示例代碼。
編寫指標
當/buy調用接口時,表示銷售完成,計算業務指標。在我們的示例應用程序中,一個隨機值被分配給指標sample_metric:
而已!不需要進一步的更改,無論運行了多少 A/B/n 測試——或者沒有。
可以在此處 (Node.js)找到完整的示例前端代碼。Python和Go中提供了替代實現。與節點示例一樣,生成的代碼可以直接復制到您自己的應用程序中。
為 A/B/n 測試部署應用程序
在部署將要進行 A/B/n 測試的應用程序組件時,唯一的要求是添加 Iter8 A/B/n 服務用于標識組件版本的標簽。在我們的例子中,我們計劃只測試后端推薦組件。
Iter8 SDK要求每個版本部署的資源實例中至少有一個包含以下標簽:
- app.kubernetes.io/name:應用程序(組件)名稱。
- app.kubernetes.io/version: 版本名稱。
- iter8-tools/track:要用于此版本的曲目標簽。
- iter8-tools/abn: 指示版本是否準備好接收流量的標志。
作為說明,可以使用以下命令手動部署示例應用程序。首先,部署前端在線商店組件:
接下來,部署示例后端推薦組件的當前或默認版本。我們將所需的標簽添加到部署對象中,因為我們希望在此組件上運行 A/B/n 測試。
最后,部署 Iter8 服務(如果尚未部署):
運行 A/B/n 測試
我們現在準備運行 A/B 測試,比較后端推薦組件的當前部署的默認版本和新的候選版本。運行測試有兩個步驟。第一步是部署組件的一個或多個候選版本。使用我們的示例應用程序,我們展示了部署后端推薦引擎的候選版本所需的步驟。待候選版本完全部署后,Iter8 Service會開始將分配給它的track label發送給前端服務。作為響應,前端商店將開始向新版本的推薦引擎發送請求。第二步是啟動 Iter8 實驗來評估收集到的指標。我們展示了一個多循環實驗——一個定期執行直到被刪除的實驗。在每次執行時,
部署候選版本
可以以任何方式部署候選版本——手動(如我們所示)或使用 CI 工作流。如上所述,必須將所需標簽添加到至少一個 Kubernetes 資源對象。
在我們的示例應用程序中部署后端推薦服務的候選版本:
在部署候選版本時,必須注意確保候選版本在前端向其發送任何請求之前已完全初始化。這可以通過僅在候選版本完全初始化后設置 iter8-tools/abn 標簽來確保。一旦初始化,Iter8 A/B/n 服務將開始提供響應Lookup()請求的版本。
這些步驟如下圖所示。最初,僅部署默認版本 v1 并接收來自前端的所有流量。
當部署候選版本 v2 時,前端繼續將所有請求發送到默認版本。
一旦候選版本準備好接收流量,例如,當 pod 為 時Ready,設置標簽iter8.tools/abn。這會觸發 Iter8 服務開始向前端推薦它,而前端又開始向兩個版本發送請求。在我們的示例應用程序中:kubectl label deployment backend-candidate iter8.tools/abn=true
實際上,測試取決于應用到前端服務的用戶負載。在本教程中,我們使用將請求發送到存儲端點的腳本來應用負載,/getRecommendation并/buy.使用將本地請求轉發到集群:kubectl port-forward svc/frontend 8090:8090
并為不同的用戶生成負載;例如,對于用戶foo和foobar:
啟動 Iter8 實驗
啟動 Iter8 實驗以定期讀取通過 編寫的業務指標WriteMetric()。可以使用預定義的 abnmetrics 任務:
此命令啟動 Iter8 實驗,該實驗運行預定義的 abnmetrics 任務以讀取在默認命名空間中運行的后端應用程序組件的記錄指標。使用 cronjob runner 表示實驗將根據 cronjobSchedule 定期運行(在本例中為每分鐘一次)。實驗結果將隨時間更新。
檢查實驗結果并決定是否推廣候選版本。第一份報告將在實驗任務第一次運行后(大約一分鐘)可用。示例報告如下:
提升贏家
在推廣候選版本時,必須注意確保沒有用戶流量意外發送到正在升級或刪除的版本。任何可用于執行促銷的方法都應包括以下步驟。還顯示了示例應用程序的手動步驟。
最初,默認版本和候選版本都從前端接收請求。
首先,iter8.tools/abn從與默認版本關聯的資源中取消設置標簽。這會在轉換期間禁用到默認版本的流量——Iter8 SDK 接口Lookup()將從其推薦后端列表中刪除默認軌道:
接下來,使用新版本重新部署與默認軌道關聯的對象。
更新的對象準備就緒后,添加iter8.tools/abn指示它已準備好接收流量的標簽。
此時,默認和候選軌道標簽都與相同的后端版本相關聯。現在可以刪除候選版本。為此,取消設置iter8.tools/abn標簽以終止到候選資源的流量:
最后,刪除候選資源。
最后的想法
我們探討了進行 A/B/n 測試的一些挑戰,尤其是應用程序的后端服務。關鍵挑戰涉及前端組件計算業務指標無法正確地將它們與有助于其計算的后端版本相關聯。Iter8 SDK 使前端能夠正確地建立這種關聯。它通過提供一個查找接口來實現這一點,該接口允許前端服務識別后端服務的版本以在處理用戶請求時使用。這樣,它可以可靠地將業務指標分配給后端版本。我們展示了使用 Iter8 SDK 修改前端服務和運行 A/B/n 測試是多么容易。
只需要幾行額外的代碼就可以對前端進行一次性更改。啟用候選版本進行測試只需要添加一些標簽。
試用本教程后,使用您自己的應用程序進行試用。