分享一個簡單的前端灰度系統

2023-03-20 18:01:03

本篇文章給大家帶來了關於前端的相關知識,其中主要跟大家分享一個簡單的前端灰度系統,並且介紹這個系統怎麼寫的?感興趣的朋友下面一起來看一下吧,希望對大家有幫助。

寫在前面的話

灰度這個概念,來自數位影像領域,最初是描述黑白數位影像的灰度值,範圍從 02550 表示黑色,255 表示白色,中間的數值表示不同程度的灰色。

灰度系統的誕生源於交叉學科的建設,在網際網路上也不例外。對於一個軟體產品,在開發和釋出的時候肯定希望使用者能夠順利的看到想讓其看到的內容。但是,釋出沒有一帆風順的,如果在釋出的某個環節出了問題,比如打錯了映象或者由於部署環境不同觸發了隱藏的bug,導致使用者看到了錯誤的頁面或者舊的頁面,這就出現了生產事故。為了避免這種情況出現,借鑑數位影像處理的理念,設計師們設計出了一種介於 01 之間的過渡系統的概念:讓系統可以預先發布,並設定可見範圍,就像朋友圈一樣,等到風險可控後,再對公眾可見。這就是灰度系統。

灰度系統版本的釋出動作稱作 灰度釋出,又名金絲雀釋出,或者灰度測試,他是指在黑與白之間能夠平滑過渡的一種釋出方式。在其上可以進行A/B testing,即讓一部分使用者繼續用產品特性A,一部分使用者開始用產品特性B,如果使用者對B沒有什麼反對意見,那麼逐步擴大範圍,把所有使用者都遷移到B上面來。(概念來自知乎)

對於前端領域,演進到現在,灰度系統主要有如下幾點功能:

  1. 增量灰度:小的patch可以增量的新增在釋出版本上,也可以通過開關一鍵關閉
  2. 使用者灰度:增量和全量版本都可對不同群體或者某幾個特定的使用者進行灰度可見
  3. 版本回退:每一個版本都在灰度系統裡可見,可以一鍵回退

前端灰度系統工作流程圖如下:

sequenceDiagram
前端專案-->灰度系統: 部署階段
前端專案->>灰度系統: 1.CI 寫入打包資源
前端專案->>灰度系統: 2.CI 打包完成後更新資源狀態
前端專案-->灰度系統: 存取階段
前端專案->>灰度系統: 1.頁面存取,請求當前登入使用者對應的資源版本
灰度系統-->>前端專案: 2.從對應版本的資源目錄返回前端資源
登入後複製

灰度規則

關於灰度資源優先順序的說明如下:

灰度策略優先順序
未生效
生效
全量一般

如此就起到了灰度的作用:全量表示所有人都可以看;生效表示只有在規則中的使用者才可以看到這部分增量更新,優先順序最高;未生效表示不灰度,優先順序最低。

灰度系統資料庫設計

為什麼灰度系統有後端:前端專案 CI 部署後,會產生一個 commit 號和一個映象記錄,並且打包後的檔案存放在伺服器中某一個深層的資料夾目錄中,灰度系統需要存入該部署的目錄地址,便於在切換灰度時查詢不同版本的檔案。

先介紹一個要部署的前端專案(你可以根據自己的前端專案動態調整)。

本專案針對的前端專案是一個基於微服務架構的專案,

下面是設計ER圖:

image.png

我們依此來分析:

子專案表

該表用於存放所有子專案的資訊,新建一個微服務子專案時,會在這個表裡新建一個條目,資料示意如下:

image.png

灰度使用者表

用於灰度系統登入的使用者,擁有灰度許可權的人才可以加入。

資源表

資源表存放專案在 CI 中寫入的 commit 資訊和 build 完以後在伺服器的存放位置,資料示意如下:

image.png

其中 branch 是跑CI的分支,data 存放打包資源目錄資訊,一般結構如下:

image.png

gitProjectId 存放該產品在 gitlab 中的專案號, status 表示構建狀態:0:構建完成 1:部署完成 2:構建失敗,3:部署失敗。

這裡簡單提一下 CI 是如何寫入灰度系統資料庫的,過多詳情不做解釋,寫入資料庫方式很多,這只是其中一種實現方式。

  1. 首先在 CI build 環節往伺服器寫入打包資訊的 JSON:

image.png

其中 build.sh 負責把傳入的引數寫到一個 json 中。

  1. 在 CI 部署環節,通過呼叫指令碼建立資源:

image.png

其中 run_gray.js:

const { ENV, file, branch, projectId, gitProjectId, user, commitMsg } = require('yargs').argv;

axios({
    url: URL,
    method: "POST",
    headers: {
        remoteUser: user
    },
    data: {
        Action: "CreateResource",
        projectId,
        branch,
        commitMsg,
        gitProjectId,
        channel: Channel,
        data: fs.readFileSync(file, 'utf8'),
        status: "0"
    }
}).then(...)
登入後複製

其中 status 的變化,在 CI 部署伺服器完成後,追加一個 UpdateResource 動作即可:

