做者 | 鄧學祥(祥翼) 來源 | Serverless 公衆號前端
高德從 FY21 財年開始啓動 Serverless 建設,至今一年了,高德 Serverless 業務的峯值超過十萬 qps 量級,平臺從 0 到 1,qps 從零到十萬,成爲阿里集團內 Serverless 應用落地規模最大的 BU,這中間的過程是怎麼樣的?遇到過哪些問題?高德爲何要搞 Serverless/Faas?是如何作 Serverless/Faas 的?技術方案是什麼樣的?目前進展怎麼樣?後續又有哪些計劃?本文將和你們作一個簡單的分享。android
1. Why-高德爲何要搞 Serverless
高德爲何要搞 Serverless?背景緣由是高德 FY21 財年啓動了一個客戶端上雲項目。客戶端上雲項目的主要目的是爲了提高客戶端的開發迭代效率。算法
之前客戶端業務邏輯都在端上,產品需求的變動須要走客戶端發版才能發佈,而客戶端發版須要走各類測試流程、灰度流程,解決客戶端崩潰等問題,目前的節奏是一個月一個版本。後端
客戶端上雲以後,某些易變的業務邏輯放到雲上來。新的產品需求在雲端來開發,不用走月度的版本發佈,加快了需求的開發迭代效率,離產研同頻的理想目標又近了一步(爲何要說「又」,是由於高德以前也作了一些優化往產研同頻的方向努力,可是咱們但願雲端一體化開發能夠是其中最有效的一個技術助力)。瀏覽器
1.1 目標:客戶端開發模式--端雲一體
雖然開發模式從之前的端開發轉變爲如今的雲 + 端開發,開發同窗應該仍是原來負責相應業務的同窗,可是你們知道,服務端開發和客戶端開發顯然是有差別的,客戶端開發是面向單機模式的開發,服務端開發一般是集羣模式,須要考慮分佈式系統的協調、負載均衡、故障轉移降級等各類複雜問題。若是使用傳統的服務端模式來開發,這個過渡風險就會比較大。性能優化
Faas 很好地解決了這一問題。咱們結合高德客戶端現有的 xbus 框架(一套客戶端上的本地服務註冊、調用的框架),擴展了 xbus-cloud 組件,使得雲上的開發就像端上開發同樣,目標是一套代碼、兩地運行,一套業務代碼既能在客戶端上運行,也能在服務端上運行。服務器
高德客戶端主要有三個端:IOS、android、車機(類 Linux 操做系統)。主要有兩種語言:C++ 和 Node.js。傳統地圖功能:如地圖顯示、導航路徑顯示、導航播報等等,因爲須要跨三個端,採用的 C++ 語言來開發。地圖導航基礎之上的一些地圖應用功能,如行前/行後卡片、推薦目的地等,主要用 Node.js 來開發。架構
FY20 財年淘系前端團隊開發了 Node.js Faas runtime。高德客戶端上雲項目,Node.js 的部分就採用了現有的淘系的 Node.js runtime,來接入集團的 Faas 平臺,完成 Node.js 這部分的一些業務上雲。2020 年十一期間很好地支撐了高德的十一出行節業務。併發
C++ Faas 沒有現有的解決方案,所以咱們決定在集團的基礎設施之上作加法,新建 C++ Faas 基礎平臺,來助力高德客戶端上雲。app
1.1.1 端雲一體的最佳實踐關鍵:客戶端和 Faas 之間的接口抽象
本來客戶端的邏輯移到 Faas 服務端上來,或者新的需求一部分在 Faas 服務端上開發,這裏的成敗關鍵點在於:客戶端和 Faas 的接口協議定義,也就是 Faas 的 API 定義,好的 API 定義除了對系統的可維護性有好處之外,對後續支撐業務的迭代開發也很重要,好的 API 定義請參考谷樸大神的文檔:《API 設計最佳實踐的思考》。
理想狀況下:客戶端作成一個解析 Faas 返回結果數據的一個瀏覽器。瀏覽器協議一旦定義好,就不會常常變換,你看 IE、Chrome 就不多更新。固然咱們的這個瀏覽器會複雜一些,咱們這個瀏覽器是地圖瀏覽器。如何檢驗客戶端和 Faas 之間的接口定義好很差,能夠看後續的產品需求迭代,若是有些產品需求迭代只須要在 Faas 上完成,不須要客戶端的任何修改,那麼這個接口抽象就是成功的。
1.2 BFF 層開發提效
提到高德,你們首先想到的應該是其工具屬性:高德是一個導航工具(這個說法如今已經不太準確了,由於高德這幾年在作工具化往平臺化的轉型,咱們要作萬能的高德,高德的交易類業務正在興起,高德打車、門票、酒店等業務發展很迅猛)。
針對高德導航來講,相比集團其餘業務(如電商)來講,有大量的只讀場景是高德業務的一大技術特色。這些只讀場景裏,大量的需求是 BFF(Backend For Frontend)類型的只讀場景。爲何這麼說?由於導航的最核心功能,例如 routing、traffic、eta 等都是相對穩定的,這部分的主要工做在持續不斷地優化算法,使得高德的交通更準,算出的路徑更優。這些核心功能在接口和功能上都是相對比較穩定的,而前端需求是多變的,例如增長個路徑上的限寬墩提示等。
Faas 特別適合作 BFF 層開發,在 Faas 上調用後端相對穩定的各個 Baas 服務,Faas 服務來作數據和調用邏輯封裝、快速開發、發佈。在業界,Faas 用的最多的場景也正是 BFF 場景(另一個叫法是 SFF 場景,service for frontend)。
1.3 Serverless 是雲時代的高級語言
FY21,高德是集團內第一個全面上雲的 BU,雖然高德已經全面上雲了,可是這還不是雲時代的終局,目前主要是全面 pouch 化並上雲,容器方面作了標準化,在規模化、資源利用率方面能夠全面享受雲的紅利,可是業務開發模式上基本上還和之前同樣,還是一個大型的分佈式系統的寫法。對於研發模式來講還並無享受雲的紅利,能夠類比爲咱們如今是在用匯編語言的方式來寫跑在雲上的服務。而 Serverless、雲原生能夠理解爲雲時代的高級語言,真正作到了 Cloud as a computer,只須要關注於業務開發,不須要考慮大型分佈式系統的各類複雜性。
1.4 Go-Faas 補充 Go 語言生態
前面講到了由於客戶端上雲項目,咱們在阿里雲 FC(函數計算)團隊之上作加法,開發了 C++ Faas Runtime。不只如此,咱們還開發了 Go-Faas,咱們爲何會作 Go-Faas 呢?這裏也簡單介紹一下背景,高德服務端 Go 部分的 qps 峯值已超百萬。高德已補齊了阿里各中間件的 Go 客戶端,和集團中間件部門共建。可觀測性、自動化測試體系也基本完善,目前 Go 生態已基本完善。補齊了 Go-Faas 以後,咱們就既能用 Go 寫 Baas 服務,又能用 Go 寫 Faas 服務了,在不一樣的業務場景採用不一樣的服務實現方式,Go-Faas 主要應用於上文提到的 BFF 場景。
2. How-技術方案介紹:在集團現有基礎設施之上作加法
2.1 總體技術架構
上文講了咱們爲何要作這個事情,接下來說咱們具體是怎麼作這個事情的,是如何實現的,具體的技術方案是什麼樣的。
本着在集團現有的基礎設施、現有的中間件基礎之上作加法的思想,咱們和 CSE、阿里雲 FC 函數計算團隊合做共建,開發了 C++ Faas Runtime 和 Go Faas Runtime。總體和集團拉通的技術架構以下圖所示,主要分爲研發態、運行態、運維態三個部分。
2.1.1 運行態
先說運行態,業務流量從咱們網關進來,調用到 FC API Server,轉發到 C++/Go Faas Runtime,runtime 來完成用戶函數裏的功能。runtime 的架構本文下一章節會具體介紹。
和 runtime container 一塊兒部署的有監控、日誌、Dapr 各類 side car,side car 來完成各類日誌採集上報功能,dapr side car 來完成調用集團中間件的功能。
另外目前 dapr 還在試點的階段,調用中間件主要是經過 Broker 和各個中間件 proxy 來完成,中間件調用的有HSF、Tair、metaq、diamond 等中間件 proxy。
最後 Autoscaling 模塊來管理函數實例的擴縮容,達到函數自動伸縮的目的。這裏的調度就有各類策略了,有根據請求併發量的調度、函數實例的 CPU 使用率的調度。也能提早設置預留實例數,避免縮容到 0 以後的冷啓動問題。
底層調用的是集團 ASI 的能力,ASI 能夠簡單理解爲集團的 K8S+ sigma(集團的調度系統),最終的部署是 FC 調用 ASI 來完成函數實例部署,彈性伸縮的,部署的最小單位是上圖中的 pod,一個 pod 裏包含 runtime container 和 sidecar set container。
2.1.2 研發態
再來看研發態,運行態決定函數是如何運行的,研發態關注函數的開發體驗,如何方便地讓開發者開發、調試、部署、測試一個函數。
C++ Faas 有個跨平臺的難點問題,C++ Faas runtime 裏有一些依賴庫,這些依賴庫沒有 Java 依賴庫管理那麼方便。這樣依賴庫的安裝比較麻煩,Faas 腳手架就是爲了解決這個問題,調用腳手架,一鍵生成 C++ Faas 示例工程,安裝好各類依賴包。爲了本地能方便地 debug,開發了一個 C++ Faas Runtime Boot 模塊,函數 runtime 啓動入口在 boot 模塊裏,boot 模塊裏集成 runtime 和用戶 Faas 函數,能夠對 runtime 來作 debug 單步調試。
咱們和集團 Aone 團隊合做,函數的發佈集成到 Aone 環境上了,能夠很方便地在 Aone 上來發布 Go 或者 C++ Faas,Aone 上也集成了一鍵生成 example 代碼庫的功能。
C++ 和 Go Faas 的編譯都依賴相應的編譯環境,Aone 提供了自定義編譯鏡像的功能,咱們上傳了編譯鏡像到集團的公共鏡像庫,函數編譯時,在函數的代碼庫裏指定相應的編譯鏡像,編譯鏡像裏安裝了 Faas 的依賴庫、SDK等。
2.1.3 運維態
最後來看函數的運維監控,runtime 內部集成了鷹眼、sunfire 採集日誌的功能,runtime 裏面會寫這些日誌,經過 sidecar 裏的 agent 採集到鷹眼、或者 sunfire 監控平臺上去(FC 是經過 SLS 來採集的)以後,就能使用集團現有的監控平臺來作 Faas 的監控了,也能接入集團的 GOC 報警平臺。
2.2 C++/Go Faas Runtime 架構
上面講的是和 Aone、FC/CSE、ASI 集成的一個總體架構,Runtime 是這個總體架構的一部分,下面具體講講 Runtime 的架構是怎樣的,Runtime 是如何設計和實現的。
最上面部分的用戶 Faas 代碼只須要依賴 Faas SDK 就能夠了,用戶只須要實現 Faas SDK 裏的 Function 接口就能寫本身的 Faas 了。而後若是須要調用外部系統,能夠經過 SDK 裏的 Http Client 來調用,若是要調用外部中間件,經過 SDK 裏的 Diamond/Tair/HSF/metaq Client 來調用中間件就能夠。SDK 裏的這些接口屏蔽了底層實現的複雜性,用戶不須要關心這些調用最後是如何實現,不須要關心 runtime 的具體實現。
SDK 層就是上面提到的 Function 定義和各類中間件調用的接口定義。SDK 代碼是開發給 Faas 用戶的。SDK 作的比較輕薄,主要是接口定義,不包含具體的實現。調用中間件的具體實如今 Runtime 裏有兩種實現方式。
往下是 Runtime 的一個總體架構。Starter 是 runtime 的啓動模塊,啓動以後,runtime 自身是一個 Server,啓動的時候根據 Function Config 模塊的配置來啓動 runtime,runtime 啓動以後開啓請求和管理監聽模式。
再往下是 Service 層,實現 SDK 裏定義的中間件調用的接口,包含 RSocket 和 dapr 兩種實現方式,RSocket 是經過 RSocket broker 的模式來調用中間件的,runtime 裏集成了 dapr(distributed application runtime),調用中間件也能夠經過 dapr 來調用,在前期 dapr 試點階段,若是經過 dapr 調用中間件失敗了,會降級到 rsocket 的方式來調用中間件。
再往下就是 rsocket 的協議層,封裝了調用 rsocket 的各類 metadata 協議。dapr 調用是經過 grpc 方式來調用的。
最下面一層就是集成了 rsocket 和 dapr 了。
rsocket 調用還涉及到 broker 選擇的問題,upstream 模塊來管理 broker cluster、broker 的註冊反註冊、keepalive 檢查等等,LoadBalance 模塊來實現 broker 的負載均衡選擇以及事件管理、鏈接管理、重連等等。
最後 runtime 裏的 metrics 模塊負責鷹眼 trace 的接入,經過 filter 模式來攔截 Faas 鏈路的耗時,並輸出鷹眼日誌。打印 sunfire 日誌,供 sidecar 去採集。下圖是一個實際業務的 sunfire 監控界面:
2.2.1 Dapr
dapr 架構以下圖所示,具體能夠參考官方文檔。
runtime 裏之前調用中間件是經過 rsocket 方式來調用的,這裏 rsocket broker 會有一箇中心化問題,爲了解決 outgoing 流量去中心化問題,和集團中間件團隊合做引入了 dapr 架構。只是 runtime 層面集成了 dapr,對於用戶 Faas 來講無感知,不須要關心具體調用中間件是經過 rsocket 調用的仍是經過 dapr 調用的。後面 runtime 調用中間件切換到 dapr 以後,用戶 Faas 也是不須要作任何修改的。
3. How-業務如何接入 Serverless
如前文所述,接入統一在 Aone 上接入。提供了 C++ Faas/Go Faas 的接入文檔。提供了函數的 example 代碼庫,代碼庫有各類場景的示例,包括調用集團各類中間件的代碼示例。C++ Faas/Go Faas 的接入對整個集團開發,目前已經有一些高德之外的 BU,在本身的業務中落地了 C++ /Go Faas。Node.js Faas 使用淘寶提供的 runtime 和模板來接入,Java Faas 使用阿里雲 FC 提供的 runtime 和模板來接入就能夠了。
3.1 接入規範-穩定性三板斧:可監控、可灰度、可回滾
針對落地新技術你們可能擔憂的穩定性問題,咱們的應對法寶是阿里集團的穩定性三板斧:可監控、可灰度、可回滾。創建 Faas 鏈路保障羣,拉通上下游各相關業務方、基礎平臺一塊兒,按照集團的 1-5-10 要求,共同努力作到 1 分鐘以內響應線上報警、快速排查;5 分鐘以內處理;10 分鐘以內恢復。
爲了規範接入過程,避免犯錯誤引起線上故障,咱們制定了 Faas 接入規範和 checkList,來幫助業務方快速使用 Faas。
可監控、可灰度、可回滾是硬性要求,除此以外,業務方若是能作到可降級就更好了。咱們的 C++ 客戶端上雲業務,在開始試點階段,就作好了可降級的準備,若是調用 Faas 端失敗,本次調用將會自動降級到本地調用。基本對客戶端功能無損,只是會增長一些響應延遲,另外客戶端上該功能的版本,可能會比服務端稍微老一點,可是功能是向前兼容的,基本不影響客戶端使用。
4. Now-咱們目前的狀況
4.1 基礎平臺建設狀況
- Go/C++ Faas Runtime 開發完成,對接 FC-Ginkgo/CSE、Aone 完成,已發佈穩定的 1.0 版本。
- 作了大量的穩定性建設、優雅下線、性能優化、C 編譯器優化,使用了阿里雲基礎軟件部編譯器優化團隊提供的編譯方式來優化 C++ Faas 的編譯,性能提高明顯。
- C++/Go Faas 接入鷹眼、sunfire 監控完成,函數具有了可觀測性。
- 池化功能完成,具有秒級彈性的能力。池化 runtime 鏡像接入 CSE,擴一個新實例的時間由原來的分鐘級變爲秒級。
4.2 高德的 Serverless 業務落地狀況
C++ Faas 和 Go Faas 以及 Node.js Faas 在高德內部已經有大量的應用落地。舉幾個例子:
上圖中的前兩個圖是 C++ Faas 開發的業務:長途天氣、沿途搜。後兩個截圖是 Go-Faas 開發的業務:導航 tips、足跡地圖。
高德是阿里集團內 Serverless 應用落地規模最大 的BU,已落地的 Serverless 應用,平常峯值超過十萬 qps 量級。
4.3 主要收益
高德落地了集團內規模最大的 Serverless 應用以後,都有哪些收益呢?
首先第一個最重要的收益是:開發提效。咱們基於 Serverless 實現的端雲一體組件,助力了客戶端上雲,解除了須要實時的客戶端發版依賴問題,提高了客戶端的開發迭代效率。基於 Serverless 開發的 BFF 層,提高了 BFF 類場景的開發迭代效率。
第二個收益是:運維提效。利用 Serverless 的自動彈性擴縮容技術,高德應對各類出行高峯就更從容了。例如每一年的十一出行節、五1、清明、春節的出行高峯,再也不須要運維或者業務開發同窗在節前提早擴容,節後再縮容了。高德業務高峯的特色還不一樣於電商的秒殺場景。出行高峯的流量不是在 1 秒內忽然漲起來的,咱們目前利用池化技術實現的秒級彈性的能力,徹底能知足高德的這個業務場景需求。
第三個收益是:下降成本。高德的業務特色,白天流量大、夜間流量低,高峯值和低谷值差別較大,時間段區分明顯。利用 Serverless 在夜間流量低峯時自動縮容技術,極大地下降了服務器資源的成本。
5. Next-後續計劃
- FC 彈內函數計算使用優化,和 FC 團隊一塊兒持續優化彈內函數計算的性能、穩定性、使用體驗。用集團內豐富的大流量業務場景,來不斷打磨好 C++/Go Faas Runtime,並最終輸出到公有云,普惠數字化轉型浪潮中的更多企業。
- Dapr 落地,解決 outcoming 流量去中心化問題,逐步上線一些 C++/Go Faas,使用 Dapr 的方式調用集團中間件。
- Faas 混沌工程,故障演練,逃生能力建設。Faas 在新財年也會參與咱們 BU 的故障演練,逐一解決演練過程當中發現的問題。
- 接入邊緣計算。端雲一體的場景下,Faas + 邊緣計算,能提供更低的延時,更好的用戶體驗。
以上要作的事情任重道遠,另外 FY22 財年咱們部門還會作雲原生的試點和落地。技術同窗都知道,從技術選型、技術原型到實際業務落地,這之間還有很長的路要走。