vivo 商城前端架構升級—前後端分離篇

網友小鐘發表於2020-10-29

本文主要以 vivo 商城專案的前後端分離經驗,總結前後端分離思路,整理前後端分離方案,以及分離過程中遇到的問題及解決方案。

一、前言

vivo官方商城在2015年建立網上商城,開闢網路銷售渠道,幾年來日活和銷售額持續增長,極大的助力了vivo手機的銷量。

而隨著業務版本迭代越來越快,業務內容逐漸增多,前後端不分離模式的弊端也逐漸顯露出來,迭代效率無法跟上逐步增長的業務需求,多端擴充套件成本高。

為此,我們在2019年開始進行商城專案的架構升級,進行前後端分離,前端技術升級,介面規範化,以便應對未來更多的業務挑戰。

二、背景

架構升級,第一步面臨的問題便是前後端分離,前後端不分離的痛點已經無需贅述,既影響開發效率,又影響開發體驗,但商城仍然處於業務高速發展時期,不能因為技術重構而停下業務版本的迭代。

 因此業務版本迭代必須要和前後端分離同時進行,那怎麼才能做到雙線並行,魚和熊掌兼得呢?方案要如何設計?如何應對技術升級帶來的風險和不可控因素呢?

讓我們帶著這些問題來看看vivo商城是如何一步步實現前後端分離。

三、前後端分離

1、基本思路

先分析我們的業務模組,是標準的樹形結構,每個功能模組包含若干子模組,每個子模組又可以包含若干更小的子模組,每個子模組對應的頁面地址頁類似於麵包屑,形成層級包含關係,並且與功能模組的包含層級一一對應,如下圖:

vivo 商城前端架構升級—前後端分離篇

那如果我們能控制某個模組的頁面請求,讓它返回分離之後的新頁面,別的請求還訪問老頁面,豈不是就能逐個功能模組進行分離?嗯,理論上是可行的。

比如以訂單模組為例,我們可以攔截訂單相關頁面的請求,使得訂單頁面的請求訪問新的資源,其他頁面請求還訪問老的資源,如下圖:

 

2、逐步分離方案

那麼問題來了,如何實現按訪問路徑去請求不同資源?商城目前的頁面請求和介面請求都是透過 Nginx來做統一的門戶入口,我們能否透過Nginx區分頁面請求路徑,從而達到路由控制的目的?

透過學習研究Nginx配置,發現 Nginx路由匹配有這樣一條特性:

location 匹配首先檢查使用字首字元定義的 location,選擇最長匹配的項並記錄下來,如果沒有匹配的正則 location 和精確匹配的 location,則使用前面記錄的最長匹配字首字元 location。

這條資訊非常重要,Nginx 的 location 匹配會採用最長的匹配路徑,因為我們的頁面路徑層級結構跟功能模組的層級結構是對應的,那我們  location匹配的路徑越長,匹配的功能模組的粒度就越細,匹配的相應頁面就越精確

比如個人中心(路徑為/my)下包含訂單相關模組(路徑為/my/order),根據Nginx最長匹配原則,就可以  透過控制匹配路徑長度,來控制要分離的模組的大小,比如透過攔截/my/order來攔截所有的訂單相關頁面。、

1
2
3
4
5
6
location /my/order {
    # 匹配所有以/my/order開頭的請求,其他請求不會被攔截,如/my/coupon則不會被攔截
    # 如訂單列表頁面 會被攔截
    # 將匹配到的頁面請求轉發到新的靜態資源伺服器
    proxy_pass http:  //new-download;
}

同理,個人中心下的評價模組下面的頁面路徑都以/my/remark開頭,那可以透過增加配置 location /my/remark {} 來攔截評價模組。當個人中心下面的子模組都分離完畢,便可以透過縮短匹配路徑來擴大匹配範圍。

1
2
3
4
5
6
location /my {
    # 匹配所有以/my開頭的請求,即個人中心的所有頁面都被攔截
    # 如個人中心首頁 會被攔截
    # 將匹配到的頁面請求轉發到新的靜態資源伺服器
    proxy_pass http:  //new-download;
}

當所有的模組逐步完成了分離,就可以直接攔截根路徑,將所有的頁面請求都取新的靜態資源。

3、雙線並行

技術是服務於業務的,而技術的更迭演進又可以為業務帶來提升,業務版本在高速迭代,猶如奮力爬升的太空梭,而利用上述方案,便可以為飛行中的飛機更換零件甚至發動機,在業務版本迭代的同時逐步進行模組重構,業務是按版本逐步迭代的,但每次迭代一般不會涉及太多模組,而是重點針對其中一到兩個模組進行迭代或者修改,當某次業務版本涉及某個模組時,我們便可以對這個模組進行分離,在分離的同時進行業務版本內容的開發,即完成了業務功能開發,又完成了模組的分離重構,而測試同學只需要測試一次,提高了版本迭代和測試效率。

