2019 JSConf China《面向傳統,Serverless 進化之路》

本次 JSConf China 分享的話題叫 《面向傳統,Serverless 進化之路》,主要講述的是阿里集團內部逐步遷移到 Serverless 體系的過程以及思考。

自 GMTC 以來,國內各個公司在 Serverless 投入都有所變化,騰訊和阿里雲都鉚足了勁在上面發力,提出了各自的解決方案,前段時間騰訊推出了他們的 Serverless 2.0,以及幾天前阿里雲推出的預留模式,都是對 Serverless 越來越重視的表現。

下面還是進入主題。

今天我所介紹的,主要有兩部分,第一是阿里在近期做的前端研發升級,為了拓展前端的邊界和職能,嘗試做了一次和 Serverless 結合,第二是在這其中,我們嘗試對現有的體系做了思考,希望能將傳統應用快速遷移到 Serverless 體系,享受到 Serverless 紅利。

現狀

之前 6 月在 GMTC 講過,阿里的 Node.js 應用非常多,1600+ 的數量讓維護和治理都變的很麻煩,每一次升級都要推行很久,這不管對框架開發還是平臺治理都是不利的。

2019 JSConf China《面向傳統,Serverless 進化之路》

很多 Node.js 應用都是 BFF 應用,內部平臺等,這些應用常年大多都處在負載低(10%以下),沒有流量的狀態,而且維護者大多處在離職或者不積極的狀態,一方面造成了資源浪費,另一方面也給治理造成了困難。

2019 JSConf China《面向傳統,Serverless 進化之路》

其次,現在在集團開發傳統應用,需要申請,整個研發流程還是比較長,需要業務瞭解預算和資源,牽扯到很多細節。

2019 JSConf China《面向傳統,Serverless 進化之路》

為此,我們開始了 前端研發升級 這個大項目。

整個前端研發模式升級的目的有兩個,一是為了“前端賦能”,二是為了“前端提效”。

所謂的“前端賦能”,是因為我們希望前端能夠打破現有的技術壁壘,朝著更底層,面向數據的地方去深入,探索,在這之中可以從面向 UI,視圖本身變的更加了解業務,從更面全面的視角來理解現有的體系。

2019 JSConf China《面向傳統,Serverless 進化之路》

而“前端提效”,則是希望讓 Serverless,用更輕量化的方式進行業務研發,降低整個前端參與業務交付的門檻,同時,在開發期間,也能減少人力總成本,讓前端減負,業務小步快跑成為可能。

2019 JSConf China《面向傳統,Serverless 進化之路》

但是阿里的 Serverless 的路非常困難,不像外界已經有的成熟的體系,目前一些原因無法使用上公有云上開放的產品,阿里雲也無法直接對內部提供服務,同時,內部的中間件在外部都沒有,都需要跨團隊來重新建設。

而我們 Node.js 基礎團隊的使命,就是給集團 Node.js 生態提供各種基礎能力,包括但不限於框架,中間件包等,而在 Serverless 體系,我們要負責框架、工具鏈、運行時、發佈系統,同時也需要和周邊的網關,監控系統等對接。

2019 JSConf China《面向傳統,Serverless 進化之路》

收益

從去年 10 月開始,我們開始進行調研 Serverless 以及瞭解相關的知識,到現在為止,我們已經取得了一定的階段性成果,將淘寶和飛豬兩道 BU 的導購鏈路整個遷移到了 Serverless 體系,並且承載了導購鏈路的千萬級流量。

2019 JSConf China《面向傳統,Serverless 進化之路》

同時,內部系統也進行了一定程度的 Serverless 升級嘗試,不管是重寫還是傳統應用遷移,我們都有了一定的沉澱。

我們最初的目的是希望能降低成本,按照網上 Serverless 的降低成本率能達到 90% 以上,不過導購業務比較特殊,流量比較大,不像那些需要彈性的應用,根據我們的測算,單進程下函數的性能非常不錯,但是由於大促要提前預留一些資源,整體機器成本只降低到了平時的 70%,而在非大促期間,不需要預留這些資源,就能更低,降到 40% 以下。

2019 JSConf China《面向傳統,Serverless 進化之路》

現在都說 DevOPS,而 Serverless 最大的好處是減少運維,減少固定服務器資源,不需要用戶關心調度等,同時也簡化了開發的代碼,專注了邏輯,晚上睡覺會更加的放心,不再擔心機器容量不足而報警。

2019 JSConf China《面向傳統,Serverless 進化之路》

