abtest-system後臺系統設計與搭建

weixin_34185560發表於2018-09-07

本文來自網易雲社群

作者:劉頌

1 專案背景:

     2017年5月:客戶端提出增加https&dns以及雙cdn業務功能 後臺配合實現使用disconf配置 針對不同的域名或者請求配置不同的https等資訊

     2017年7月:考拉上線了工廠店,工廠店產品要求 上線一定時間內 內網灰度 外網不可見 之後某個特定時間 全網開啟工廠店  包括首頁 搜尋 品牌等各個業務模組為了實現這個簡單的灰度要求 app 搜尋 主站 分別基於disconf實現了多套灰度  一方面程式碼冗餘嚴重 一方面進行整體操作需要協調多方開發測試進行 徒增風險

     2017年8月:隨著app 3.8版本開發的開始 多個產品要求針對新增產品進行新老功能的AB實驗,如果效果可觀會全面開啟新功能 基於此,我們覺得有必要將abtest進行統一的設計和服務的提供 在進行技術評審之後 偶然發現有類似功能需求的開發組並不少:



我們希望提供的一個abtest-system需要解決以下問題:

         1 產品針對不同場景進行ABTest,從而根據使用者行為選擇更好的設計方向

           2 針對一些上線需要先內測 後公測的功能提供統一的灰度服務

         3 對於前端或其他呼叫方需要進行灰度個性化的支援

2 灰度框架的架構:

1 架構設計上將abtest-system分為了兩個工程:

     提供後臺資料儲存以及快取功能的abtest-generic工程

2 兩個工程分工不同 做到功能解耦和

     提供前臺灰度邏輯計算的abtest-compose工程

3 工作流同樣分為兩個:

      在將資料儲存到資料庫的同時 abtest-generic新增增量重新整理快取 將快取儲存在solo裡

      後臺通過接入許可權控制系統的mobilems-front提供的前臺服務 進行結果 條件 資源的增刪改查操作

      通過kschedule平臺每天進行全量的資料同步操作

      如果發現呼叫的快取資料不存在 那麼會呼叫資料庫進行資料同步操作

      前臺請求過來 通過abtest-compose獲取請求資訊 呼叫abtest-generic提供的灰度資訊介面進行灰度邏輯運算

      進行灰度計算發現出現異常行為 通過哨兵進行報警

3 灰度使用方式和定義:  

   1 工程間通過dubbo介面呼叫 是否灰度 對客戶端透明

   2 灰度工程概念定義  key ---1:n --->  灰度結果  --- 1:n ---> 灰度條件  --- 1:n ---> 灰度配置

        2.1 key :呼叫方定義,定義好後 在灰度工程中配置 不同key應用地方不同 例如https mam 雙cdn等 需要不同key

        2.3 灰度條件 : 和灰度結果為一對多關係 一個灰度結果可以有多個灰度條件 如果滿足其中任意一個灰度條件 即為認定屬於灰度訪問 返回灰

        2.2 灰度結果 : 和key為一對多關係 一個key可以有多個灰度結果 如果滿足灰度條件 會將多個灰度結果去重返回的結果   

   3 使用方式:

        3.1 呼叫方定義key 並且在呼叫程式碼中通過對指定key的返回值進行業務邏輯處理

        3.2 呼叫方在灰度後臺配置一個或多個灰度配置 使用者判斷請求資料是否完全滿足配置條件

        3.3 呼叫方在灰度後臺配置一個或多個灰度條件 用於判斷請求是否屬於灰度訪問 每個灰度條件繫結多個灰度配置 

        3.4 呼叫方在灰度後臺配置一個或多個同名key的灰度結果 返回撥用方需要的資料格式 每個灰度結果繫結多個灰度條件

   4 可以建立一些常用的資源配置 例如灰度ip等

   6 後臺配置關係:

   5 灰度結果 資源配置為彈窗形式  灰度條件為頁面

