美團早期業(yè)務(wù)快速發(fā)展,各業(yè)務(wù)在 Node 應用上各取所長,但在可用性和運維上需要付出額外的維護成本。隨著美團建設(shè)了 Serverless 平臺,前端也緊隨其后,將 Node 應用由傳統(tǒng)架構(gòu)向 Serverless 架構(gòu)演進,通過 Serverless 方式升級 Node 基礎(chǔ)設(shè)施。
本次分享將介紹美團建設(shè) Serverless 前端研發(fā)體系的建設(shè)思路,并與大家分享如何為各業(yè)務(wù)提供統(tǒng)一的 Serverless 平臺,支持業(yè)務(wù)向 Serverless 遷移,最后分享了美團的部分具體業(yè)務(wù)案例,希望給大家在 Serverless 技術(shù)轉(zhuǎn)型和實踐帶來一些啟發(fā)。
本文整理自美團前端技術(shù)專家張方成在 ArchSummit 全球架構(gòu)師峰會(深圳站)上的演講分享,主題為“美團基于 Serverless 的前端研發(fā)體系建設(shè)和業(yè)務(wù)實踐”。分享主要分為四部分:1. 背景;2. 美團 Serverless 前端建設(shè);3. 前端交付實踐;4. 未來規(guī)劃。
背景
為什么做 Serverless?
首先我們?yōu)槭裁匆?Serverless?美團是一個一站式的生活服務(wù)平臺,為消費者提供外賣旅游等服務(wù),為商戶提供營銷、配送等服務(wù)。作為美團技術(shù)團隊,我們需要為消費者、商戶還有內(nèi)部的開發(fā)者提供很多的技術(shù)平臺。隨著美團業(yè)務(wù)復雜度不斷增加,技術(shù)團隊面臨的挑戰(zhàn)也越來越大。
技術(shù)架構(gòu)演進
我們的技術(shù)架構(gòu)演進可以分為三個階段,整體趨勢是復雜度下沉并服務(wù)化。
第一個階段,我們稱為基礎(chǔ)設(shè)施的服務(wù)化,這一階段由基礎(chǔ)技術(shù)平臺負責基礎(chǔ)設(shè)施的維護工作,業(yè)務(wù)同學需要負責業(yè)務(wù)應用,以及一些平臺軟件的開發(fā)和維護工作。
第二個階段,我們稱為平臺服務(wù)化,這時候我們將業(yè)務(wù)應用原來維護的平臺軟件部分下沉到技術(shù)基礎(chǔ)平臺,由技術(shù)基礎(chǔ)平臺統(tǒng)一負責平臺和基礎(chǔ)設(shè)施的維護工作。
第三個階段,我們稱為業(yè)務(wù)邏輯托管服務(wù)化,這個時候我們將業(yè)務(wù)應用當中大量的通用邏輯下沉到技術(shù)基礎(chǔ)平臺,由技術(shù)基礎(chǔ)平臺統(tǒng)一負責基礎(chǔ)設(shè)施、平臺軟件、業(yè)務(wù)應用底座相關(guān)的一些維護工作,業(yè)務(wù)開發(fā)者只需要維護相應的業(yè)務(wù)邏輯即可。
目前我們正處在由平臺服務(wù)化向業(yè)務(wù)邏輯托管架構(gòu)演進的階段,在這個時候,Serverless 是一個很重要的技術(shù)點。
Serverless 可以為前端解決什么問題?
2019 年我們上線了 Serverless 平臺,Serverless 使業(yè)務(wù)開發(fā)者聚焦業(yè)務(wù)邏輯開發(fā)工作,主要幫助前端解決 Web 應用場景下的問題。美團的 Node 主要應用在 B 端、C 端以及工具型產(chǎn)品:B 端產(chǎn)品的特點是系統(tǒng)本身很復雜,更關(guān)注研發(fā)的效率;C 端產(chǎn)品的特點是訪問量比較大,更關(guān)注服務(wù)的穩(wěn)定性;工具型產(chǎn)品的特點是訪問量比較低,但仍然需要占用大量的機器,更關(guān)注機器的費用問題??偨Y(jié)下來業(yè)務(wù)面臨的痛點主要有三個:
1、研發(fā)效率低,體現(xiàn)在研發(fā)過程當中,開發(fā)者仍然需要負責很多業(yè)務(wù)無關(guān)的工作;
2、運維成本比較高,體現(xiàn)在開發(fā)者需要在穩(wěn)定性保障上做很多事情;
3、機器費用比較高,比如說機器需要冗余部署,資源利用率整體也比較低。
Serverless 是如何幫助我們解決這些問題的?假如我們現(xiàn)在要開發(fā)一個 Node 應用,通常會涉及到基礎(chǔ)設(shè)施、平臺軟件等工作,當然在業(yè)務(wù)應用層還需要考慮框架還有服務(wù)的可用性,包括性能、高并發(fā)這些問題,整體下來我們的運維成本從上至下越來越高。
Serverless 對前端開發(fā)者屏蔽了基礎(chǔ)設(shè)施、平臺軟件,以及業(yè)務(wù)應用底座當中一些復雜的事情,使前端開發(fā)者可以聚焦在業(yè)務(wù)邏輯開發(fā)當中。
這是我們 Serverless 前端的全景,主要包括研發(fā)套件、PaaS 平臺、技術(shù)組件,以及業(yè)務(wù)層的解決方案。我們通過研發(fā)套件的建設(shè)和技術(shù)組件的建設(shè)來提升業(yè)務(wù)的開發(fā)效率,通過 PaaS 平臺的建設(shè)來為業(yè)務(wù)提供服務(wù)的架構(gòu)和穩(wěn)定保障能力,同時 PaaS 的彈性特點,可以很好解決原來系統(tǒng)與部署的問題。
美團 Serverless 前端建設(shè)
研發(fā)套件建設(shè)
研發(fā)套件主要是指研發(fā)流程當中需要的一些工具,比如說框架、開發(fā)工具和部署工具等等。在前端研發(fā)與 Serverless 結(jié)合的背景下,我們面臨的主要問題是,原有的研發(fā)流程當中一些工具不好用甚至是用不了,這些工具面臨重構(gòu)。公司內(nèi)開發(fā)就有很多研發(fā)框架,在 Serverless 下,我們需要的是一個開箱即用的 Serverless 研發(fā)框架。在調(diào)試階段,我們希望可以去調(diào)試 Serverless 下的云函數(shù)能力;在構(gòu)建部署階段,Serverless 當中我們部署的是函數(shù),原有的發(fā)布工具支持也不是很好,我們希望可以去部署對函數(shù)友好的項目;在線上運維階段,我們也希望去提供 Serverless 架構(gòu)下的一些運維工具,幫助業(yè)務(wù)降低在 Serverless 架構(gòu)下的運維成本。
我們的整體思路展開來說,第一是在開發(fā)階段,通過開放能力的建設(shè),去集成業(yè)務(wù)研發(fā)框架,使已有的框架可以低成本地在 Serverless 架構(gòu)下運行起來;第二是提供整個研發(fā)流程中一些必要的工具,比如說在調(diào)試階段,提供本地 / 遠程的調(diào)試能力,在構(gòu)建部署階段,提供部署組件、灰度組件,在線上運維階段,提供服務(wù)的監(jiān)控、鏈路追蹤以及性能診斷等運維工具。
下面來看一下我們通過開放能力集成業(yè)務(wù)的框架,和在云端開發(fā)體驗上的一些探索。
首先看一下我們?nèi)绾瓮ㄟ^開放的能力集成已有的框架。我們的策略是與公司內(nèi)框架的提供者團隊合作共建,使已有的業(yè)務(wù)框架遵循相關(guān)的規(guī)范,沉淀到我們 Serverless 研發(fā)套件中來,這樣就可以面向公司范圍去提供框架服務(wù),我們制訂了架構(gòu)規(guī)范和部署規(guī)范,以及運維相關(guān)的規(guī)范。
同時我們基于 Serverless 架構(gòu),正在探索云端的開發(fā)體驗,探索完全在線的開發(fā)結(jié)構(gòu)模式,開發(fā)者只需要打開瀏覽器就可以實現(xiàn)項目的開發(fā)部署、運維等相關(guān)所有的事情,云端開發(fā)可以幫助我們實現(xiàn)整個開發(fā)周期的閉環(huán),包括項目的創(chuàng)建、開發(fā)、調(diào)試、部署,還有運維當中的一系列工作。
與傳統(tǒng)的本地開發(fā)模式相比,云端開發(fā)幫助我們消除了本地線上頻繁的切換動作,提高了開發(fā)效率,同時云端開發(fā)可以幫助我們實現(xiàn)高效的同步合作,云端開發(fā)提供一致的橫向配置,以及可共享的開發(fā)環(huán)境,可以使代碼協(xié)作就像在線文檔協(xié)作一樣簡單,提高整體的協(xié)作效率。有了云端開發(fā)并不意味著我們放棄了傳統(tǒng)的開發(fā)模式,兩者是可以互補的,目前我們也在探索實踐當中。
基礎(chǔ)組件建設(shè)
下面我們來看一下基礎(chǔ)組件,主要是指 PaaS 產(chǎn)品和運維產(chǎn)品。我們面臨的主要問題是學習和使用的成本比較高,主要體現(xiàn)在 SDK 同步、配置比較零散。我們有幾十個技術(shù)組件,比如數(shù)據(jù)庫、對象存儲、文件存儲等等,我們原有的使用方式是需要在代碼當中引入技術(shù)組件的 SDK,通過一系列的配置還有調(diào)試工作,使代碼和組件正常跑起來,整個流程下來的成本還是比較高的。我們的策略是為業(yè)務(wù)提供兩種簡化的使用方式:第一種是基于事件模式的使用方式,開發(fā)者只需要在 FaaS 管理端去配置化啟用相關(guān)的組件,不需要引入 SDK,開發(fā)者只需要提供一些 API 方法,我們?nèi)ヌ幚硐嚓P(guān)的邏輯即可,技術(shù)組件的 SDK 調(diào)用還有事件的觸發(fā)都由事件網(wǎng)關(guān)這一層來負責。第二種是基于運行時的使用方式,我們在函數(shù)運行時內(nèi)部提供技術(shù)組件加載器,主要負責加載這些技術(shù)組件,開發(fā)者只需要在文件當中去配置相應的組件,同時也不需要引入 SDK,就可以在函數(shù)上下文當中去調(diào)用相應的實例以及相應的 API 方法。
FaaS 平臺建設(shè)
我們下面來看一下 FaaS 平臺,即云函數(shù)平臺。我們大體上可以把它分為運行態(tài)和管理態(tài),運行態(tài)要負責事件流轉(zhuǎn)的過程。首先由觸發(fā)源來產(chǎn)生事件,經(jīng)過事件網(wǎng)關(guān)分發(fā)到具體的業(yè)務(wù)實例當中的函數(shù)里去處理,業(yè)務(wù)函數(shù)會對我們的事件做處理和響應。事件網(wǎng)關(guān)除了分發(fā)流量之外,還會做一些限流降級、流量統(tǒng)計等相關(guān)的工作。在實例這一層提供了函數(shù)沙箱,里面運行的是業(yè)務(wù)函數(shù),對業(yè)務(wù)函數(shù)起隔離的作用,在管理系統(tǒng)里提供函數(shù)的管理、發(fā)布以及監(jiān)控等運維能力。
下面我們來看三個問題,首先是我們?nèi)绾螒獙Ω卟l(fā)問題,第二是我們?nèi)绾谓档蜋C器的費用,第三個我們在穩(wěn)定性保證建設(shè)方面做了哪些事情。
首先看一下我們是如何應對高并發(fā)的。Serverless 架構(gòu)下,彈性的特點可以幫助我們在需要的時候得到更多的實例來承擔流量,事件網(wǎng)關(guān)會將我們的請求分散到不同的實例上,達到負載均衡的作用。我們支持高并發(fā)的一個關(guān)鍵是需要支持快速擴容,需要在短時間之內(nèi)擴容到所有的實例,這樣服務(wù)才是足夠穩(wěn)定的。支持快速擴容的關(guān)鍵就是減小整體的冷啟動時間,冷啟動時間長意味著我們需要更多的時間來得到足夠的實例,我們的服務(wù)就會有風險。
我們看一下冷啟動優(yōu)化治理,整體流程包括容器啟動、鏡像下載、業(yè)務(wù)代碼下載、啟動容器、業(yè)務(wù)函數(shù)運行,以及代碼加載這么多過程。其中容器啟動里包含了美團的一些定制化的流程。我們做了一些相應的優(yōu)化,第一個方式是消除實例初始化的時間,主要的策略是提供資源池的方案,提前啟動好一批常用配置的機器,當業(yè)務(wù)需要的時候從資源池當中調(diào)度和分配給相應的業(yè)務(wù)即可。第二個優(yōu)化方式是減小業(yè)務(wù)代碼體積來降低業(yè)務(wù)代碼的下載和加載時間。
下面我們來看一下如何降低機器費用。Serverless 架構(gòu)下彈性的特點可以幫助我們把傳統(tǒng)模式下機器浪費的問題給解決掉,這里我們要說的是如何進一步降低機器的費用,主要有四種方式:
第一種是提供單實例、多并發(fā)的能力
第二種是減小沙箱的配置
第三種是提供實例為 0 的能力
第四種方式是提供合并部署的方式
下面我們來看一下穩(wěn)定性保障,我們整體的策略是穩(wěn)定性和建設(shè)下沉,使業(yè)務(wù)專注于解決自身的調(diào)整。作為 PaaS 平臺的提供方,我們希望為業(yè)務(wù)承擔更多業(yè)務(wù)無關(guān)的工作。這是我們穩(wěn)定性保障的全景,整體分為 7 層,下面的三層主要是與故障的識別、風險規(guī)避和故障處理相關(guān)。上面的四層主要是與軟件的開發(fā)和產(chǎn)品的發(fā)布流程相關(guān),我們在各個方面都做了一些建設(shè),這里我們主要看一下在高可用架構(gòu)、可觀測性,以及灰度發(fā)布部分的工作。
首先在高可用架構(gòu)上,我們提供了部署架構(gòu)、彈性伸縮、容災降級等方面的保障。在部署架構(gòu)這里,我們?yōu)椴煌臉I(yè)務(wù)線提供了一些獨立的集群來運行相關(guān)業(yè)務(wù),這樣可以做到業(yè)務(wù)線的隔離。在業(yè)務(wù)的獨立集群內(nèi)我們做了多機房的部署,做到了按地域隔離。在彈性伸縮這里我們支持定時伸縮、預留實例,以及提前擴容,提前擴容是指當流量達到擴容條件的時候,提前準備實例來承接流量。在平臺降級這一塊,我們在事件網(wǎng)關(guān)這一層提供了業(yè)務(wù)層的降級能力,配合著我們對業(yè)務(wù)提供的限流和熔斷這些能力,整體保障業(yè)務(wù)服務(wù)的可用性。
下面我們來看一下可觀測性,可觀測性主要是指發(fā)現(xiàn)問題和定位問題的能力。發(fā)現(xiàn)問題方面,我們希望提供 Serverless 架構(gòu)下的服務(wù)交換能力,幫助業(yè)務(wù)更好地觀測云函數(shù)的運行狀態(tài),在定位問題方面,我們提供了服務(wù)日志與性能診斷等平臺,來幫助業(yè)務(wù)去排查業(yè)務(wù)問題,還有代碼的性能問題,在服務(wù)監(jiān)控方面,基于公司統(tǒng)一的無監(jiān)控平臺,定制了 Serverless 架構(gòu)下的系統(tǒng)監(jiān)控、應用監(jiān)控還有健康監(jiān)控。系統(tǒng)監(jiān)控提供的是實例緯度的 CPU、磁盤這些監(jiān)控數(shù)據(jù),應用監(jiān)控提供的是應用粒度的訪問量、QPS 等監(jiān)控的數(shù)據(jù),進程的監(jiān)控提供的是代碼實際運行進程內(nèi)的 CPU 和內(nèi)存相關(guān)的數(shù)據(jù)。進程監(jiān)控可以幫助開發(fā)者更清晰地看到函數(shù)實際運行進程內(nèi)的情況。
在 Serverless 架構(gòu)下,函數(shù)平臺內(nèi)部的事件網(wǎng)關(guān)還有函數(shù)運行時成為請求鏈路當中的關(guān)鍵節(jié)點,我們也提供了一些平臺內(nèi)部的日志,幫助業(yè)務(wù)去排查問題。同時結(jié)合業(yè)務(wù)的用戶端日志還有業(yè)務(wù)函數(shù)相關(guān)的日志,我們將所有的日志全部下沉到日志系統(tǒng),為用戶提供統(tǒng)一查詢的能力,以及鏈路拓撲全鏈路日志等日志分析的能力,幫助業(yè)務(wù)在遇到問題時更快速排查問題。
PaaS 平臺同時為我們提供了灰度發(fā)布的能力,灰度發(fā)布的策略主要有流量百分比,還有一些自定義的條件。通過流量百分比還有自定義條件,業(yè)務(wù)可以實現(xiàn)比如平滑發(fā)布、AB 測試等靈活的灰度方式。平滑發(fā)布可以幫助我們在日常發(fā)布的過程中保障服務(wù)整體可用性。
前端交付實踐
下面來看兩個業(yè)務(wù)案例,看一看我們?yōu)闃I(yè)務(wù)實際解決了哪些具體的問題。
**案例?:流量波動較大的服務(wù) **
首先第一個案例是一個流量波動比較大的服務(wù),這個服務(wù)提供的是 SSR 頁面和 API 服務(wù),業(yè)務(wù)的特點是平時流量比較小,在高峰的時候流量突然增加,QPS 最高和最低差距能達到 30 倍以上,這是一個一體化的漏斗服務(wù),部署在我們傳統(tǒng)的容器當中,需要我們開發(fā)者去維護機器。業(yè)務(wù)面臨的痛點主要有三個:
服務(wù)器的成本比較高
運維成本比較高
應急響應不及時
我們?yōu)闃I(yè)務(wù)提供了一個低成本的遷移方式,主要思路是在平臺側(cè)提供一個 Web 適配器的能力,來解決傳統(tǒng)架構(gòu)和 Serverless 架構(gòu)的差異點,使傳統(tǒng)架構(gòu)更平滑過渡到 Serverless 架構(gòu)當中來,后面逐步引導新的需求甚至原有的服務(wù)慢慢遷移到標準的 Serverless 架構(gòu)下。業(yè)務(wù)經(jīng)過了一些適配和改造,最終接入到了我們 Serverless 架構(gòu),并帶來了一些改變。首先實例是可以自動伸縮的,通過自動擴容、定時擴容,可以應對流量高峰場景;其次是有全面的監(jiān)控能力,包括系統(tǒng)、流量、性能監(jiān)控等監(jiān)控數(shù)據(jù)會有一站式的解決方案。體現(xiàn)在收益上有以下幾個方面:
服務(wù)器成本降低:資源利用率由 10% 提升到 35% 以上;
運維成本降低:一站式監(jiān)控,遷移后零運維;
應急響應:秒級發(fā)布、實例異常自動隔離,系統(tǒng)層面的緊急情況由平臺承擔。
案例?:低頻訪問 SSR??場景
我們看一下案例 2,這是一個訪問 SSR 頁面的場景,業(yè)務(wù)已經(jīng)由傳統(tǒng)的架構(gòu)遷移到我們的 Serverless 架構(gòu),但仍然面臨著一些問題。它的業(yè)務(wù)特點是:
頁面粒度部署
日常流量較小
流量有波峰波谷
業(yè)務(wù)的痛點主要有兩個,首先是因為隔離性比較差,所有的頁面全部部署在一個沙箱之內(nèi),之間的穩(wěn)定性相互影響。第二個痛點是發(fā)布回滾耦合在一起,整體的發(fā)布時間比較長。業(yè)務(wù)針對這些痛點做了一些演進,每個頁面部署在一個沙箱之內(nèi),同時每個頁面需要一個實例,原來是僅需要一個實例,現(xiàn)在是需要更多的實例來承擔同樣的服務(wù)。體現(xiàn)在收益上,因為頁面間做到了沙箱的隔離,在發(fā)布效率上有所提升。這時候業(yè)務(wù)面臨一個新的痛點,就是整體的資源利用率比較低,大約是在 10%。最終針對于業(yè)務(wù)這種情況,我們?yōu)闃I(yè)務(wù)提供了合并部署的方式,將業(yè)務(wù)演進為多頁面每個頁面部署在一個沙箱當中,這些沙箱部署在一個實例之內(nèi),將業(yè)務(wù)原有的發(fā)布 / 回滾時長的 10 分鐘級別,降低到了發(fā)布只需要五秒,回滾只需要 0 秒,頁面間原來是耦合的,現(xiàn)在依然可以做到沙箱的隔離。
在這個業(yè)務(wù)場景下,我們沉淀了滿足業(yè)務(wù)對隔離性相關(guān)需求的能力:
函數(shù)運行時支持插件能力
業(yè)務(wù)定制 SSR 運行時
支持多框架擴展
冷啟動時間降低
未來規(guī)劃
未來我們首先要提升 Serverless 架構(gòu)下整體的資源利用率,希望將資源利用率推到 65% 以上,這是一個很有挑戰(zhàn)的目標,涉及到我們在穩(wěn)定性保障、穩(wěn)定性能優(yōu)化,以及各個方面的優(yōu)化和提升。其次是繼續(xù)提升我們的研發(fā)效率,在工具建設(shè)還有組件集成上做進一步的努力,來幫助業(yè)務(wù)去做更多的事情,降低業(yè)務(wù)的開發(fā)成本,進而提升業(yè)務(wù)的研發(fā)效率。最后是迎接 Serverless 架構(gòu)下的運維挑戰(zhàn),在 Serverless 架構(gòu)下,當函數(shù)體量比較小的時候,對業(yè)務(wù)來說幾乎是 0 運維的,當我們又把傳統(tǒng)的大應用全部拆分成函數(shù),部署到我們 Serverless 架構(gòu)下,我們需要運維的函數(shù)或者服務(wù)會越來越多,未來一定會有一些挑戰(zhàn),目前我們還在探索 Serverless 架構(gòu)下函數(shù)服務(wù)體量的過程中。