當然,業務版本一般都是對一些通用模組的迭代,比如商品,結算,購物車等模組,總有一些比較穩定或者生僻的模組很長一段時間甚至一兩年內都不會有大的變動,針對這種情況,就需要單獨的版本進行迭代,好在這些模組並不算多,業務也相對比較穩定。

4、質量保證,風險規避

在一般的業務迭代中,只需要對某些模組程式碼進行修改,適配,或者補充,整個模組完全重構,無疑會增加額外的開發和測試工作量,而更多的變動和修改帶來的是更多的風險和不可控因素,那怎麼保證重構質量呢?

同時,業務版本策劃可能只涉及此次版本業務內容,不涉及該模組的歷史功能,那測試該以什麼參考標準來測試這些歷史功能呢,如何能保證測試覆蓋率,確保所有的業務場景都能被覆蓋到呢?

關於參考標準,線上標準就是最好的標準。現在網頁都提供了http和https兩種訪問方式,使用者訪問的內容是一樣的,在伺服器配置也基本上是一樣的,將https的配置改為新的配置,而http還保持不變,當用https的形式就可以訪問到最新的頁面,而用http形式訪問的還是老頁面,當然,這兩個頁面是可以同時訪問的,因此我們可以進行新舊頁面之間的對比,確保分離前後頁面的一致性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
    listen       80;
    server_name  shop.vivo.com.cn;
 
    # 老的配置不變
    ...
}
 
server {
    listen       443;
    server_name  shop.vivo.com.cn;
 
    # 分離模組配置
    location /my {
      proxy_pass http:  //new-download;
    }
}

為了保證測試覆蓋率,我們引入了程式碼覆蓋率檢查工具,精確檢測某一行程式碼是否被測試用例覆蓋。透過程式碼覆蓋率報告,我們能很清晰的看出哪些程式碼被執行了,哪些分支沒有被執行到,為什麼沒有被執行到,基於這些反饋對測試用例做調整和補充,確保全面的測試覆蓋。

vivo 商城前端架構升級—前後端分離篇

5、遇到的問題

(1)上線部署順序

上線過程主要有三個部分,分別是服務端介面釋出,前端靜態資源釋出,Nginx修改,這三個操作是有前後依賴關係的,如果順序錯了,那就會造成線上事故,因此必須嚴格遵守以下發布順序:

  • 服務端介面釋出

服務端介面是向前相容的,在分離過程中並不是直接在老介面上修改,而是新開了介面,保證在釋出期間新老介面都是可以呼叫的。

  • 前端靜態資源釋出

前端頁面依賴於服務端介面,因此必須確保服務端介面已經發布完畢才可以發前端頁面,否則會出現介面404的問題。

  • Nginx配置修改

這一步要放到最後,如果Nginx在前端靜態資源釋出之前就進行了修改,那使用者訪問頁面時就會出現頁面404的情況。

(2)容災措施

當版本上線出現問題時,如何能快速回退,且不對使用者造成影響?因為我們是直接攔截使用者請求並重定向到了新的靜態資源伺服器,那如果出現線上問題,只需要將此部分的攔截配置關閉,就可以達到快速回退的目的。而服務端介面是向前相容的,因此無需後退。

vivo 商城前端架構升級—前後端分離篇

四、結果

根據這個方案,我們經過一年時間的逐步迭代,迭代8個版本,終於完成wap端的前後端分離,可以讓專業的人做專業的事。現在回過頭來看看,這次技術升級我們到底解決了什麼難題,而它又為我們帶來了什麼提升和正向作用呢?

  • 純前端業務上線釋出速度提升10+倍

  • 釋放研發人力,專業的人做專業的事,開發效率最高提升1倍

  • 打好native化、多端渠道擴充基礎

  • 積累技術經驗、賦能更多業務

五、總結

整個前後端分離過程漫長而曲折,在這個過程中我們面臨的最大問題就是如何在人力成本,業務需求和技術升級之間取得一個平衡點,這對我們來說是很有挑戰性的一個難題,很多時候技術問題都可以找到參考和解決方案,但如何能在複雜的人力,資源,版本,技術積累情況下制定技術方案,兼顧各方,去主動推動解決問題,提前識別和規避風險才是對我們真正的考驗。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69976626/viewspace-2730805/,如需轉載,請註明出處,否則將追究法律責任。

相關文章