4 灰度工程提供出去的方法:

   1 根據請求key獲取返回結果資訊

            //key: 呼叫方定義key

            //requestGrayParam:呼叫方請求灰度工程入參

            //返回值body中含有json 需要呼叫方進一步解析

        Response<body> getABTestResult(String key, RequestABTestParam requestABTestParam, ABTestDefaultStrService abTestDefaultStrService);

    2 根據請求key返回是否為灰度請求

            //key: 呼叫方定義key

            //requestGrayParam:呼叫方請求灰度工程入參

        Boolean isGrayTestIp(String ip) ;

        Boolean isABTestRequest(String key, RequestABTestParam requestABTestParam, ABTestDefaultBoolService abTestDefaultBoolService);

    3 返回請求ip是否為灰度ip

            //ip : 呼叫方ip

5 工程實現遇到的問題:

 5.1 如何保證高併發情況下快速響應:

    高併發下的快速響應 主要通過solo快取方式解決,其中的快取設計經過三次改版最後形成與後臺操作一一對應的方式實現:

          1  結果key<--> 結果key內部儲存資訊 + 結果繫結條件資訊

          2 條件key<--> 條件key內部儲存資訊 + 條件繫結資源資訊

          3 資源key<--> 資源key內部儲存資訊

通過這三種層次的資料快取儲存 在abtest-compose進行訪問的時候入參為結果key 返回值是該結果key所對應的所有條件和條件所對應的所有資源。

          在後臺進行資料庫變更的時候 只需要將相對應的資料同步到快取即可

          在整個快取的同步和獲取的操作中 如果出現異常情況 會進行報警並且手動同步操作

  快取資料流程圖:

5.2 如何做到優雅的工程降級:

       abtest工程在建立之初就被定義為可降級工程,那麼如何做到可以優雅降級呢?

       首先 可降級工程代表著工程的降級不會對業務造成不可預料的結果 或者工程的降級 不會導致考拉主業務的阻塞 那麼abtest-system的降級就不能對呼叫方返回統一的預設值 因為不同的呼叫方對於灰度走A還是走B或者走C都存在不同的業務邏輯處理 如果大促期間的灰度統一返回撥用方走A 那麼可能對於其中的某些業務對使用者的展現並不是產品所期望的。所以對於abtest工程來說 優雅的降級就是abtest不提供任何服務 呼叫方還可以獲取到期望返回值 我這裡使用了Dubbo的Stub和SOA系統配合實現該功能 首先 在提供出去的介面中 採用Stub的方式實現提供介面,在後面增加入參的引數為一個預設介面,呼叫方需要實現該介面進行邏輯操作 可以進行簡單計算 也可以直接返回預設值 該介面主要的用於大促降級之後的本地運算 如下圖程式碼:

如程式碼所示 對正常的業務邏輯進行了try--cache操作,正常情況下可以正常返回abtest灰度計算結果 異常情況下 就會走業務方預設值了

那麼問題來了 如何保證abtest系統降級之後 業務方並不是通過訪問超時等方式獲取異常?

     答案就是通過SOA動態配置中的降級配置 強制丟擲異常實現,這樣當請求走到ZooKeeper的時候 請求不會呼叫到abtest工程 而是直接返回異常給呼叫方 呼叫方捕獲異常進行預設值計算和返回  因為我們知道當工程降級之後 希望做的就是沒有任何請求打到工程上 才能稱得上是真正的降級,那麼abtest如何做到這點?

如下圖所示:

6 現有不足和後續優化:

    現有不足:

         1 產品 運營接入成本較高 一方面後臺需要配置資源 條件 結果才能生效 一方面沒有做成跳轉性質的接入方式 後續準備改成在一個頁面全部進行配置

         2 灰度目前只提供根據udid進行百分比計算 後面需要增加根據accountId 隨機以及根據業務方傳入值進行隨機等

         3 灰度結束目前還需要業務方自行配置開關 後面準備增加優雅的灰度結束開關 通過abtest後臺系統 一鍵結束灰度

         4 灰度上線後沒有明確的資料或者檢視表明灰度生效結果,接下來準備深入接入哨兵 提供檢視功能可以動態看到灰度效果

整體的二期計劃如下圖所示:



網易雲大禮包:https://www.163yun.com/gift

原文:abtest-system後臺系統設計與搭建,經作者劉頌授權釋出


相關文章:
【推薦】 網易雲釋出雲端計算全棧一體機,私有云迎來“航母模式”

相關文章