高德Serverless平臺建設及實踐

amap_tech發表於2021-05-28

導讀

高德啟動Serverless建設已經有段時間了,目前高德Serverless業務的峰值早已超過十萬QPS量級,平臺從0到1,QPS從零到超過十萬,成為阿里集團內Serverless應用落地規模最大的BU。這個過程如何實現,遇到過哪些問題?本文將和大家分享高德為何要搞Serverless/Faas,如何做,技術方案是什麼?目前進展以及後續計劃有哪些,希望對感興趣的同學有所幫助。

1. 高德為什麼要搞Serverless

背景原因是高德當年啟動了一個客戶端上雲專案,專案主要目的是為了提升客戶端的開發迭代效率。以前客戶端業務邏輯都在端上,產品需求的變更需要走客戶端發版才能釋出,而客戶端發版需要走各種測試流程,灰度流程,解客戶端崩潰等問題。

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

1.1 目標:客戶端開發模式——端雲一體

雖然開發模式從以前的端開發轉變為現在的雲 + 端開發,開發同學應該還是原來負責相應業務的同學,而大家知道,服務端開發和客戶端開發顯然是有差異的,客戶端開發往往是面向單機模式的開發,服務端開發通常是叢集模式,需要考慮分散式系統的協調、負載均衡,故障轉移降級等各種複雜問題。

如果使用傳統的服務端模式來開發,這個過渡風險就會比較大。Faas很好的解決了這一問題。我們結合高德客戶端現有的xbus框架(一套客戶端上的本地服務註冊、呼叫的框架),擴充套件了xbus-cloud元件,使得雲上的開發就像端上開發一樣,目標是一套程式碼,兩地執行,一套業務程式碼既能在客戶端上執行,也能在服務端上執行。

高德客戶端主要有三個端:iOS、Android、車機(類Linux作業系統)。主要有兩種語言,C++和Node.js。傳統地圖功能:如地圖顯示,導航路徑顯示,導航播報等等,由於需要跨三個端,採用C++語言來開發。地圖導航基礎之上的一些地圖應用功能,如行前、行後卡片,推薦目的地等主要是用Node.js來開發的。

在阿里集團,淘系前端團隊開發了Node.js Faas Runtime。高德客戶端上雲專案,Node.js的部分就採用了現有的淘系的Node.js Runtime,來接入集團的Faas平臺,完成Node.js這部分的一些業務上雲。2020年十一很好的支撐了高德的十一出行節業務。

C++ Faas沒有現有的解決方案,因此我們決定在集團的基礎設施之上做加法,新建C++ Faas基礎平臺,來助力高德客戶端上雲。

1.1.1 端雲一體的最佳實踐關鍵:客戶端和Faas之間的介面抽象

原本客戶端的邏輯移到Faas服務端上來,或者新的需求一部分在Faas服務端上開發,這裡的**成敗關鍵點在於:客戶端和Faas的介面協議定義,也就是Faas的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是雲時代的高階語言

雖然高德已經全面上雲了,但是目前還不是雲時代的終局,目前主要是全面Docker化並上雲,容器方面做了標準化,在規模化,資源利用率方面可以全面享受雲的紅利,但是業務開發模式上基本還和以前一樣,還是一個大型的分散式系統的寫法。

對於研發模式來說還並沒有享受雲的紅利,可以類比為我們現在是在用匯編語言的方式來寫跑在雲上的服務。而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. 技術方案介紹——在集團現有基礎設施之上做加法

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. 業務如何接入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. 我們目前的情況

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的自動彈性擴縮容技術,高德應對各種出行高峰就更從容了。例如每年的10-1出行節,5-1、清明、雙旦、春節的出行高峰,不再需要運維或者業務開發同學在節前提前擴容,節後再縮容了。

高德業務高峰的特點還不同於電商的秒殺場景。出行高峰的流量不是在一秒內突然漲起來的,我們目前利用池化技術實現的秒級彈性的能力,完全能滿足高德的這個業務場景需求。

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

5. 後續計劃

  • FC彈內函式計算使用優化,和FC團隊一起持續優化彈內函式計算的效能、穩定性、使用體驗。用集團內的豐富的大流量業務場景,不斷打磨好C++/Go Faas Runtime,並最終輸出到公有云,普惠數字化轉型浪潮中的更多企業。
  • Dapr落地,解決Outcoming流量去中心化問題,逐步上線一些C++/Go Faas,使用Dapr的方式呼叫集團中介軟體。
  • Faas混沌工程,故障演練,逃生能力建設。Faas在新財年也會參與我們BU的故障演練,逐一解決演練過程中發現的問題。
  • 接入邊緣計算。端雲一體的場景下,Faas + 邊緣計算,能提供更低的延時,更好的使用者體驗。

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

歡迎對Serverless、雲原生、或者Go應用開發感興趣的小夥伴,想一起做點事情的同學來加入我們(不管之前是什麼技術棧,英雄不問出處,投簡歷到 gdtech@alibaba-inc.com,郵件主題為:姓名-技術方向-來自高德技術),這裡有大規模的落地場景和簡單開放的技術氛圍。歡迎自薦或推薦。

相關文章