Node部署和運維工作量降低80%,騰訊NOW直播是怎麼做到的?
- 2019 年 11 月 14 日
- 筆記
上一篇文章,分享了《NGW,前端新技術賽場:Serverless SSR 技術內幕》,本篇文章,將分享騰訊NOW直播在Serverless技術的探索實踐。
一、背景簡介
首先解釋一下幾個名詞:
- NGW(Node Gateway,Node 前端接入層):IVWEB 團隊開發的內部前端業務接入層方案,目前處於騰訊內部開源狀態。
- BFF (Backend For Frontend) ,通常指服務於前端的後端。
- SFF (Severless For Frontend) , BFF 架構的升華,落地到 Serverless 中。
目前,NOW 直播團隊正在逐步接入 NGW,完成 BFF 向 SFF 架構的演進。
從前後端分離到 BFF,前端的能力不斷擴大,逐漸涉獵到後端和運維,對前端人員的技術能力要求也越來越高。NOW 直播 IVWEB 團隊從提升研發效率的角度,在調研了騰訊雲Serverless之後,團隊決定接入雲函數SCF產品,對 BFF 架構結合 Serverless 進行了新的嘗試。
在 SFF 架構下,Node 服務落地到 Serverless,最大的收益者是前端開發人員:
- 前端同學不再需要關注伺服器的申請/維護/擴容;
- 無需關心生產環境的搭建;
- 真正做到專註業務邏輯的開發;
- 自動擴容,零運維;
- 接入工作量降低了 80%。
此前,團隊已經通過開發 Nest 系統的聚合服務(Node 服務的可視化管理)完成了 BFF 架構的演進。NGW 作為新項目,響應騰訊自研上雲的號召,拋開歷史包袱,全面擁抱上雲,並且有幸成為公司內首個和騰訊雲 SCF 大規模合作的前端項目,結合 SCF 實現了同構直出和 Node 服務的無服務化,做到自動部署和更新。在這裡感謝騰訊雲Serverless團隊和QQ團隊的大力支援。
二、從一個故事說起
阿特是個特別認真的人,但也有漢子柔情的一面,他攢了很久的假期,準備在情人節和小美來一場說走就走的旅行。不巧,就在情人節前一天,新上線的項目被產品挑戰了,說「首屏速度不夠快」。
作為高級工程師的阿特,有 100 種可以讓頁面提升首屏的方法;他馬上用團隊的同構直出框架,半天就擼出來了一個直出服務,部署完之後就可以和心愛的小美去旅行了。
阿特打開運維繫統,看了一下業務機的承載,需要擴容才能滿足需求。為了不影響線上業務,阿特選了新申請一批機器。半天過去了,新機器終於下來了,這時距離下班時間還有 5 分鐘。為了小美的旅行,今天無論如何都要上線。
面對新下來的機器,阿特一把梭裝好了所有基礎組件,配置和部署好直出服務,現在只需要將原來的靜態請求接入到直出服務就可以了;但事情並沒有這麼簡單,現網的域名竟然要經過好幾層接入機才能到直出服務。
憑藉著高級工程師的一雙能手,阿特一步步地終於將業務成功上線了。他鬆了一口氣,看了一下時間,沉默了許久。現在是北京時間 2 月 14 日上午 9:55,距離飛機起飛時間還有 5 分鐘,阿特終究還是錯過了和小美的旅行。
故事雖然聽起來比較誇張,但反映的事實卻無比真實:
- 業務不斷增多,服務混布導致新老業務的變更越來越複雜,全部獨立部署則會造成資源浪費;
- 運維繫統魚龍混雜概念繁多,不是老司機很難理清楚,對小白不友好;
- 業務模組多、機器多、配置多,變更全靠配置系統下發;
- 前後端共用接入機,轉發邏輯複雜。
我們發現,即使完成了 BFF 架構的演進,但難免會存在服務混布,而且仍需關注複雜的運維,效率的瓶頸始終在運維上。有沒有一種方法可以既能使服務獨立部署,並且能有效降低運維成本呢?
答案:Serverless。
三、NGW 的架構
NGW(Node Gateway,Node 前端接入層)是介於 STGW 和真實業務的中間層,用戶的請求會通過 統一網關先進入到 NGW 層,再由 NGW 來分發請求到對應業務上。

這裡的業務可以是:
- 靜態頁面
- BFF 架構下的 Node 服務
- SFF 架構下的 Serverless 直出或 Node 服務
咦,這不是 Nginx 做的工作嗎?——Nginx 雖然強大,但缺點是無法做到強邏輯的分發,也不容易進行擴展,而且每次更改配置之後都需要重啟服務,查看日誌也很困難。
NGW 使用 TypeScript + Node 開發,對前端同學更友好,能更方便地進行功能的迭代和擴展,轉發邏輯可以動態下發,無需重啟服務。
整個 NGW 方案主要分為三個模組:
- NGW 分發層:主要專註於業務的分發;
- NGW-Service 層:負責周邊服務,如配置管理、Serverless 服務的部署和更新,日誌旁路等;
- NGW Platform:管理平台,用於配置管理與日誌管理等。
四、容器化
作為 9102 年的新項目,響應自研上雲的號召,NGW 的全部服務均使用 Orange-CI(自研內部 CI 工具) + TKE 騰訊雲容器服務 進行構建和部署,並利用容器編排對 Docker 鏡像的構建部署進行了優化。(優化後構建鏡像時間縮短為 20秒,大小縮小至 10M 以內)
NGW 分發層作為業務分發的基礎服務,性能和穩定性非常重要,有了 Orange-CI 和 STKE 的加持,大大提高了服務部署的敏捷程度,並且在高並發場景下也能做到靈活自動擴容,再也不用提前評估業務量。
TKE 單機滿負載運行資源佔用(8 核 16G,數據來源 TKE):

