本篇文章給大家?guī)砹岁P(guān)于前端的相關(guān)知識,其中主要跟大家分享一個簡單的前端灰度系統(tǒng),并且介紹這個系統(tǒng)怎么寫的?感興趣的朋友下面一起來看一下吧,希望對大家有幫助。
(資料圖)
寫在前面的話
灰度這個概念,來自數(shù)字圖像領(lǐng)域,最初是描述黑白數(shù)字圖像的灰度值,范圍從 0到 255,0表示黑色,255表示白色,中間的數(shù)值表示不同程度的灰色。
灰度系統(tǒng)的誕生源于交叉學科的建設(shè),在互聯(lián)網(wǎng)上也不例外。對于一個軟件產(chǎn)品,在開發(fā)和發(fā)布的時候肯定希望用戶能夠順利的看到想讓其看到的內(nèi)容。但是,發(fā)布沒有一帆風順的,如果在發(fā)布的某個環(huán)節(jié)出了問題,比如打錯了鏡像或者由于部署環(huán)境不同觸發(fā)了隱藏的bug,導致用戶看到了錯誤的頁面或者舊的頁面,這就出現(xiàn)了生產(chǎn)事故。為了避免這種情況出現(xiàn),借鑒數(shù)字圖像處理的理念,設(shè)計師們設(shè)計出了一種介于 0和 1之間的過渡系統(tǒng)的概念:讓系統(tǒng)可以預先發(fā)布,并設(shè)置可見范圍,就像朋友圈一樣,等到風險可控后,再對公眾可見。這就是灰度系統(tǒng)。
灰度系統(tǒng)版本的發(fā)布動作稱作 灰度發(fā)布,又名金絲雀發(fā)布,或者灰度測試,他是指在黑與白之間能夠平滑過渡的一種發(fā)布方式。在其上可以進行A/B testing,即讓一部分用戶繼續(xù)用產(chǎn)品特性A,一部分用戶開始用產(chǎn)品特性B,如果用戶對B沒有什么反對意見,那么逐步擴大范圍,把所有用戶都遷移到B上面來。(概念來自知乎)
對于前端領(lǐng)域,演進到現(xiàn)在,灰度系統(tǒng)主要有如下幾點功能:
增量灰度:小的patch可以增量的添加在發(fā)布版本上,也可以通過開關(guān)一鍵關(guān)閉用戶灰度:增量和全量版本都可對不同群體或者某幾個特定的用戶進行灰度可見版本回退:每一個版本都在灰度系統(tǒng)里可見,可以一鍵回退前端灰度系統(tǒng)工作流程圖如下:
sequenceDiagram前端項目-->灰度系統(tǒng): 部署階段前端項目->>灰度系統(tǒng): 1.CI 寫入打包資源前端項目->>灰度系統(tǒng): 2.CI 打包完成后更新資源狀態(tài)前端項目-->灰度系統(tǒng): 訪問階段前端項目->>灰度系統(tǒng): 1.頁面訪問,請求當前登錄用戶對應(yīng)的資源版本灰度系統(tǒng)-->>前端項目: 2.從對應(yīng)版本的資源目錄返回前端資源
關(guān)于灰度資源優(yōu)先級的說明如下:
| 灰度策略 | 優(yōu)先級 |
|---|---|
| 未生效 | 低 |
| 生效 | 高 |
| 全量 | 一般 |
如此就起到了灰度的作用:全量表示所有人都可以看;生效表示只有在規(guī)則中的用戶才可以看到這部分增量更新,優(yōu)先級最高;未生效表示不灰度,優(yōu)先級最低。
先介紹一個要部署的前端項目(你可以根據(jù)自己的前端項目動態(tài)調(diào)整)。
本項目針對的前端項目是一個基于微服務(wù)架構(gòu)的項目,
下面是設(shè)計ER圖:
我們依此來分析:
該表用于存放所有子項目的信息,新建一個微服務(wù)子項目時,會在這個表里新建一個條目,數(shù)據(jù)示意如下:
用于灰度系統(tǒng)登錄的用戶,擁有灰度權(quán)限的人才可以加入。
資源表存放項目在 CI 中寫入的 commit 信息和 build 完以后在服務(wù)器的存放位置,數(shù)據(jù)示意如下:
其中 branch是跑CI的分支,data存放打包資源目錄信息,一般結(jié)構(gòu)如下:
gitProjectId存放該產(chǎn)品在 gitlab 中的項目號, status表示構(gòu)建狀態(tài):0:構(gòu)建完成 1:部署完成 2:構(gòu)建失敗,3:部署失敗。
這里簡單提一下 CI 是如何寫入灰度系統(tǒng)數(shù)據(jù)庫的,過多詳情不做解釋,寫入數(shù)據(jù)庫方式很多,這只是其中一種實現(xiàn)方式。
首先在 CI build 環(huán)節(jié)往服務(wù)器寫入打包信息的 JSON:其中 build.sh 負責把傳入的參數(shù)寫到一個 json 中。
在 CI 部署環(huán)節(jié),通過調(diào)用腳本創(chuàng)建資源:其中 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 部署服務(wù)器完成后,追加一個 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灰度策略是對灰度資源的調(diào)動配置。其設(shè)計如下:
其中,prijectId表示灰度的項目,resourceId表示使用的資源,rules配置了對應(yīng)的用戶或用戶組(看你怎么配置了,我這里只配置了單獨的 userId),status是灰度的狀態(tài),我設(shè)置了三種:
狀態(tài)生效表示是增量發(fā)布的意思。
到這里,數(shù)據(jù)庫設(shè)計就完畢了。
有了數(shù)據(jù)庫,還需要提供能夠操作數(shù)據(jù)庫的服務(wù),上邊創(chuàng)建資源的接口就是調(diào)用的灰度自己的API實現(xiàn)的。主要的API列表如下:
| 名稱 | 描述 |
|---|---|
| getResourcesByProjectId | 獲取單個產(chǎn)品下所有資源 |
| getResourcesById | 通過主鍵獲取資源 |
| createResource | 創(chuàng)建一個資源 |
| updateResource | 更新一個資源 |
| getIngressesByProjectId | 獲取單個產(chǎn)品下灰度策略任務(wù)列表 |
| getIngressById | 通過主鍵獲取單個灰度策略任務(wù)詳情 |
| createIngress | 創(chuàng)建一個策略 |
| updateIngress | 更新一個策略 |
剩余的接口有用戶處理的,有子項目管理的,這里不做詳述。除了上邊的必須的接口外,還有一個最重要的接口,那就是獲取當前登錄用戶需要的資源版本的接口。在用戶訪問時,需要首先調(diào)用灰度系統(tǒng)的這個接口來獲取資源地址,然后才能重定向到給該用戶看的頁面中去:
| 名稱 | 描述 | 接收參數(shù) | 輸出 |
|---|---|---|---|
| getConsoleVersion | 獲取當前用的產(chǎn)品版本 | userId,products | resource鍵值對列表 |
getConsoleVersion接受兩個參數(shù),一個是當前登錄的用戶 ID, 一個是當前用戶訪問的微服務(wù)系統(tǒng)中所包含的產(chǎn)品列表。該接口做了如下幾步操作:
其中第三步處理相對繁瑣一些,比如說,一個資源有兩個起作用的灰度資源,一個是增量的,一個是全量的,這里應(yīng)該拿增量的版本,因為他優(yōu)先級更高。
獲取用戶版本的流程圖如下:
graph TD用戶登錄頁面 --> 獲取所有產(chǎn)品下的資源列表獲取所有產(chǎn)品下的資源列表 --> 根據(jù)灰度策略篩選資源中該用戶可用的部分 --> 返回產(chǎn)品維度的資源對象
最后返回的資源大概長這個樣子:
interface VersionResponse { [productId: number]: ResourceVersion;}interface ResourceVersion { files: string[]; config: ResourceConfig; dependencies: string[];}其中 files 就是 JSON 解析后的上述 data 信息的文件列表,因為打包后的文件往往有 css和多個js。
至于這個后端使用什么語言,什么框架來寫,并不重要,重要的是一定要穩(wěn)定,他要掛掉了,用戶就進不去系統(tǒng)了,容災(zāi)和容錯要做好;如果是個客戶比較多的網(wǎng)站,并發(fā)分流也要考慮進去。
前端頁面就隨便使用了一個前端框架搭了一下,選型不是重點,組件庫能夠滿足要求就行:
登錄查看資源配置策略部署以后,實際運行項目看看效果:
可以看到,在調(diào)用業(yè)務(wù)接口之前,優(yōu)先調(diào)用了 getConsoleVersion來獲取版本,其返回值是以產(chǎn)品為 key 的鍵值對:
這里拿到部署信息后,服務(wù)器要進行下一步處理的。我這里是把它封裝到一個對象中,帶著參數(shù)傳給了微服務(wù)的 hook 去了,可以期待一下后續(xù)的手寫一個前端微服務(wù)的系列文章;如果你是單頁應(yīng)用,可能需要把工作重心放在 Nginx 的轉(zhuǎn)發(fā)上,通過灰度系統(tǒng)告知轉(zhuǎn)發(fā)策略后,Nginx負責來切換路由轉(zhuǎn)發(fā),可能只是改變一個路由變量。(你也可以參照我 nginx 相關(guān)文章),下面我簡單的給個示意圖:
graph TD灰度系統(tǒng)配置灰度策略 --> 告知Nginx資源地址 告知Nginx資源地址 --> Nginx服務(wù)器配置資源轉(zhuǎn)發(fā)
前端灰度系統(tǒng),其實就是一個后臺管理系統(tǒng)。他配置和管理了不同版本的前端部署資源和對應(yīng)的用戶策略,在需要的時候進行配置。
接下來的文章我會配套性的講一下 Nginx和 Docker的前端入門使用,敬請期待!
推薦學習:《web前端開發(fā)》
以上就是分享一個簡單的前端灰度系統(tǒng)的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
關(guān)鍵詞: