高德 Serverless 平臺建設及實踐

作者 | 鄧學祥(祥翼)

本文整理自阿里巴巴高級技術專家 -- 祥翼在【阿里雲 Serverless Developer Meetup 上海站】上的分享。

**導讀:**高德從 FY21 財年開始啓動 Serverless 建設,至今一年了,高德 Serverless 業務的峯值超過十萬 qps 量級,平臺從 0 到 1,qps 從零到十萬,成爲阿里集團內 Serverless 應用落地規模最大的 BU,這中間的過程是怎麼樣的?遇到過哪些問題?高德爲什麼要搞 Serverless/Faas?是如何做 Serverless/Faas 的?技術方案是什麼樣的?目前進展怎麼樣?後續又有哪些計劃?本文將和大家做一個簡單的分享。

Why - 高德爲什麼要搞 Serverless

高德爲什麼要搞 Serverless?背景原因是高德 FY21 財年啓動了一個客戶端上雲項目。客戶端上雲項目的主要目的是爲了提升客戶端的開發迭代效率。

以前客戶端業務邏輯都在端上,產品需求的變更需要走客戶端發版才能發佈,而客戶端發版需要走各種測試流程、灰度流程,解決客戶端崩潰等問題,目前的節奏是一個月一個版本。

客戶端上雲之後,某些易變的業務邏輯放到雲上來。新的產品需求在雲端來開發,不用走月度的版本發佈,加快了需求的開發迭代效率,離產研同頻的理想目標又近了一步(爲什麼要說 “又”,是因爲高德之前也做了一些優化往產研同頻的方向努力,但是我們希望雲端一體化開發可以是其中最有效的一個技術助力)。

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 基礎平臺,來助力高德客戶端上雲。

原本客戶端的邏輯移到 Faas 服務端上來,或者新的需求一部分在 Faas 服務端上開發,這裏的成敗關鍵點在於:客戶端和 Faas 的接口協議定義,也就是 Faas 的 API 定義,好的 API 定義除了對系統的可維護性有好處以外,對後續支撐業務的迭代開發也很重要,好的 API 定義請參考谷樸大神的文檔:《API 設計最佳實踐的思考》。

理想情況下:客戶端做成一個解析 Faas 返回結果數據的一個瀏覽器。瀏覽器協議一旦定義好,就不會經常變換,你看 IE、Chrome 就很少更新。

當然我們的瀏覽器會複雜一些,它是地圖瀏覽器。如何檢驗客戶端和 Faas 之間的接口定義好不好,可以看後續的產品需求迭代,如果有些產品需求迭代只需要在 Faas 上完成,不需要客戶端的任何修改,那麼這個接口抽象就是成功的。

2. BFF 層開發提效

提到高德,大家首先想到的應該是其工具屬性:高德是一個導航工具(這個說法現在已經不太準確了,因爲高德這幾年在做工具化往平臺化的轉型,我們要做萬能的高德,高德的交易類業務正在興起,高德打車、門票、酒店等業務發展很迅猛)。

針對高德導航來說,相比集團其他業務(如電商)來說,有大量的只讀場景是高德業務的一大技術特點。這些只讀場景裏,大量的需求是 BFF(Backend For Frontend)類型的只讀場景。爲什麼這麼說?因爲導航的最核心功能,例如 routing、traffic、eta 等都是相對穩定的,這部分的主要工作在持續不斷地優化算法,使得高德的交通更準,算出的路徑更優。這些核心功能在接口和功能上都是相對比較穩定的,而前端需求是多變的,例如增加個路徑上的限寬墩提示等。

Faas 特別適合做 BFF 層開發,在 Faas 上調用後端相對穩定的各個 Baas 服務,Faas 服務來做數據和調用邏輯封裝、快速開發、發佈。在業界,Faas 用的最多的場景也正是 BFF 場景(另外一個叫法是 SFF 場景,service for frontend)。

3. Serverless 是雲時代的高級語言

FY21,高德是集團內第一個全面上雲的 BU,雖然高德已經全面上雲了,但是這還不是雲時代的終局,目前主要是全面 pouch 化並上雲,容器方面做了標準化,在規模化、資源利用率方面可以全面享受雲的紅利,但是業務開發模式上基本上還和以前一樣,仍是一個大型的分佈式系統的寫法。對於研發模式來說還並沒有享受雲的紅利,可以類比爲我們現在是在用匯編語言的方式來寫跑在雲上的服務。而 Serverless、雲原生可以理解爲雲時代的高級語言,真正做到了 Cloud as a computer,只需要關注於業務開發,不需要考慮大型分佈式系統的各種複雜性。

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 場景。

How - 技術方案介紹

1. 整體技術架構

上文講了我們爲什麼要做這個事情,接下來講我們具體是怎麼做這個事情的,是如何實現的,具體的技術方案是什麼樣的。

本着在集團現有的基礎設施、現有的中間件基礎之上做加法的思想,我們和 CSE、阿里雲 FC 函數計算團隊合作共建,開發了 C++ Faas Runtime 和 Go Faas Runtime。整體和集團拉通的技術架構如下圖所示,主要分爲研發態、運行態、運維態三個部分。

先說運行態,業務流量從我們網關進來,調用到 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。

再來看研發態,運行態決定函數是如何運行的,研發態關注函數的開發體驗,如何方便地讓開發者開發、調試、部署、測試一個函數。

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 等。

最後來看函數的運維監控,runtime 內部集成了鷹眼、sunfire 採集日誌的功能,runtime 裏面會寫這些日誌,通過 sidecar 裏的 agent 採集到鷹眼、或者 sunfire 監控平臺上去(FC 是通過 SLS 來採集的)之後,就能使用集團現有的監控平臺來做 Faas 的監控了,也能接入集團的 GOC 報警平臺。

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 監控界面:

dapr 架構如下圖所示,具體可以參考官方文檔:https://dapr.io/

runtime 裏以前調用中間件是通過 rsocket 方式來調用的,這裏 rsocket broker 會有一箇中心化問題,爲了解決 outgoing 流量去中心化問題,和集團中間件團隊合作引入了 dapr 架構。只是 runtime 層面集成了 dapr,對於用戶 Faas 來說無感知,不需要關心具體調用中間件是通過 rsocket 調用的還是通過 dapr 調用的。後面 runtime 調用中間件切換到 dapr 之後,用戶 Faas 也是不需要做任何修改的。

How - 業務如何接入 Serverless

如前文所述,接入統一在 Aone 上接入。提供了 C++ Faas/Go Faas 的接入文檔。提供了函數的 example 代碼庫,代碼庫有各種場景的示例,包括調用集團各種中間件的代碼示例。C++ Faas/Go Faas 的接入對整個集團開發,目前已經有一些高德以外的 BU,在自己的業務中落地了 C++ /Go Faas。Node.js Faas 使用淘寶提供的 runtime 和模板來接入,Java Faas 使用阿里雲 FC 提供的 runtime 和模板來接入就可以了。

1. 接入規範 - 穩定性三板斧:可監控、可灰度、可回滾

針對落地新技術大家可能擔心的穩定性問題,我們的應對法寶是阿里集團的穩定性三板斧:可監控、可灰度、可回滾。建立 Faas 鏈路保障羣,拉通上下游各相關業務方、基礎平臺一起,按照集團的 1-5-10 要求,共同努力做到 1 分鐘之內響應線上報警、快速排查;5 分鐘之內處理;10 分鐘之內恢復。

爲了規範接入過程,避免犯錯誤引發線上故障,我們制定了 Faas 接入規範和 checkList,來幫助業務方快速使用 Faas。

可監控、可灰度、可回滾是硬性要求,除此之外,業務方如果能做到可降級就更好了。我們的 C++ 客戶端上雲業務,在開始試點階段,就做好了可降級的準備,如果調用 Faas 端失敗,本次調用將會自動降級到本地調用。基本對客戶端功能無損,只是會增加一些響應延遲,另外客戶端上該功能的版本,可能會比服務端稍微老一點,但是功能是向前兼容的,基本不影響客戶端使用。

Now - 我們目前的情況

1. 基礎平臺建設情況

2. 高德的 Serverless 業務落地情況

C++ Faas 和 Go Faas 以及 Node.js Faas 在高德內部已經有大量的應用落地。舉幾個例子:

上圖中的前兩個圖是 C++ Faas 開發的業務:長途天氣、沿途搜。後兩個截圖是 Go-Faas 開發的業務:導航 tips、足跡地圖。

高德是阿里集團內 Serverless 應用落地規模最大 的 BU,已落地的 Serverless 應用,日常峯值超過十萬 qps 量級。

3. 主要收益

高德落地了集團內規模最大的 Serverless 應用之後,都有哪些收益呢?

首先第一個最重要的收益是:開發提效。我們基於 Serverless 實現的端雲一體組件,助力了客戶端上雲,解除了需要實時的客戶端發版依賴問題,提升了客戶端的開發迭代效率。基於 Serverless 開發的 BFF 層,提升了 BFF 類場景的開發迭代效率。

第二個收益是:運維提效。利用 Serverless 的自動彈性擴縮容技術,高德應對各種出行高峯就更從容了。例如每年的十一出行節、五一、清明、春節的出行高峯,不再需要運維或者業務開發同學在節前提前擴容,節後再縮容了。高德業務高峯的特點還不同於電商的秒殺場景。出行高峯的流量不是在 1 秒內突然漲起來的,我們目前利用池化技術實現的秒級彈性的能力,完全能滿足高德的這個業務場景需求。

第三個收益是:降低成本。高德的業務特點,白天流量大、夜間流量低,高峯值和低谷值差異較大,時間段區分明顯。利用 Serverless 在夜間流量低峯時自動縮容技術,極大地降低了服務器資源的成本。

Next - 後續計劃

以上要做的事情任重道遠,另外 FY22 財年我們部門還會做雲原生的試點和落地。技術同學都知道,從技術選型、技術原型到實際業務落地,這之間還有很長的路要走。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/bFcrWYMWSuZUI1FWEVuI0Q