另一邊,對於我們應用治理的人來說,之前會考慮各種版本碎片化的問題,node 的多版本,框架的多版本,以及啟動腳本、依賴等等問題,而使用 Serverless 之後,我們將這些都固化了,用戶也不關心這些,一切都變的簡單了,我們也只需要治理運行時一個版本即可。

2019 JSConf China《面向傳統,Serverless 進化之路》

在業務前端方面,帶來的是挑戰和機遇,一方面,前端的工作量增大了,能幹的事情也變多了,成了一職多能的多面手,也更瞭解業務了,另一方面,傳統的後端可以從和前端溝通中解放出來,更專注於提供服務。前端從傳統的面向接口編程變成了面向服務編程,由於集團內都是 RPC 服務,在 RPC 發佈時會有固定的定義和文檔,在調用時有工具輔助生產代碼,大大簡化了調用鏈路。

2019 JSConf China《面向傳統,Serverless 進化之路》

在流程方面,原來需要在各個環境準備和調研,從一開始申請應用,申請預算,申請環境開始,需要了解各個方面的知識,和不同部門的人打交道,流程審批也很長,而現在只需要在我們的統一研發平臺上直接申請函數組,替代了原本的複雜流程,也提升了整個開發體驗。

2019 JSConf China《面向傳統,Serverless 進化之路》

同時在編碼中也不再考慮路由,MVC 的事情,這些在網關層配置就好,編寫代碼時會更關注邏輯,和之前的構建發佈不同的是,現在增加了雲端集成測試的步驟,由於函數和前端代碼一樣,是分版本的,也不擔心修改到線上的正常服務,在測試完畢後,只需要將舊函數的 tag 指向新函數即可,這就完成了整個切流的過程,而一旦碰到問題,把 tag 切回去就行。

2019 JSConf China《面向傳統,Serverless 進化之路》

這整個就是我們前端研發模式升級的思考和收益,帶給我們的不僅僅是變化,更多的是流程、思維的革新。

思考

在研發模式升級過程中,我們針對現有的導購業務進行了重構,可以說是使用了 Serverless 的方式進行了重寫,而有一些老的應用,如果整體進行改造,這個成本會非常之大。

這個時候開發者就會有很常見的一個疑問,“我原來的應用,怎麼遷移到 Serverless 體系”。

而我們的回答是兩種:

  • 1、使用 FaaS + Baas 的方式進行重構,代碼更精簡,就是需要改造成本
  • 2、把整個傳統應用作為一個函數,雖然不夠優雅,但是能解決遷移的問題
2019 JSConf China《面向傳統,Serverless 進化之路》

把整個應用遷移到函數會有一些限制,會對代碼結構和模型做一些微調,以符合整個 Serverless 的結構,畢竟新的體系和傳統的代碼模型是有所區別的。

阿里集團採用的是 FaaS + BaaS 的實現方式,而 FaaS 的整體概念和傳統的應用不太一樣。

2019 JSConf China《面向傳統,Serverless 進化之路》

在概念上,Serverless 比 FaaS 的外延要廣,FaaS 屬於 Serverless 的其中一種實現方式,主要解決的是用戶自定義的代碼邏輯如何做到 Serverless,也可以叫做 Serverless Compute,同時它也是事件驅動架構的一種。

而 CNCF Serverless 白皮書中也說到,Serverless Compute 是一種粒度更細的部署模型,通過一個或者多個 function,用於響應用戶的需求。可以說,粒度小,靈活性高是它的最大特性。

在代碼層面,為了讓用戶更好的理解,我們把傳統代碼的結構進行了分解,傳統的 MVC 類型的代碼,會分為幾層。

  • 1、HTTP 服務,原框架(koa/midway/egg...),Node.js 運行時,啟動腳本等,將會變為函數運行時,固化下來
  • 2、原有的 HTTP Router,Web 中間件等,將會由 HTTP 網關承接
  • 3、原有的 Controller,業務邏輯(調用遠程服務),繼續保留,變為函數代碼
  • 4、原有的數據庫,消息隊列,RPC 調用等,都作為 BaaS 服務,用戶只關心對應的服務,使用同一的 BaaS Client 進行調用
2019 JSConf China《面向傳統,Serverless 進化之路》

這樣分解過後,我們對新舊兩個體系的代碼結構有了進一步認識,可以開始嘗試修改部分代碼,變成真正的 Serverless。

遷移

傳統的應用,會暴露出一些對外的服務供外部調用,比如 HTTP,定時任務,RPC 服務等等,這些服務一般我們會單獨抽離目錄,並且和其他暴露的服務共享邏輯層代碼,我們也經常稱這些服務為“入口”。