if [[ $RetCode != 0 ]]; then curl "$STARK_URL" -X 'POST' -H 'remoteUser: '"$GITLAB_USER_NAME"'' -H 'Content-Type: application/json' -d '{"Action": "UpdateResource", "id": "'"$ResourceId"'", "status": "2"}' > test.log && echo `cat test.log`; fi
登入後複製

灰度策略表

灰度策略是對灰度資源的調動設定。其設計如下:

image.png

其中,prijectId 表示灰度的專案,resourceId 表示使用的資源,rules 設定了對應的使用者或使用者組(看你怎麼設定了,我這裡只設定了單獨的 userId),status 是灰度的狀態,我設定了三種:

  • default: 未生效
  • failure: 生效
  • success: 全量

狀態生效表示是增量釋出的意思。

到這裡,資料庫設計就完畢了。


灰度系統介面API開發

有了資料庫,還需要提供能夠運算元據庫的服務,上邊建立資源的介面就是呼叫的灰度自己的API實現的。主要的API列表如下:

名稱描述
getResourcesByProjectId獲取單個產品下所有資源
getResourcesById通過主鍵獲取資源
createResource建立一個資源
updateResource更新一個資源
getIngressesByProjectId獲取單個產品下灰度策略任務列表
getIngressById通過主鍵獲取單個灰度策略任務詳情
createIngress建立一個策略
updateIngress更新一個策略

剩餘的介面有使用者處理的,有子專案管理的,這裡不做詳述。除了上邊的必須的介面外,還有一個最重要的介面,那就是獲取當前登入使用者需要的資源版本的介面。在使用者存取時,需要首先呼叫灰度系統的這個介面來獲取資源地址,然後才能重定向到給該使用者看的頁面中去:

名稱描述接收引數輸出
getConsoleVersion獲取當前用的產品版本userId,productsresource鍵值對列表

getConsoleVersion 接受兩個引數,一個是當前登入的使用者 ID, 一個是當前使用者存取的微服務系統中所包含的產品列表。該介面做了如下幾步操作:

  1. 遍歷 products,獲取每一個產品的 projectId
  2. 對於每一個 projectId,聯查資源表,分別獲取對應的 resourceId
  3. 對於每一個resourceId,結合 userId,並聯查灰度策略表,篩選出起作用的灰度策略中可用的資源
  4. 返回每一個資源的 data 資訊。

其中第三步處理相對繁瑣一些,比如說,一個資源有兩個起作用的灰度資源,一個是增量的,一個是全量的,這裡應該拿增量的版本,因為他優先順序更高。

獲取使用者版本的流程圖如下:

graph TD
使用者登入頁面 --> 獲取所有產品下的資源列表
獲取所有產品下的資源列表 --> 根據灰度策略篩選資源中該使用者可用的部分 --> 返回產品維度的資源物件
登入後複製

最後返回的資源大概長這個樣子:

interface VersionResponse {
    [productId: number]: ResourceVersion;
}

interface ResourceVersion {
    files: string[];
    config: ResourceConfig;
    dependencies: string[];
}
登入後複製

其中 files 就是 JSON 解析後的上述 data 資訊的檔案列表,因為打包後的檔案往往有 css和多個js。

至於這個後端使用什麼語言,什麼框架來寫,並不重要,重要的是一定要穩定,他要掛掉了,使用者就進不去系統了,容災和容錯要做好;如果是個客戶比較多的網站,並行分流也要考慮進去。

前端頁面展示

前端頁面就隨便使用了一個前端框架搭了一下,選型不是重點,元件庫能夠滿足要求就行:

  • 登入

image.png

  • 檢視資源

image.png

  • 設定策略

image.png

image.png


部署以後,實際執行專案看看效果:

image.png

可以看到,在呼叫業務介面之前,優先呼叫了 getConsoleVersion來獲取版本,其返回值是以產品為 key 的鍵值對:

image.png

存取轉發

這裡拿到部署資訊後,伺服器要進行下一步處理的。我這裡是把它封裝到一個物件中,帶著引數傳給了微服務的 hook 去了,可以期待一下後續的手寫一個前端微服務的系列文章;如果你是單頁應用,可能需要把工作重心放在 Nginx 的轉發上,通過灰度系統告知轉發策略後,Nginx負責來切換路由轉發,可能只是改變一個路由變數。 (你也可以參照我 ),下面我簡單的給個示意圖:

graph TD
灰度系統設定灰度策略 --> 告知Nginx資源地址 
告知Nginx資源地址 --> Nginx伺服器設定資源轉發
登入後複製

總結

前端灰度系統,其實就是一個後臺管理系統。他設定和管理了不同版本的前端部署資源和對應的使用者策略,在需要的時候進行設定。

接下來的文章我會配套性的講一下 NginxDocker 的前端入門使用,敬請期待!

推薦學習:《》

以上就是分享一個簡單的前端灰度系統的詳細內容,更多請關注TW511.COM其它相關文章!