高並發場景壓測下自動擴容至 8 個實例,峰值接近 8000 TPS(數據來源於 WeTest 壓測大師):

為什麼峰值只壓到 8000 TPS 呢?主要是因為峰值已經達到下層靜態伺服器的最大承載了,導致轉發效率變慢,並不代表 8000 TPS就是 NGW 層的最大承載(逃)。在 STKE 資源充足的前提下,NGW 是可以無限擴容的,無需擔心高負載導致伺服器宕機。
五、配置下發
Nginx 每次更改轉發配置,都需要重啟 Nginx 服務。
NGW 開發了 NGW-Service 層,結合管理平台對配置進行動態管理,配置更改後通過雲 Redis 下發到 NGW 分發層中。配置熱重載,平滑過渡。
配置下發流程:

目前已完成分發邏輯的動態下發,後續將陸續支援操作記錄和版本管理。
六、Serverless 無服務
在 NGW 分發層的基礎上,結合騰訊雲 SCF,就能更方便靈活地對現有 Node 服務進行 BFF 到 SFF 的演進。
- NGW-Service 負責 Serverless 服務的管理,如部署、更新等;
- NGW 分發層進行業務的轉發。
架構:

目前 NGW 已經支援同構 SSR 的 Serverless 化方案,並且已接入多個項目在線上通過驗證,成功率接近 99.99%(數據來自內部打點統計系統)。

NGW 目前處於騰訊內部開源狀態,待方案完善脫敏後將會逐步進行外部開源。
關於 Serverless 化方案的實現技術細節,後續將會有專門的文章來介紹,本文先不贅述了。
七、插件體系
前文說到 Nginx 雖然強大,但缺點是不容易進行擴展。NGW 的分發功能擴展是怎麼實現的呢?
除了 Koa 中間件,NGW 還引入了插件的概念來對專用分發邏輯進行模組化:
- Koa 中間件:用於處理統一邏輯;
- 插件:與單次分發過程的生命周期強關聯,用於處理專用邏輯。
插件的實現基於 Tapable,通過生命周期鉤子來對分發過程進行邏輯干預。
生命周期鉤子:
// 分為同步和非同步鉤子兩種,以同步鉤子為例interface ApplicationSyncHooks { // 收到請求 didReceiveReq: AsyncSeriesHook<[Application, ProxyConfig]>; // 即將轉發代理請求 willSendProxyReq: AsyncSeriesHook<[Application, ProxyConfig]>; // 代理請求成功 proxyReqSucc: AsyncSeriesHook<[Application, TswAjaxResult]>; // 代理請求失敗 proxyReqFail: AsyncParallelHook<[Application, TswAjaxResult]>; // 接收到代理請求響應 didReceiveProxyRes: AsyncParallelHook<[Application, IncomingMessage]>; // 即將返回代理層響應結果 willReturnRes: AsyncSeriesHook<[Application, IncomingMessage]>; // 返迴響應完成 didReturnRes: AsyncSeriesHook<[Application, TswAjaxResult]>;}利用插件,可以在基礎的分發邏輯上進行一些專用的邏輯處理,比如灰度轉發、白名單等。以灰度插件為例,可以在分發配置中添加插件:
{ "origin": "/ngw/index.html", "proxyPass": "http://the-path-where-you-want-to-go.com", // 添加灰度插件,Application 會在分發前進行插件實例化,並將 args 傳入構造函數中 "plugins": [{ "name": "AlphaPlugin", "args": ["plan-A"] }]}插件邏輯處理:
// 以下為簡化程式碼... class AlphaPlugin extends AbstractPlugin { public name = 'AlphaPlugin'; public config: AlphaPluginConfig; public constructor(args: AlphaPluginConfig) { super(); this.config = args; // 接收配置中的 args 參數 } public apply(application: Application) { application.syncHooks.didReceiveReq.tapPromise(this.name, this.didReceiveReq.bind(this)); } public async didReceiveReq(application: Application, proxyConfig: ProxyConfig) { const alphaConfig = getAlphaConfig(this.config[0]); // 獲取灰度邏輯,入參是配置的 "plan-A" proxyConfig.proxyPass = alphaConfig.url; // 修改分發的地址 }}這樣一來,就可以通過灰度插件實現對現網業務進行灰度上線或 ABTest,比如現網投放的 A 頁面,通過 NGW 可以動態分發到 B 或 C 等頁面。
八、日誌查看
NGW 基於 TSW,得益於 TSW 的染色體系,可以輕鬆地查看實時染色日誌,秒殺 Nginx。後續也會將 SCF 中的日誌收歸到 NGW-Platform 中。
九、現狀
Serverless SSR

目前 NGW + Serverless SSR 已經應用到 NOW 直播、手 Q 附近、瀏覽器直播和手 Q 群送禮等多個項目中。實際業務開發中,Node 業務的部署和運維工作量降低了 80% 以上。
以前的業務上線路徑:
申請機器 -> 申請 CL5 -> 織雲包下發部署服務 -> 更改 Nginx 配置
接入 NGW + Serverless SSR 只需要兩步,後續接入團隊腳手架後,連這兩部都可以省掉了,工作量 down down down:
- 更改 oci 配置,將 CI 製品推送到 SCF
- NGW-Platform 添加分發配置
穩定性
NGW 目前的分發成功率穩定在 3 個 9 以上,單元測試覆蓋率已超過 85%。

十、接下來的計劃
- 和騰訊雲 SCF 展開深度合作,提升性能;
- React Chunked 流式渲染方案,結合 SCF 進一步提升首屏速度;
- 接入 Aegis 前端監控體系,實現前端全息日誌;
---------下方更多精彩----------

NGW,前端新技術賽場:Serverless SSR 技術內幕


