摘要:基于的前端灰度發布方案灰度發布和測試簡介灰度發布將某個功能灰度發布逐漸放量給特定線上人群,避免新功能全量上線帶來的風險。如果我們把這些版本信息管理起來,并且通過特定的手段對用戶請求應用測試就可以完成前端不同版本的灰度發布。
基于Nodejs的前端灰度發布方案 1. 灰度發布和A/B測試簡介 灰度發布
將某個功能灰度發布(逐漸放量)給特定線上人群,避免新功能全量上線帶來的風險。
上面的圖可以通過兩個方面來理解:
藍色實線和藍色虛線訪問Nginx服務器,nginx通過負載均衡將流量分攤到后端服務器。
黃色的線是應用了灰度的流量(配置Nginx規則)可以將特定流量分發到特定的機房,以達到對特定用戶應用產品新功能;
舉個簡單的例子:將http請求cookie中含有test=1字段的請求都轉發到灰度代碼的機房;
上面通過通過配置特定Nginx規則的方法來達到產品灰度的方法雖然可以滿足一定業務量的需求,但是他也有很多的缺點:
不靈活,每次上線新業務代碼需要做灰度都要重新更新nginx規則,造成開發和運維負擔;
上線的代碼要做機房區分,不能夠將代碼全量。本地的Git代碼也要區分開發分支和測試分支,線上分支等若干分支,管理起開麻煩;
不能滿足業務量大或者業務需要頻繁迭代,需要頻繁做測試的業務;
那么有沒有更好的方法來做灰度發布呢?當然是有的,A/B測試就能夠彌補上面通過Nginx規則來做灰度的缺點。
A/B測試將線上一部分真實人群流量隨機拆分成多個組,對每個分組的人群應用不同策略或功能,通過計算每組人群的業務指標(轉化率、成交率等)來衡量策略或功能的實際效果。
我們通過下面的這張圖簡單的了解下A/B測試的原理:
由上圖我們可以知道A/B和傳統的灰度方法的區別:
傳統的灰度是通過Nginx分發流量到服務器,A/B測試是通過業務代碼區分流量訪問不同的代碼塊。
那么A/B測試的優缺點是什么呢?
優點:
隨著業務的變化不用頻繁的變化Nginx規則,不用分機房上線業務代碼,本地git分支不用為了做灰度而建專門的分支;
流量區分是業務代碼做的。所以上線代碼的時候可以全量上線到所有機房;
缺點:
因為流量區分是業務代碼做的。所以在代碼中會存在很多的if...else分支語句。但是這樣還好,因為根據SDK的規范來書寫代碼,還是很好管理的。
2. 基于A/B測試的前端灰度怎么做前端跟后端很大的區別就是直接面對用戶,就算很簡單的修改一次按鈕的顏色就需要一次上線。這種操作對用戶是可感知的。
現代前端有個特點就是脫離了后端模板引擎的渲染,大多數是使用React、Vue這種MVVM框架的前端(瀏覽器)渲染。這種情況下后端其實僅僅是給用戶提供一個空的html文件(工作中經常稱作為殼)。大多數業務代碼開發完以后都是作為靜態文件上線到服務器,經過用戶訪問后緩存到CDN節點上的。而且這個過程大多數是增量上線的。
其實我們每次上線完之后服務器上緩存的html文件就包含不同的版本信息。如果我們把這些版本信息管理起來,并且通過特定的手段(對用戶請求應用A/B測試)就可以完成前端不同版本的灰度發布。
使用Nodejs靈活控制前端發布我們可以觀察下Webpack或者是其它打包工具打包后的html文件。每次外聯的靜態文件都包含不同的hash戳。這些外鏈的文件又都是增量緩存到服務其上的。
index.html (我們頁面的“殼”)
一些 xxx.js文件 (渲染頁面+頁面的業務邏輯)
xxx.css 文件 (控制頁面顯示樣式)
大概就是下面的這個樣子
基于以上的特點,我們能不能盡量減少對業務代碼侵入,而可以覆蓋業務改動較大的需求進行灰度或者是A/B測試呢?
看下下面的這個這個請求的圖:
每次我們打包編譯完之后,就將相關的css文件和js文件信息保存到本地的一個json文件中。這些信息的key可以是我們的git的tag信息(主要來描述本次發版信息包含的功能等)。
基本上json文件包含的信息如下:
const version = { // 可以描述本次的上線內容/ 或者是git tag "tag1": { "css": "xxxxxxx.css", "app": "app_xxx.js", "ventor": "ver_xxx.js" } }
這里僅僅是一個簡單的demo示例,可以使用Nodejs寫文件的特性直接將文件版本號寫入到index.html返回給前端瀏覽器
Nodejs服務的特點是每次更新完代碼需要重啟之后才能生效。每次上完線重啟服務就會先檢查本地代碼根目錄下的這個json文件。看下這個其中包含的tag是否在DB中存儲,如果有存儲就不做操作,如果沒有就將它存儲DB做持久化。
上面圖上面的Apollo就是用來配置那些用戶訪問新功能的平臺。在Nodejs端,每次接收到用戶請求的時候都會判斷用戶的信息是否滿足相關條件,然后從DB中讀取相關靜態文件信息渲染到index.html中去。
簡單總結下:將每次打包的靜態文件信息先存儲下來,之后請求到達Nodejs的時候判斷用戶是否滿足相關條件,如果滿足就讀取DB將相關的靜態文件信息返回給Nodejs,Nodejs將靜態頁渲染好之后返回給用戶,達到灰度的目的。
3.其它細節問題使用Nodejs之前我們的頁面就是直接部署在服務其上,這次使用了Nodejs后,會有很多其它的問題需要做,比如說Nodejs服務的監控,多機房部署等。這些在大部分的公司應該都有相關的運維工程師來做。我這里簡單介紹一些其它的內容
規范的確定這里的規范包括本地開發時工程目錄的規范和線上用戶訪問url的規范。
開發目錄規范
在筆者寫這篇文章的時候最新的Nodejs版本已經是 11.10版本了,最新的LTS版本是10.15.1版本。建議使用Nodejs的同學都升級自己的Node到8.0版本以上,因為8.0版本是一個官方原生支持async...await語句的版本。
.
├── client // 放置客戶端的代碼
├── index.html
├── index.js
├── node_modules
├── output
├── package-lock.json
├── package.json
├── server // 放置服務端Nodejs代碼
├── test.sh
需要注意的就是在編寫webpack打包工具的時候將server目錄下的給排除掉。放置不必要的編譯和產出,增加打包速度。
線上url的約定
當使用了新的服務的時候為了防止跟舊業務的沖突肯定需要使用新的url。這個時候就需要做一些約定。目前我們是這么約定的
// 域名/產品線/模塊/ http://wwww.aaa.com/driver/bus/index.html // 域名/產品線/模塊/靜態文件目錄 http://wwww.aaa.com/driver/bus/static/js/index.js http://wwww.aaa.com/driver/bus/static/css/index.html兼容老業務需要做的工作
前面提到這次業務升級我們使用了新的url,但是為了保證業務的穩定性我們不是一次性將所有的流量都切到新服務上去的。我們也是通過批量的切的,所以會存在線上用戶有的地區訪問新服務有地區訪問舊服務。那么有一天會有全部切換的一天,但是還是會有一些用戶訪問到舊鏈接,這個時候可以通過配置Nginx 的`rewrite來講舊鏈接都轉成新的鏈接。
升級后的業務怎么訪問新的連接
已經請求相關的配置
避免不必要的請求前端路由可以分為兩種方式,hash和path切換。因為對于前端渲染頁面來說,當第一次請求完成后,其實所有的頁面都已經下載到了本地(頁面異步加載除外)。在我們通過path切換頁面的時候,每次都會向服務端發送請求,其實這些請求是不需要到達Nodejs服務的。我們可以通過Nginx配置將這些無用的流量抵擋在Nginx這一層,減少服務器的壓力。
如果是使用hash的方式則不存在這樣的問題,但是會有另外的問題就是對搜索引擎不友好。當然前端路由切換還是應該根據自己的業務做取舍。
4. 前端業務拓展當我們應用了Nodejs服務之后,可以拓展的技術點有哪些,一下簡單列舉一些:
服務端渲染:提高首屏渲染時間,提升用戶體驗。
前端接口校驗:增加前端訪問后端接口,后端接口返回數據的安全性。
前后端分離,前端工程師的靈活性更加的高。
5. 技術升級帶來的收益前端上線可以實現小流量、灰度、發布,可以對線上流量做A/B測試,減少線上問題;
可以定制化對部分用戶推動新功能;
加快首屏的渲染時間,提升用戶體驗;
多機房部署前端代碼,降低前端服務不可用的風險;
團隊成員技術能力的提升;
6. 最后當然這種方案也不僅僅是可以使用Nodejs來做,也可以使用其它語言。因為我們公司已經有基于A/B測試的Nodejs-SDK。我這我就不具體介紹原理了。原理可以參考百度百科。如果有問題需要一起討論可以留言或者是郵箱聯系我:hpuhouzhiqiang@gmail.com
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102218.html
摘要:有贊容器化方案我們的容器化方案基于和,下面介紹一下我們在各個方面遇到的問題以及解決方案。不過對于上線來說,需要整個運維體系來適配容器化,比如監控發布日志等等。 前言 容器化已經成為一種趨勢,它可以解決很多運維中的痛點,比如效率、成本、穩定性等問題,而接入容器的過程中往往也會碰到很多問題和不便。在有贊最開始做容器化是為了快速交付開發測試環境,在容器化的過程中,我們碰到過容器技術、運維體系...
摘要:為指定事件注冊一個單次監聽器,即監聽器最多只會觸發一次,觸發后立刻解除該監聽器。移除指定事件的某個監聽器,監聽器必須是該事件已經注冊過的監聽器。返回指定事件的監聽器數組。如何創建空對象我們已經了解到,是要來儲存監聽事件監聽器數組的。 毫無疑問,nodeJS改變了整個前端開發生態。本文通過分析nodeJS當中events模塊源碼,由淺入深,動手實現了屬于自己的ES6事件觀察者系統。千萬不...
閱讀 738·2021-10-09 09:44
閱讀 2005·2021-09-22 15:54
閱讀 5043·2021-09-22 10:55
閱讀 1435·2019-08-29 18:41
閱讀 771·2019-08-29 11:24
閱讀 2099·2019-08-28 18:20
閱讀 1025·2019-08-26 11:51
閱讀 3044·2019-08-26 11:00