[譯]伯克利談serverless:過去,現在和未來

Lumin發表於2019-04-11

本文是Cloud Programming Simplified: A Berkerley View on Serverless Computing一文的中文閱讀筆記,並非權威翻譯,僅供個人學習參考

譯者序

2018年伊始,serverless計算的概念突然在雲端計算領域火了起來,如今它對我們來說已經不再是一個陌生的名詞。儘管serverless目前仍然沒有一個明確的定義和規範,但已經有無數的廠商和機構開始大力投入此領域並取得了一些成功(比如現在風靡一時的FaaS)。不可否認的是,隨著逐漸的發展和完善,serverless必將成為未來雲端計算的主流趨勢,我們也有充足的理由相信,它會給開發領域注入全新的血液,成為通向雲時代的階梯。

2019年2月,加州大學伯克利分校發表了這篇名為《Cloud Programming Simplified: A Berkerley View on Serverless Computing》的論文,對serverless的形成、現狀以及未來進行了全面的梳理和總結,藉著研讀的過程我將它翻譯成了中文,希望能夠幫助到更多對serverless感興趣的朋友。翻譯水準有限,如有勘誤還請指正。

1. Serverless計算簡介

早在2009年,伯克利曾針對當時興起的雲端計算做過評論,並提出了以下6個潛在的優點:

  1. (理論上)無限可用的計算資源
  2. 使用者再也不需要承擔伺服器運維的工作和責任
  3. 服務的按需付費成為可能
  4. 超大型資料中心的使用成本顯著降低
  5. 通過視覺化資源管理,運維操作的難度大大降低
  6. 得益於分時複用,物理硬體的利用率大大提高

2009年至今的10年裡,雲端計算領域已經有了很大的發展,上述的諸多優勢已經成為現實,但最後兩點目前的實現仍然不夠優秀,使得大部分的雲服務使用者不得不承受複雜的運維成本和較低的硬體使用率。

當時,市場上主流的兩種雲服務方案分別是亞馬遜推出的EC2和谷歌推出的App Engine (GAE)。這兩種方案分別代表了兩種思路,EC2選擇了提供底層基礎,它的例項使用起來和一臺物理伺服器十分類似,沒有任何的額外功能,你可以在上面執行任何型別、任何語言的服務;相反的,GAE則選擇了提供高層抽象,包括令人印象深刻的自動縮擴容等能力,但同時對使用者能夠執行的程式碼做出了限制 —— 要想獲得這些特性,就必須使用google提供的儲存和計算服務,遵循相應的規範。

最終,市場選擇了擁抱EC2這種底層硬體的虛擬方案,這主要是因為開發者們傾向於使用和自己本地開發環境相同的環境來執行服務,這樣做,開發好的程式碼基本不需要什麼改動就可以輕易部署到雲例項上去。

但這樣的決定也帶來了負面影響,採用底層硬體虛擬的方案意味著所有的運維操作都要由開發人員自己來解決,並且為了保證執行在雲上的服務具有足夠的穩定性,需要解決很多的問題,比如下面列出的這些:

  1. 提供冗餘容錯能力,保證一臺機器出現故障時不會影響到整個服務
  2. 異地容災和備份機制
  3. 能夠有效利用硬體資源的負載均衡方案
  4. 響應式地調整服務的規模,實現自動縮擴容
  5. 實時監控服務是否正常執行
  6. 記錄足夠的日誌資訊,方便debug和效能調優
  7. 系統升級問題,包括安全補丁
  8. 能夠快速將服務遷移到新例項的能力

可以看到,上面的每一個問題複雜度都非常高,需要投入大量的人力物力資源才能解決,對於小規模的公司而言,全靠自己來解決這些問題顯然是不可能的。

另一方面,使用基於底層硬體虛擬的方案導致單個服務的開發成本也非常高,打個比方,一個簡單的業務功能,實際實現可能只有幾十行程式碼,但卻需要新增諸多體積龐大的庫和框架(比如rpc、資料中心訪問、快取、監控...)才能夠執行在雲服務例項上,這是嚴重拖慢開發效率的。

注意到這些問題,亞馬遜在2015年推出了AWS Lambda服務,提出了Cloud Function的概念,並引起了業界對於Serverless的廣泛關注(Serverless這一詞並不是說真的沒有伺服器了,只是開發人員不需要再關注伺服器了,你的程式碼仍然是執行在真實存在的伺服器上的)。

Cloud Function最終被平臺打包成**FaaS (Function as a Service, 函式即服務)的形式,它代表著Serverless的核心理念。當然,雲平臺也提供以BaaS (Backend as a Service)**形式存在的Serverless服務框架。簡單的說,Serverless Computing = FaaS + BaaS

以我們的觀點而言,一個serverless應用必須能夠實現自動縮擴容按使用量計費cloud function做到了這一點,因此我們將其視為當今serverless計算的基本元素。在本文剩下的部分中,將會關注和論述cloud function的形成、演化以及未來;進一步會給serverless計算下一個定義,列舉它所面臨的挑戰和機遇。儘管我們還不知道究竟哪種解決方案會取得最終的勝利,但我們相信所有困擾serverless的問題最終都將會被解決,讓這一概念真正成為雲端計算的門面(become the face of cloud computing)。

2. Serverless的形成

對於任何一個serverless平臺而言,使用者都只需要使用高階語言編寫一個cloud function,然後選擇一個觸發該函式執行的觸發器 (trigger)(比如檔案上傳、資料庫的改動等),其餘的工作(例項選擇、縮擴容、部署、容災、監控、日誌、安全補丁...)則全部由serverless系統託管。下面的表格總結了在serverless和傳統雲端計算(我們稱其為serverful)兩種方式的一些區別:

[譯]伯克利談serverless:過去,現在和未來

接著我們給出一張serverless雲的架構圖:

[譯]伯克利談serverless:過去,現在和未來

從上圖中可以看出serverless是如何簡化應用的開發流程和資源使用方式的,在雲平臺的環境下,傳統的serverful開發方式就像是在使用匯編這樣的底層語言,而serverless則像是在使用python這樣的高階語言。換言之,當今serverless帶給我們的提升,正如當年高階語言替代彙編一樣,是一種質的改變。

準確的說,我們認為serverless相比serverful,有以下3個顯著的改變:

  1. 弱化了儲存和計算之間的聯絡。 服務的儲存和計算被分開部署和收費,服務的儲存不再是它本身的一部分,而是演變成了獨立的雲服務,這使得計算變得無狀態化,更容易排程和縮擴容,同時也降低了資料丟失的風險。

  2. 程式碼的執行不再需要手動分配資源。 我們再也不需要為服務的執行指定需要的資源(比如使用幾臺機器、多大的頻寬、多大的磁碟...),只需要提供一份程式碼,剩下的交由serverless平臺去處理就行了

  3. 按使用量計費。 serverless按照服務的使用量(呼叫次數、時長等)進行計費,而不是像傳統的serverful服務那樣,按照使用的資源(ECS例項、VM的規格等)計費。

基於上述的三個改變,接下來我們將解釋serverlss和一些相似的產品究竟有何不同。

2.1 Serverless計算的前生今世

serverless計算到底帶來了什麼技術突破?關於這個問題有不少爭論,許多人認為serverless計算不過是一些已有技術的重組和封裝,只是對一些PaaS產品(如Heroku, Firebase, Parse)的簡單整合歸納。甚至有一部分人認為上世紀90年代非常流行的web host共享技術就已經實現了serverless的功能,比如他們都使用無狀態化的程式設計模型,並且提供多租戶機制。一個典型的例子就是CGI (Common Gateway Interface),它甚至允許你直接部署使用不同語言(Perl或PHP)編寫的指令碼到伺服器上執行。而之前提到的GAE早在serverless概念流行起來的幾年前就提供了相似的功能,但還是遭到了市場的否決,我們憑什麼認為serverless是一種不同於PaaS和其他這些產品的革新呢?

今天使用cloud functions的serverless計算和它的前輩們有著幾個重要的不同,主要體現在:更好的自動縮擴容、強隔離性、平臺靈活度以及服務生態支援上。

以自動縮擴容為例,AWS Lambda提供的自動縮擴容能力和之前存在的類似功能相比拉開了顯著的距離:它能夠更精確地追蹤機器的負載並且快速響應縮擴容,甚至允許縮容到零例項狀態來實現零費用。同時,計費的粒度也精細到了毫秒級別,而不是之前的小時級,現在我們可以說,使用者的服務是真正按照程式碼實際執行的時間來收費的,而不是之前那樣按照需要執行程式碼的資源來收費的了。

serverless所需要的多租戶硬體共享依賴於高效能的安全隔離,目前的主流選擇是VM級隔離,但這裡存在一個問題,就是VM的啟動速度比較慢,不足以支援serverless所需要的彈性縮擴容能力。為了解決這個問題,AWS Lambda使用了兩種VM例項的資源池,一種稱為“預熱池(warm pool)”,僅僅是被分配給對應的租戶(但是不啟動服務),另一種則被稱為“啟用池(active pool)”,它們是之前已經執行過函式服務的例項,並且會一直保持著去服務後續的請求。這些能夠實現硬體高利用率的資源生命週期管理和多租戶打包才是serverless的關鍵技術,使它區別於原有的類似產品。需要一提的是,為了解決多租戶隔離的開支問題,現在也有很多除VM之外的隔離方案,比如使用容器、unikernel、libraryOS、語言虛擬機器(如JVM)等。

除了自動縮擴容和多租戶隔離外,serverless的其他幾個不同點也為它的成功奠定了基礎。相比於針對特定使用場景的PaaS服務,serverless計算所支援的應用範圍要廣泛得多,因為它允許使用者將外部的庫打包進服務,此外,今天的serverless計算的規模比起早起的web host共享技術要也要大得多。

在第1節中我們提過,cloud functions讓serverless這一名詞流行了起來。然而,它們的成功也離不開公有云早期時代出現的BaaS。我們認為這些服務也是serverless計算的一種實現,只不過它們具有一定的領域針對性和高度優化,而cloud functions更加通用化,相關的對比可以參考下面的表格,總結了幾種不同型別服務的程式設計介面和計費模型:

[譯]伯克利談serverless:過去,現在和未來

當我們討論serverless計算的時候經常會被問到一個問題,那就是它和kubernetes的關係。我們認為kubernetes本身不是serverless,相對地,它是一種簡化serverless計算管理的技術。k8s由Google多年的內部沉澱所孕育,正在快速地被大規模應用,它能夠很好地提供一種生命週期很短的計算環境,就像serverless計算一樣,但在諸多方面都有著更少的限制(如硬體資源、執行時間、網路連線等)。只需少量改動,我們也可以在k8s上輕鬆部署那些原本為公有云平臺設計的應用。

從另一個角度來看,serverless計算意味著服務的提供商要解決所有的運維責任,並且要使得多租戶的資源利用盡可能地達到最佳。而目前的一些k8s平臺提供商,如GKE (Google Kubernetes Engine) 和EKS (Amazon Elastic Kubernetes Service) 等提供的是一種介於serverful計算和serverless計算之間的中間產物:他們提供k8s平臺的運維保障,給使用者提供了靈活的容器排程能力,但再上一層級的運維和排程仍然需要開發者自己來承擔。這些k8s服務和serverless計算一個很大的不同點在於計費標準,它們無法做到按實際程式碼的執行次數和時間來收費,而是和serverful計算類似,按照使用的資源數量等收費。

k8s也是一個執行混雜(Hybird)模式應用的好選擇,在這種模式下執行的服務一部分在本地硬體上執行,另一部分則在雲端上執行。從長遠的角度看,隨著雲規模的逐步增大、網路速度的提升和雲服務的擴張,純粹的雲應用最終會成為主流,但在那一天到來前,混雜模式的應用會是一種很好的過渡。

(原文此處還提到了有關邊緣計算的一些觀點,因為不是重點這裡就跳過不譯了,感興趣的可以閱讀原論文)

經過上面的討論,我們定義了什麼是serverless計算,也說明了它和之前那些類似產品的區別,接著我們來探尋為何它能夠如此吸引雲提供商、使用者和研究者們。

2.2 Serverless計算的吸引力

對於雲服務提供商而言,serverless計算能夠給他們帶來商業上的增長。得益於程式設計模型的簡化,serverless計算能夠吸引更多的新客戶,而對於那些已有的客戶,serverless計算使得他們能夠更好地利用雲資源。舉個例子,近期的一項調查發現serverless的使用者群體中,有大約24%是第一次接觸雲端計算,而已經在使用serverful雲端計算的客戶中,有30%的人也同樣使用了serverless計算。另外,serverless計算執行時間短、記憶體使用少以及無狀態的特性讓雲服務提供商很容易找到一些尚未利用的資源來執行它們,這樣就進一步提高了資源利用率。雲服務商甚至可以用一些對於severful雲端計算而言已經“過時”的舊伺服器資源來執行serverless服務,減少成本和開銷。

對於購買雲服務的客戶而言,serverless計算帶來的主要收益是程式設計生產力的提高,以及在許多場景下的支出節省。Jevons paradox指出,即使serverless計算讓客戶變得更有效率,他們也不會因此減少雲的使用率,相反他們會因為使用者數量的增長而更多地使用雲。

serverless還把雲部署從x86機器碼(99%的雲端計算機使用x86指令集)提升到了高階語言層面,作為開發者你無需再關心伺服器上究竟安裝的是什麼執行環境,也不需要擔心從32位編譯器換到64位編譯器帶來的遷移成本 —— serverless系統會幫你解決這些問題,因此應用的架構就有了更多的創新空間。如果ARM或者RISC-V能夠提供比x86更好的表現,serverless計算也可以很方便地替換指令集。雲服務提供商甚至可以增加一些針對特定語言或者領域的優化,來給使用像python這種語言的編寫的程式加速。

雲服務的開發者們會很喜歡serverless計算,對於新手而言,即便完全不理解雲基礎設施如何運作也能快速編寫出可用的程式碼;對於專家而言,serverless節省了他們部署和運維的時間,讓他們能夠更加專注於解決和優化應用本身的問題。下面的表格中給出了目前serverless計算最受歡迎的幾個應用場景

[譯]伯克利談serverless:過去,現在和未來

最後,研究者們之所以被severless計算所吸引,主要是因為cloud functions這種通用目的計算抽象很有希望成為雲端計算的未來,而且就serverless系統的目前還有很多侷限性,優化和改進的空間還非常大,值得進行相關的研究。

3. 當前Serverless計算平臺的侷限性

Serverless Cloud Functions已經被成功應用於很多不同的場景,但仍然有許多場景沒有使用serverless計算,為了探究是什麼阻礙了serverless計算應用於更加廣泛的場景,我們選擇了幾個感興趣的應用,以及一些其他人的研究樣本,嘗試把他們改造成serverless的形式來發現阻礙改造的難點。

在這一部分中,我們挑選了5個用於研究的專案,他們原本都是基於傳統serverful雲端計算的應用,而我們儘可能只使用cloud functions來實現它們的serverless版本,除了最後一個例子 —— Serverless SQLite,FaaS在這方面的支援太過薄弱,因此我們認為資料庫和其他較重規模的有狀態服務將仍然以BaaS的形式存在。

有趣的是,儘管這些應用是我們隨意挑選的,本身並沒有太多的相似點,但在它們身上暴露出的serverless計算的弱點確實相同的,下面就讓我們來看看這些例子。

  1. ExCamera:實時視訊編碼

    ExCamera 是一個給使用者提供實時視訊編碼的服務,用於幫助他們把視訊上傳到Youtbue這樣的網站上。取決於不同的視訊檔案大小,編碼方案可能需要花費數十分鐘甚至數小時的時間。為了能夠實現實時的視訊編碼,ExCamera把編碼過程中比較慢的部分並行化,比較快的部分則繼續使用序列化。ExCamera對外暴露了視訊編碼器和解碼器的介面,使你可以通過呼叫函式的方式來完成相關的任務。

  2. MapReduce

    大資料分析框架,如MapReduce, Hadoop 和 Spark,在傳統方式下都是部署在可控制叢集上的。目前一些純Map相關的任務已經可以執行在serverless計算環境中了,下一步需要支援的就是完整的MapReduce任務。推動這一改進的潛在動力是serverless計算帶來的靈活性,它能夠有效地處理一些資料集大小變化非常明顯的任務,增加資源的利用率。

  3. Numpywren:線性代數

    大規模的線性代數計算過去基本是被部署在由高速網路連線的高效能叢集,或者超算上。基於這樣的歷史背景,serverless計算看起來並不能夠勝任這一工作。不過目前有兩個讓serverless計算對線性代數運算領域產生意義的因素:一是管理叢集對於非計算機專業的研究人員而言是一件非常吃力的事情,二是整個計算過程中的並行數量可能變化的非常劇烈,使用固定容量的叢集有可能使得計算過程變得非常緩慢(機器數量太少),或者使得整個叢集的資源利用率非常低(機器數量太多)。

  4. Cirrus:機器學習訓練

    機器學習研究人員過去使用VM叢集來處理機器學習相關的工作流,比如預處理、模型訓練和超引數調整。這種方式有一個挑戰,那就是整個處理過程的不同步驟對資源數量的要求存在顯著的差別。和線性代數運算一樣,使用固定數量的叢集會造成計算的緩慢或者資源的浪費。利用serverless計算的彈性縮擴容能力可以很好的解決資源利用率的問題,同時也可以把科研人員從管理叢集的繁瑣任務中釋放出來。

  5. Serverless SQLite:資料庫

    如今市面上已經存在許多不同的具有自動縮擴容能力的資料庫服務,但serverless計算在這方面卻十分乏力。為了更好的理解serverless計算在這方面存在的限制,就需要先搞明白資料庫的工作負載為什麼那麼難以實現。對於這種情況,我們考慮了對於第三方而言,是否可能直接使用cloud functions這種serverless計算的通用模組來構建一個serverless的資料庫。一個可能會受到抨擊的方案是直接在cloud functions裡執行傳統的事務型資料庫,比如PostgreSQL,Oracle或者MySQL,這種方案有非常多的挑戰:首先,serverless計算沒有內建的持久化儲存,所以我們需要利用遠端的持久化儲存,這必定會導致較大的延遲;其次,資料庫一般使用基於連線的協議,而現有的cloud functions一般執行在網路地址轉換器的上層,無法向客戶端提供穩定的長連線;最後,由於大多數的高效能資料庫都依賴於共享記憶體,物理隔離的cloud functions則無法實現這一點,而那些無需共享記憶體的資料庫也要求所有的節點始終保持線上並且可以根據地址直連。上述的問題在severless計算中都難以得到解決,因此我們認為資料庫應該仍以BaaS的形態存在。

serverless計算對上面列舉的這些應用而言有一個共同的優勢,那就是自動縮擴容,這樣可以應對應用急劇變化的資源需求。下面的表格總結了上述五個應用的特性、挑戰以及可能的變通方法,我們將根據它來論述serverless計算目前面臨的幾個侷限。

[譯]伯克利談serverless:過去,現在和未來

3.1 不足以支援細粒度操作的儲存

serverless平臺的無狀態特性使它很難支撐需要共享精細狀態的的應用。這主要是由於目前雲提供商的儲存服務存在較大的限制。下面的表格列舉了目前市面上的一些儲存服務的特點:

[譯]伯克利談serverless:過去,現在和未來

像AWS S3, Azure Blob Stroage 和 Google Cloud Storage這樣的物件儲存一般具有高度的可擴充套件性,並且長期的物件儲存價格也相對廉價,但其訪問成本和延遲都較高。根據近期的測試結果來看,上述的這些服務在讀寫小物件檔案時都需要花費至少10ms以上的時間。關於IOPS(一種磁碟的效能指標),S3最近提高了相應的限制,從而提供了較高的吞吐量,但也帶來了更高的費用。

AWS ElasticCache例項在某幾個維度上能夠提供更好的表現,比如低於毫秒級的讀寫延遲,以及超過100K的IOPS(只需配置和執行一個單執行緒的redis例項)。

鍵值對型資料庫,比如AWS DynamoDB,Google Cloud Datastore 或者 Azure Cosmos DB能夠提供較高的IOPS,但是它們的價格非常昂貴,並且擴容起來比較耗時。

最後,儘管雲供應商也提供了一些主流的記憶體型資料庫如Memcached和Redis,但它們的容災能力很差,並且不能夠自動縮擴容。

從之前的表格中我們可以看出,在serverless基礎設施上構建的應用需要能夠提供透明配置(transparent provisioning)的儲存服務,並且要求它能夠實現和應用同等的自動縮擴容能力。不同的應用對於持久化和可用性,以及延遲和效能的要求都有所不同,我們相信這將會推動短暫型和持久型儲存的研發,在第4部分中我們將會進一步討論這個話題。

3.2 缺少細粒度的任務協作方式

為了擴充套件對有狀態應用的支援,serverless框架需要提供一種任務協作的方法。舉個例子,如果任務A需要使用任務B的輸出,那麼A需要通過某種途徑來知道自己的輸入(任務B)何時處於可用狀態,即便A和B可能執行在不同的節點上。許多用於保證資料一致性的協議也需要類似的協作機制。

目前已有的所有云儲存服務都還不具有訊息通知能力。儘管雲供應商提供了單獨的訊息服務,比如SNS和SQS,但這些服務都存在顯著的延遲,有時候甚至可能達到上百毫秒。並且使用他們來實現精細的協作,往往需要付出高昂的費用。儘管目前也已經有一些像Pocket這樣的針對該領域的研究成果,但目前還沒有被雲供應商應用於生產環境。

於是乎,這些應用想要實現協作就只剩下了兩個選擇,要麼使用基於VM的系統來提供訊息通知機制,比如ElastiCache和SAND;要麼就得自己實現一套通知機制,比如ExCamera中那樣,讓cloud functions之間通過一個持續執行的、基於VM的通訊伺服器來通訊。這個限制也為我們揭示了serverless計算一些值得探索的新形態,比如給函式例項進行命名並且允許他們之間通過一些內部的定址能力直接通訊。

3.3 乏力的標準通訊模式

Broadcast, Aggregation 和 Shuffle 或許是目前分散式系統中最常見的原始通訊模型,它們被機器學習訓練和大資料分析應用廣泛地使用。下圖展示了這些通訊模型在基於VM和基於函式這兩種情景下的方案:

[譯]伯克利談serverless:過去,現在和未來

使用基於VM的解決方案,執行在同一臺例項上的所有任務可以通過共享資料的方式來實現廣播(Broadcast),或者在將部分結果傳送給其他例項前先在本地執行聚合(Aggregation)。在這種情況下,廣播和聚合的通訊複雜度都是O(N),其中N是VM例項的數量。然而如果我們使用clound functions,由於無法執行本地聚合,這個複雜度將會提升到O(N x K),其中K是每臺VM上執行的函式例項的數量。在Shuffle操作上這個差異會更加明顯:基於VM的方案中,由於所有的本地任務可以結合在一起,所其實相當於兩臺VM之間通訊,如果我們假設資料的傳送者和接收者數量相同,那麼就會產生N^2個需要處理的訊息;但在cloud functions的方案中,這個數量將會提升到(N x K)^2,由於VM上執行的函式使用的核數往往遠小於VM本身所具有的,因此K的取值一般在10到100之間。並且因為應用無法控制cloud functions具體執行在哪臺VM上,因此最終產生的訊息數量會比基於VM的方案高出2到4個數量級。

3.4 效能瓶頸

serverlss計算目前在效能上仍然存在諸多問題。

首先是例項冷啟動的延遲問題。儘管cloud functions比起傳統的VM例項啟動延遲要低許多,但它建立新例項的速度依然不能夠滿足某些應用的要求。影響冷啟動時間的因素主要有三個:

  1. 啟動cloud function的時間
  2. 初始化軟體和函式執行環境的時間(如:載入python庫)
  3. 使用者程式碼中的初始化任務

相比起後兩者所消耗的時間,第一項幾乎可以忽略不計,如果啟動一個cloud function需要不到1s,那麼初始化應用所需要的所有庫可能需要花上數十秒。

另一個限制效能的阻礙是底層硬體資源的多樣性,由於雲供應商可以靈活的選擇底層伺服器的規格和型號,這就導致了每個cloud function執行的物理環境效能不盡相同。我們在實驗過程中發現,有些時候函式執行的環境甚至使用了不同時代的CPU。這種不確定性其實暴露了雲供應商的背後的目的:他們想要最大化的平衡資源的使用和預算。

4. Serverless計算應該是什麼樣的

經過上面3個小節的討論,我們已經充分介紹和分析了今天的serverless計算,並且指出它所存在的侷限性。現在讓我們把目光投向未來,分析如何將severless的優勢帶給更多的應用。研究者們已經開始解決我們之前提到的諸多問題,並且嘗試去探索如何進一步改進serverless平臺和執行在它之上的工作負載。下面我們將給出困擾serverless計算應用於更廣泛的硬體和軟體範圍的五大挑戰:抽象、系統、網路、安全以及架構。

4.1 抽象挑戰

資源需求: 今天的serverless平臺給開發者提供的cloud functions只包含記憶體大小和執行時間的限制,但是其他的資源是無法調控的。這對於那些想要控制更多指定資源(如CPU數,GPU數或加速器型別)的開發者來說是一個很大的阻礙。如果允許開發者明確地指定各種資源的需求,又會導致雲供應商無法很好的實現資源的高利用率,因為這會給函式的排程增加許多限制。而且這也違背了serverlss本身降低開發人員對伺服器關注度的初衷。

一個更好的可選方案是提高抽象的層級,讓雲供應商來推斷函式服務的資源需求,而不是由開發者手動去宣告。要實現這一點,雲供應商可以使用很多手段,比如靜態程式碼分析,歷史執行記錄分析,或者是動態地調整程式碼執行的架構。

給正在執行的程式自動分配適量的記憶體是一個極具吸引力的終極目標,然而要實現它卻充滿了挑戰性,因為必須和高階語言執行時環境的GC系統進行互動。有些研究表明這些語言的執行時環境(runtime)可以完全下沉到serverless平臺中,使二者成為一個整體。

資料依賴: 如今的雲平臺還無法感知不同cloud functions之間的資料依賴,更不用說它們之間互動的資料量了。這種缺陷可能會通訊模式的低效率,就像我們在第3部分中提到的那樣。

一種解決方案是由雲供應商來提供允許應用宣告它們計算圖譜 (computation graph) 的API,來推斷能夠使通訊成本最小化的放置方案。我們注意到許多通用的分散式框架(如MapReduce,Apache Spark,Apache Beam 和 Cloud Dataflow)、並行SQL引擎(如BigQUery,Azure CosmosDB)和一些排程框架(如Apache Airflow)早就在它們內部應用了計算圖譜。原則上來說,這些系統經過改造後都可以執行在cloud functions上,並且向雲供應商暴露它們的計算圖譜。AWS Step Functions在此領域已經有了一定的進展,它通過提供一種機器狀態語言和API的方式來解決此類問題。

4.2 系統挑戰

高效能,可負擔,可透明配置的儲存: 我們在第3部分中討論過兩類不同的無地址儲存訴求:Serverless短期儲存和Serverles持久儲存。

短期儲存:

在第3部分中提到的前四個應用都受到了儲存系統的速度和延遲限制,儘管它們所需要的能力各有不同,但都需要一種在整個應用宣告週期中維持應用狀態的儲存。這樣的短期儲存在其他應用中可能以快取的方式存在,一旦應用執行完畢,這些狀態就可以被銷燬。

一種給serverlss應用提供短期儲存能力的方案是構建一個分散式的記憶體快取服務,我們需要優化網路堆疊來保證毫秒級別的延遲,這樣系統就可以允許應用函式在其生命週期內更有效的儲存和交換狀態。對於這個記憶體快取服務,需要實現自動的縮擴容,並提供滿足應用需求的IO吞吐能力。一種獨特的觀點是:通過它應用不僅可以透明地分配記憶體,也可以透明地釋放記憶體。特別地,當某個應用終止或異常退出時,為其分配的短期儲存應該被立刻釋放。這種管理手段和作業系統為程式自動分配和釋放記憶體的功能有點類似。進一步地,這樣的儲存還必須為應用提供訪問許可權保護,並且對跨應用的資料進行隔離。

RAMCloud 和 FaRM 已經向我們展示了構建具有毫米級延遲和萬級IOPS能力的記憶體快取系統的可能性,他們通過對整個系統進行精細優化和RDMA技術的使用最大化的降低了延遲。不過仍然需要應用提供儲存使用的宣告,而且也未能保證不同租戶之間的儲存強隔離。另一個產品Pocket目前正發力解決短期儲存的抽象問題,但也還是不能夠提供自動縮擴容的特性。

通過利用統計複用 (statistical multiplexing) 技術,serverless計算的短期儲存可以改造的比現在更加有效率。在serverful計算中,如果一個應用使用的快取空間只是為它分配的VM例項上記憶體的一小部分,其餘的記憶體空間就都被浪費掉了。相對的,在serverless計算中,如果我們使用共享的記憶體服務 (shared in-memory service),那麼這些未被利用的記憶體就可以被其他的應用所使用。實際上,即便只有一個應用在執行,它也可以從統計複用技術中獲利:在serverful計算中,一個VM上未被利用的記憶體是不能夠被執行在其他VM上的程式所使用的,但如果使用共享的記憶體服務,情況就不一樣了。當然,在serverlss計算中,如果cloud functions不能很好地利用它們的本地記憶體,也會產生許多的記憶體碎片,在某些場景下,把cloud functions的應用狀態存放在共享內的存服務中可以緩解記憶體碎片的問題。

長期儲存:

就像其他的應用一樣,我們用作實驗的serverless的資料庫應用也受到了儲存系統在延遲和IOPS方面的限制,但相比之下,它還有對持久化資料儲存和語義可變化檔案系統 (mutable-state semantics of a file system) 的需求。我們已經討論過資料庫和OLTP不太可能以函式化的方式來執行,而是以BaaS的形式提供,但是仍然會有類似的應用,需要更加持久化的資料儲存,這是短期儲存所不能提供的。為了實現高效能的serverless長期儲存,一種辦法是利用基於SSD的分散式儲存,並和分散式的記憶體快取搭配使用。近期有一個名為Anna的key-value資料庫在很大程度上實現了這個目標,它通過對現有多種雲儲存的組合做到了同時兼顧低費用和高效能。不過這種設計有一個很大的挑戰,那就是長尾延遲 (tail latency),因為記憶體快取的容量一般要遠小於SSD的儲存容量,因此總會有大部分的資料擊穿快取,導致整體讀取速度的下降。利用一些號稱能夠提供微秒級訪問的新儲存技術也許有望解決這個問題。

和serverless短期儲存一樣,長期儲存也應該為服務提供透明的配置,以及足夠安全的隔離性,同時還要保持可以接受的效能。在程式結束時,短期儲存將會被自動回收,但長期儲存則不同,它只在使用者宣告時才能夠被回收(通過delete或者remove這樣的命令),就和傳統的儲存系統一樣。另外它還要保證資料的永續性,即便發生錯誤也能夠恢復。

任務協同/訊號服務: 在不同的函式之間共享狀態經常會使用生產者-消費者的設計模式,這需要消費者知道生產者的資料什麼時候可用。類似的,一個函式可能需要通知另一個函式開始協作(比如實現資料一致性),這都需要訊號通知系統。我們希望它能提供毫秒級的延遲,可靠的送達,還有廣播和分組通訊機制。

我們還注意到現在cloud functions的例項並不是獨立編址的,因此他們不能被用於實現課本上的那些分散式演算法,比如選主和一致性。

最小化啟動時間: 目前serverless應用的啟動時間通常由三部分組成:(1) 排程和啟動cloud function所需資源的時間,(2) 下載函式所需應用環境(作業系統、庫)的時間,(3) 執行應用本身啟動工作的時間

資源排程和初始化經常會帶來顯著的拖慢,主要是因為建立隔離執行環境和配置客戶VPC及IAM的常規開支。部分雲供應商最近已經開始通過開發輕量級隔離機制來著手解決啟動時間的問題。

一種減少第(2)項消耗的方法是利用unikernels,它通過兩種方式避免了建立傳統作業系統所帶來的開支。第一,它不像傳統作業系統那樣動態地檢測硬體、應用使用者配置和分配資料結構,而是把這些操作通過預配置的方式全部壓縮掉了(需要提前根據硬體配置),執行時只是靜態地分配資料結構;第二,unikernels裡只包含了應用所必須的驅動和庫,這不會帶來任何負面影響,因為它本身就是針對特定的應用量身定製的。還有一種減少第(2)項開銷的方法,那就是動態地載入應用所需的庫(被呼叫時才載入),Azure Functions的共享檔案系統目前已經在使用這一技術。

第(3)項開銷則需要開發人員自己來動手解決,不過雲供應商可以在他們的API中提供一些就緒訊號,避免函式例項在準備就緒之前就收到工作任務。更廣泛一點說,雲供應商可以提前執行啟動任務,這對於那些與客戶無關的任務來說是非常有力的提升,比如啟動一個裝載主流作業系統和庫的VM例項,這些例項可以作為“預熱池 (warm pool)”來被多租戶共享。

4.3 網路挑戰

就像我們在第3節中討論的那樣,cloud functions對於一些常見基礎通訊模式的支援不是很好,比如boardcast,aggregation和shuffle。假設我們在一個VM例項上執行了K個cloud function,那我們在boardcast和aggregation上就要忍受K倍的訊息數量,在shuffle中則是K^2倍。

要解決這個問題,有以下幾種可能的方法:

  • 為cloud functions提供更多的核心數,這樣可以同時執行多個任務並在它們之間共享資料。

  • 允許開發者宣告cloud functions的部署位置,同時提供一些開箱即用的通訊原語,這樣做他們便可以將相關的cloud function部署在同一個VM例項上來進行通訊。

  • 讓應用程式提供計算圖譜(computation graph),然後由雲供應商以此為根據排程cloud functions,來達到最小化通訊成本的目的。

前兩種方案有可能會降低雲供應商排程cloud functions的靈活性,並導致資料中心利用率的降低,它們同時也違背了serverless的理念,因為這需要開發者自己去思考如何管理系統。

4.4 安全挑戰

severless計算的出現使應用的安全責任發生了一次洗牌,將很多責任從雲服務的使用者身上轉移給了雲供應商。除此之外,serverless計算還必須解決應用程式分離和多租戶資源共享本身的風險。

隨機化排程和物理隔離: 物理共存是在雲平臺內部引發 hardware-level side-channel 和 Rowhammer 攻擊的主要原因。此類攻擊的第一步往往是尋找和攻擊目標位於同一物理宿主機的租戶作為侵入物件,而cloud functions的生命週期往往較短,且排程存在隨機性,這會使攻擊者難以找到和攻擊目標共存的侵入物件。使用一種隨機化的、能感知入侵的排程演算法將會大大降低此類攻擊發生的可能性,不過這樣產生的物理隔離又可能會導致啟動時間增加、資源利用率降低以及低效通訊等問題。

細粒度的安全上下文: cloud functions需要細粒度的配置,包括私鑰、儲存物件甚至是本地臨時資源的訪問許可權。這要求我們轉變現有serverful應用的安全策略,並且為cloud functions提供能夠動態呼叫的安全API。舉個例子,某個cloud function可能需要給其他的cloud function或雲服務提供安全授權,而基於密碼學的能力控制模型 (A capability-based access control mechanism using cryptographically)就能很好的適用於這樣的分散式系統(近期也有一些研究使用資訊流作為跨函式訪問的控制方法)。如果為cloud function動態建立短期的金鑰和認證,則會進一步加大提供分散式安全控制所帶來的挑戰,比如非模糊性 (non-equivocation) 和認證吊銷問題。

在系統層面上,使用者需要為cloud function提供的更加細粒度的安全隔離措施,至少作為一個可選的選項。提供函式級沙箱的要面臨的挑戰是在不快取執行環境的條件下,仍然要保證足夠短的啟動時間。一種可能性是使用本地快照,這樣每個函式都可以從一個足夠乾淨的狀態啟動。或者,目前輕量級的虛擬化技術也正在逐漸被serverless供應商所採用,比如包括gVisor在內的library OS,通過使用者態的“墊片層 (shim layer)”來提供系統API;以及像AWS Firecracker這樣的unikernel和microVM,簡化訪客核心並幫助縮小可能的攻擊面。這些隔離技術可以把啟動時間降低到幾十毫秒,比起VM秒級的啟動速度要快得多。至於這些方案是否能夠達到和傳統VM技術相同的安全性還需要時間來檢驗,我們也希望構建低啟動延時的隔離環境能夠成為一個持續發展的研究和開發課題。至少從積極的一面看,serverless計算中由供應商提供的管理機制和短生命週期的例項會讓漏洞的修補變得更加迅速。

對於那些想要防禦同駐攻擊 (co-residency attack) 的使用者而言,要求物理隔離可能是一個不錯的解決方案,因為近來的硬體攻擊(如 Spectre 和 Meltdown)幾乎可以使整個核心或是整臺物理機器癱瘓。雲供應商可以為客戶提供一些高階選項,允許他們在專用的物理主機上啟動函式服務。

serverless計算的隱患: cloud function有可能會在通訊期間洩露訪問模式和計時資訊。對於serverful的應用而言,資料通常以批量方式檢索並快取在本地。相對的,由於cloud functions生命週期短暫,並且廣泛分佈在雲端,因此它的網路傳輸模式有可能會向網路攻擊者(比如內部僱員)洩露更多的敏感資訊(即便運輸載體已經被加密了),而將serverless應用拆分成諸多更小函式的趨勢則進一步加劇了這種風險。儘管最大的安全隱患往往來自外部的攻擊者,但針對內部人員也應當採取一定的防範措施,不幸的是,這些措施往往有很高的成本。

4.5 計算機架構的挑戰

硬體異構性,定價和易管理性: Alas,在雲上具有主宰地的x86微處理器,近年來在效能上幾乎沒有任何提升。2017年,單個程式的執行效能僅僅上升了3%。假設這個趨勢繼續下去,即便20年後效能也不會翻倍。類似的,單個晶片的DRAM能力也已經接近極限,16G的DRAM在市面上很常見,但32G的造起來就不太可行了。

儘管通用目的微處理器出現了效能上的問題,但對更快算力的要求卻沒有停止過。要向前進,只有兩條路可行了:一是對於用高階指令碼比如js和python編寫的函式,使用專門優化過的硬體-軟體設計,定製對應的處理器,這可以把特定語言的執行速度提升1到3個數量級。二是使用領域特定的體系架構(Domain Specific Architectures),比如使用GPU,這在影象加速和機器學習領域已經是很常見的事情了,相信在未來會有更多針對領域定製的處理器出現。

我們在4.1節中曾經提到過,serverless計算要支援即將到來的硬體異構問題有兩種方案:

  1. serverless可以包含不同的例項型別,併為它們制定不同的單位使用價格。

  2. 雲供應商可以支援自動切換基於語言的加速器或者領域特定體系架構。這種自動化能力可以基於cloud functions中所使用的語言或軟體庫隱式地完成,比如自動使用GPU來執行CUDA程式碼、用TPU來執行TensorFlow程式碼。雲供應商還可以監控cloud functions的實際執行效能,根據歷史資料來為它們選擇最適合執行的硬體。

serverless計算目前面臨的異構性問題,只是x86的SIMD指令集上面很小的一部分。AMD和Intel都在通過增加單時鐘週期內執行指令數和增加新指令的方式來快速改進x86指令集。對於使用SIMD指令集的程式而言,執行在最新的Intel Skylake微處理器上要比在舊的Broadwell上快得多。今天這兩種微處理器在AWS Lambda上都有應用,但它們的收費是相同的,使用者也沒辦法選擇自己的例項到底執行在哪一種處理器上。

由於加速器在雲上越來越流行,serverless的雲供應商可能沒辦法再繼續忽略硬體的異構性問題,特別是在已經存在合理補救措施的情況下。

5. 陷阱與謬誤

在這一部分中,我們使用Hennessy和Patterson所提出的“陷阱與謬論 (Pitfall & Fallacy)”風格來進行論述。

(譯者注:這裡的謬誤是指人們對serverless的一些錯誤看法,陷阱則是指那些serverless潛在的坑和隱患)

謬誤 AWS Lambda的函式例項規格和AWS t3.nano例項相同(0.5G記憶體),但是每分鐘的計費標準卻是後者的7.5倍,因此serverless雲端計算要比傳統的serverful雲端計算昂貴的多

serverless計算的優點在於它的收費包含了所有的系統管理功能,包括擴充套件性、日誌、監控、可用性和冗餘能力。雲供應商指出客戶在將原有應用遷移到serverless架構後,費用節省了4-10倍。單個cloud function的等效功能其實遠遠超過單個t3.nano例項,後者的CPU使用率在出現單點故障時將會被信用系統限制到每小時6分鐘(就雙核虛擬CPU而言,大概是5%的使用率),因此在峰值負載期間很有出現大面積的服務拒絕,同樣的情況則不會在serverless例項上發生。serverless無論在擴容還是在縮容上都有更精細的邊界,這樣在計算資源的使用上要有效率的多。另外在沒有請求的情況下,serverless例項是不會進行扣費的,因此它產生的實際費用很可能要便宜的多。

陷阱 serverless計算可能會產生不可預測的成本

對於某些使用者而言,serverless計算這種“用多少花多少”的收費模式帶來的缺點就是:沒法預測具體會產生多少費用,這於許多組織管理預算的方式很不一樣,他們通常按年為單位進行預算的批准,因此需要知道下一年serverless服務究竟會帶來多少費用。這是一個合理的顧慮,雲供應商可以通過提供基於桶的定價來緩解這個問題,就像手機通訊運營商提供固定費率的定量套餐那樣。同時我們也相信隨著越來越多的公司和機構採用serverless計算,他們將能夠根據歷史資料來推測serverless可能產生的費用,就像我們現在今天估計電費的方式一樣。

謬誤 由於serverless計算採用像python這樣的高階語言作為程式語言,因此在不同的serverlss計算供應商之間移植應用很簡單

通常來說,不同的severless計算供應商所提供的函式呼叫語義都是不同的。而且許多serverless應用還強依賴於一些非標準化的BaaS服務生態系統。物件儲存,Key-Value資料庫,認證,日誌,監控都是典型的例子。如果要實現可移植性,serverless使用者必須要使用某種規範化的API,就像POSIX之於作業系統那樣。Google的Knative專案現在已經在這個方向上邁出了一步,它為應用開發人員提供了一套統一的、跨部署環境的原語集。

陷阱 serverless計算可能有著比serverful計算更強的廠商鎖定

這個陷阱是前一個謬誤所造成的結果,如果移植非常困難,那麼很有廠商鎖定就是一件很有可能發生的事情。現在有一些框架承諾提供提供跨雲平臺的技術支援,這在一定程度上緩解了這個問題。

謬誤 Cloud Functions無法實現那些有效能預測和低延遲要求的應用

serverful例項之所以能夠用於處理有低延遲要求的應用程式,是因為他們總是處於執行狀態,所以接收到請求時可以快速地響應。我們注意到如果cloud function不能滿足給定應用的低延遲需求,可以通過“預熱”的方式來解決這個問題:通過定期執行cloud functions的方式進行預熱,從而保證當請求到來時有足夠多的例項進行快速響應。

陷阱 那些號稱“彈性”的服務中,只有很少一部分真正符合serverless計算對靈活性的要求

“彈性 (Elastic)”一詞在今天是一個特別流行的術語,但它也被濫用於許多並不具有serverless計算那樣自動縮擴容特性的服務上。我們真正感興趣的是那些能夠快速調整容量,並且幾乎無需使用者干預的,甚至可以在不使用時縮減到零例項(scale to zero)的服務。舉個例子,儘管AWS ElastiCache名字中帶有“彈性”二字,但它只允許你例項化一定數量的redis例項。其他的“彈性”服務都還需要使用者手動進行所需容量的宣告,而且其中還不乏一些需要花費數分鐘才能響應縮擴容,或者縮擴容量存在限制的服務。如果使用者把具有高彈性的cloud functions和資料庫、搜尋索引以及彈效能力不足的serverful應用繫結在一起,將會失去serverless計算的許多優勢。在出現可以量化的指標或者能夠被廣泛接受的技術定義前,“彈性”一詞將仍然會是一個模糊不清的概念。

6. 總結和預測

通過提供簡化的程式設計環境,serverless計算讓雲用起來更容易,因此吸引了許多人使用。serverless計算由FaaS和BaaS共同組成,對雲端計算而言有著里程碑式的重要意義,它把開發人員從繁重的手動資源管理和效能優化中解放出來,就像40多年前組合語言演變到高階語言的過程一樣。

我們預測serverless仍然會飛速發展,同時隨著時間的推移,混合型別的雲應用 (hybird) 的數量將會逐漸減少,不過由於一些監管限制和資料治理規則,仍然會有類似的部署存在。

serverless現在已經取得了一定的成功,但也仍然存在一定的挑戰,如果克服了這些挑戰,它將能夠在更廣的領域裡獲得更大的成功。比如上文提到的serverless短期和長期儲存方案,以及能夠更好支援主流通訊原語的訊號機制。

此外,serverless計算未來還將面臨安全和成本問題,尤其是需要適配特殊目的處理器(GPU,TPU等)帶來的效能-成本提升。不過好在serverless計算本身的特效能夠幫助它應對這些挑戰:比如cloud function的隨機排程特性可以有效地避免同駐(co-reidency)和旁道(side-channel)攻擊,而cloud function所使用的高階語言(如js,python,tensorflow)都提高了程式設計的抽象度,與底層硬體充分解耦,這樣便可以更加輕鬆地應用具有高效能比的硬體。

2009年,在伯克利關於雲端計算的觀點(Berkeley View of Cloud Computing)一文中,我們預測當時雲端計算所面臨的挑戰將會被逐一解決,雲端計算將會繁榮昌盛起來 —— 事實的確如此,現在的雲產業的利潤率正在以每年50%的速度增長,給雲供應商帶來了極大的收益。

在本文的最後,我們針對serverless計算在未來十年的可能表現提出一些新的預測:

  • 我們期望有新形態的BaaS儲存服務出現,讓更多型別的應用能在serverless平臺上執行地更好。這些儲存服務需要達到和本地塊儲存同樣高的效能,並且提供短期儲存和長期儲存兩種變體。serverless計算未來將會由更多的異構硬體組成,而不是僅僅是傳統的x86處理器。

  • 得益於cloud functions高度的程式語言抽象和細粒度的隔離措施,serverless計算未來應該能夠提供比當前serverful計算更簡單的方式來解決程式設計安全問題。

  • serverless計算的收費模型將得到很大的改進,以至於幾乎所有的應用,無論以什麼樣的規模執行在serverless平臺上,都要省錢的多。

  • 傳統serverful計算在未來將會促進BaaS的發展,那些被證明是很難以serverless形式執行的應用,比如OLTP資料庫或者佇列這樣的通訊原語,未來很可能會是雲供應商所提供的更豐富的服務的一部分。

  • 雖然serverful雲端計算不會消失,但隨著serverless存在的缺陷被逐個攻克,它在雲端計算中所佔的相對比重將會逐漸下降。

  • serverless計算將會成為雲時代預設的計算正規化,大面積取代原有的serverful計算,併為傳統的客戶端-伺服器時代劃上一個句號。

相關文章