2019 JSConf China《面向傳統,Serverless 進化之路》

在 Serverless(FaaS) 化的過程中,我們會根據當前部署平臺的能力(比如阿里雲 FC,騰訊 SCF 都會提供 HTTP 服務,定時任務,消息隊列等等),將這些入口代碼變為基於事件驅動的函數,

2019 JSConf China《面向傳統,Serverless 進化之路》

我們通過構建機制,在發佈時生成不同的包,在共享一份邏輯代碼的同時,部署到不同的環境,這個方案最大的優勢是複用了原有的邏輯部分,可以和傳統應用同步開發,而劣勢也有,就是包依賴混在一起,由於函數對包大小有限制,可能會造成依賴過大等問題。

HTTP 相對於其他的來說會複雜很多,會有很多限制,這個我們在講下游方案的時候再說。

2019 JSConf China《面向傳統,Serverless 進化之路》

針對上面的情況,對下游的數據調用我們也有相應的方案。我們將這些方案取了幾個名字,比如代理模式和網關模式。

代理模式

首先來看看代理模式。一個傳統的 Web 應用會分為 Router/Controller,以及邏輯層,在代理模式中,我們會保留傳統的應用,只將原本的邏輯層部分遷移到了雲函數中,暴露出 HTTP 服務。

2019 JSConf China《面向傳統,Serverless 進化之路》

這樣的好處是代碼變的精簡,改動適中,也易於服務複用,缺點就是依舊會佔用一個應用資源作為代理層。

而代理應用一般是通過 HTTP 客戶端代理來實現的只是用戶體感上需要做一些額外的支持,讓開發者在體驗上感覺到是調用了遠端服務。

2019 JSConf China《面向傳統,Serverless 進化之路》

網關模式

第二種方式是網關模式,這個模式下,所有的代碼都會遷移到新的體系,在 Web 層簡單的時候比較適用。

該模式下,所有傳統的 Web Router 會遷移到 HTTP Gateway 上,原本的路由,會話、鑑權等能力都將被網關所控制,而函數本身不需要關心這些,只需要關心數據即可。

業界現有的 FaaS 模型大多是這種結構,集團內也採用了這類結構去實踐。

2019 JSConf China《面向傳統,Serverless 進化之路》

在這種模式下,原有的能力會碰到一些問題,舉一些例子:

  • 1、原有的 Web 中間件(koa middlware),會不知道如何處理,中間件大多是做請求流的攔截和消費,這個時候大多會拆成兩部分,一部分被網關所處理,另一部分,只能交給函數本身,如果有共享的需求,也可以依賴模塊來完成
  • 2、原有的會話維持,一部分平臺會進行透傳 cookie,這個時候你依舊可以維持一個 sessionId,同時使用第三方來存儲數據,但是如果網關不做這塊,那麼就很麻煩了
  • 3、請求對象和原有的不同,由於函數獲取的是 event,context 參數,或者原始的 request 對象,和現有的 koa 等框架不是很一致,上面的方法不一定有,會導致原有的代碼做出修改和挑戰

偽裝者模式

那麼有沒有不修改代碼的方案呢?我們嘗試在函數外部進行代碼包裹和數據模擬,讓應用整個跑在函數之上,以一種 “微應用” 的方式繼續存在。

2019 JSConf China《面向傳統,Serverless 進化之路》

我們把原有的 Web Server(midway/egg),啟動起來,在運行時中通過一個固定的端口轉發,把 FaaS 的請求參數包裹成 HTTP Request 對象,而在出口處,也將 HTTP Response 包裹為函數能讀懂的形式,通過這樣續命的方式來延續傳統應用。而由於阿里雲上的容器只讀不能寫,目前還無法直接用這種模式。

2019 JSConf China《面向傳統,Serverless 進化之路》

這種方式需要調整的是,框架需要使用單進程模型(機器配置,輕量化的要求),應用需要無狀態(函數機制決定),以及沒有長連接等高消耗的操作。

2019 JSConf China《面向傳統,Serverless 進化之路》

總結

關於 Serverless 的問題還有很多,30 分鐘我們無法關注到過於細節的地方,我們從阿里當前的狀況講起,分享了從去年到今年的研發模式升級實踐,也介紹了在這其中我們的一些思考,傳統應用遷移到 FaaS 體系下的方式。

感謝大家來 JSConf 聽(閱讀)我的分享,我們的整套方案希望經過雙十一的洗禮,大流量的考驗,在之後貢獻給社區,開放給大家。


原文地址

https://zhuanlan.zhihu.com/p/87940654


分享到:


相關文章: