Serverless:微服務架構的終極模式
點擊上方“服務端思維”,選擇“設為星標”
回復”669“獲取獨家整理的精選資料集
回復”加群“加入全國服務端高端社群「后端圈」

微服務的生態(tài)和實踐已經比較成熟,其設計方法、開發(fā)框架、CI/CD工具、基礎設施管理工具等,都可以幫助企業(yè)順利實施微服務。然而,微服務遠沒有達到完美,它在架構、開發(fā)、基礎設施方面仍然面臨新的挑戰(zhàn)。
微服務面臨的挑戰(zhàn)
微服務的粒度影響服務的交付速度及擴展性,微服務的開發(fā)引入治理組件,增加了開發(fā)的難度,以容器為基礎的微服務基礎設施在彈性等方面仍有不足,而微服務增加帶來的基礎設施成本也是微服務實施的新挑戰(zhàn)。
1.微服務的粒度仍然比較大
當前微服務劃分主要遵循單一職責的原則,比如將用戶管理的功能作為一個單獨的微服務。如圖所示,用戶管理微服務提供了API注冊、登錄、登出功能。通常,從提升用戶體驗的角度來看,瀏覽器會保留用戶的會話,除非用戶主動登出,否則不會請求登出API。所以,登出和注冊的QPS差距較大,對擴展的訴求完全不同。而且,注冊API和登出API的變更頻率也可能不同。進一步拆分可以帶來擴展性等便利,但整個微服務的數量也會提升一個量級,給基礎設施的管理帶來負擔,那么如何做好架構權衡,既能夠擁有架構上的高可擴展性,又不用增加基礎設施管理成本呢?

2.微服務開發(fā)仍有較高門檻
如圖所示,Java微服務開發(fā)的軟件棧要求開發(fā)者掌握以下技能。

Java微服務開發(fā)技術棧
相比于單體應用開發(fā),微服務開發(fā)效率得到提升的部分來自服務粒度減少及開發(fā)框架的改進,例如,從復雜的SpringMVC演進到SpringBoot,框架更加輕量化。但在其他方面(并發(fā)處理等)并沒有什么改變,同時在微服務治理、分布式事務等方面的開發(fā)難度反而增加了。服務網格的出現,讓開發(fā)人員可以不用關心服務治理的內容,但這樣會帶來服務性能的下降和維護的復雜性,其使用的范圍也存在局限。是否存在一種新的編程模型及開發(fā)框架,讓開發(fā)者在了解基本的語言特性和編程模型后,便可上手開發(fā)業(yè)務邏輯,而不用關心網絡、并發(fā)、服務治理等問題?
3.微服務基礎設施管理、高可用和彈性仍然很難保證
容器和Kubernetes工具的使用,提升了應用部署及基礎設施運維自動化的能力,但保證基礎設施高可用、可擴展對運維人員的能力要求很高。如圖所示,服務上云后,基礎設施團隊可以不用再關心服務器、交換機等硬件的運維,但仍然需要關心虛擬機的維護,如安全補丁、基礎鏡像的更新升級、擴容等。

基礎設施團隊依然需要管理虛擬機
從On-Premise到公有云,實際上虛擬機的可用性在降低,比如云服務商提供的單虛擬機的可用性可能只有95%。運維人員需要借助云側的工具來保證基礎設施的高可用,難度仍然存在,而且很依賴運維人員的能力。
集群及其他云原生工具的維護也帶來額外的挑戰(zhàn)。以Kubernetes集群為例,維護和管理Kubernetes集群需要專業(yè)的技能。同理,維護云原生的監(jiān)控、日志服務的高可用性也有不小的難度。所以,基礎設施管理的難度仍然存在,只是從虛擬機轉移到容器集群,從Rsyslog轉移到ElasticSearch。
對于服務層面的擴展性,當前的策略也比較簡單,例如,設定最少和最多使用的虛擬機數量,或者想辦法改善根據CPU/內存使用率來伸縮或擴容的延遲。但是,由于總體資源量不會超過策略設定的虛擬機極限數量,因此一旦請求超過最大資源能承載的范圍,可能會影響用戶的使用體驗甚至會服務中斷。以容器為單位的擴容,從虛擬機性能的分鐘級減少到30s左右,但當面對突發(fā)流量時依然會出現響應不及時、用戶體驗差的情況。是否存在全托管的基礎設施及監(jiān)控運維服務,能提供更好的彈性,從而讓開發(fā)者無須關心所有底層和集群的維護工作,不再依賴高級運維人員來保證基礎設施的可用性?
4.基礎設施的成本依然較高
微服務會增加基礎設施的成本。每個微服務都要考慮冗余,保證高可用。隨著微服務數量的增加,基礎設施的數量會呈現指數級增長,但云服務的基礎設施收費方式沒有改變,依然采用按照資源大小及以小時為單位(或包年)計費的方式。閑時和忙時的收費相同,對企業(yè)來說存在成本的浪費。是否存在一種新的基礎設施服務,能按照“用多少付多少”的方式收費,從而降低基礎設施成本?
微服務面臨的這些新問題,是否可以通過新的基礎設施服務及開發(fā)模式來解決呢?
什么是Serverless
2012年,時任Iron.io的副總裁Ken提出了Serverless的概念,他認為未來的軟件和應用都應該是Serverless的:“即使云計算興起,世界仍然圍繞著服務器運轉。不過,這不會持續(xù)下去。云應用程序正在進入無服務器世界,這將對軟件和應用程序的創(chuàng)建和分發(fā)產生重大影響。”
2014年,AWS推出Lambda函數計算服務,提供簡化的編程模型及函數的運行環(huán)境全托管,并且計費方式更加接近實際的使用情況(請求次數和每100ms使用的內存資源)。2015年,AWS推出API Gateway(全托管的網關服務),正式將Serverless這個概念推廣開來。近年來,大部分的云提供商也提供了各種形態(tài)的Serverless服務,用于支持更多應用的開發(fā)和運行。下圖為AWS Serverless全景圖。

AWS Serverless全景圖
Google在Serverless上的投入和發(fā)展節(jié)奏也很快。為了擴大在移動應用開發(fā)領域的優(yōu)勢,同時為Google云引流,Google在2011年就收購了Firebase,2016年將其作為mBaaS(移動后端即服務)的Serverless解決方案推出,以及安卓應用開發(fā)的主流云服務。除此之外,Google也推出了其他Serverless服務,以提供跨平臺(Android、Web、iOS等)能力,支持移動、Web等應用開發(fā),下圖為Google Serverless全景圖。

Google?Serverless全景圖
華為終端云服務以多年為超過百萬移動應用開發(fā)者提供服務為基礎,結合多年在Serverless領域的技術積累,推出了Serverless行業(yè)解決方案,包含構建類(云函數、認證、云存儲、云數據庫等)、增長類(推送服務、遠程配置等)、質量和分析類(性能服務、崩潰服務等),提供面向移動應用開發(fā)的Serverless服務。2021年,云函數、云數據庫等核心構建類服務已面向全球HMS生態(tài)的開發(fā)者開放,下圖為HUAWEI AppGallery Connect Serverless全景圖。

HUAWEI AppGallery Connect Serverless全景圖
Serverless的定義
那么Serverless到底是什么呢?維基百科將Serverless定義為一種云計算執(zhí)行模型。
云服務商按需分配計算機資源,開發(fā)者無須運維這些資源,不用關心容器、虛擬機或物理服務器的容量規(guī)劃、配置、管理、維護、操作和擴展。
Serverless計算無狀態(tài),可在短時間內完成計算,其結果保存在外部存儲中。
當不使用某個應用時,不向其分配計算資源。
計費基于應用消耗的實際資源來度量。
CNCF(Cloud Native Computing Foundation,云原生計算基金會)認為Serverless旨在構建和運行不需要服務器管理的應用程序,二者的不同之處在于它描述了一個更細粒度的部署模型,能夠以一個或多個函數的形式將應用打包并上傳到平臺執(zhí)行,并且按需執(zhí)行、自動擴展和計費。
Serverless并不意味著不需要服務器來托管和運行代碼,也不意味著不再需要運維工程師。Serverless是指開發(fā)者不再需要將時間和資源花費在服務器調配、維護、更新、擴展和容量規(guī)劃上,這些任務都由Serverless平臺處理,開發(fā)者只需要專注于編寫應用程序的業(yè)務邏輯,運維工程師能夠將精力放在業(yè)務運維上。綜合維基百科和CNCF的定義,可以認為Serverless是一種云計算執(zhí)行、部署和計費模型,Serverless服務按請求為應用分配資源,按照使用計費,基礎設施全托管(無須關心維護、擴容等)。
目前,Serverless服務主要分為FaaS和BaaS。
函數即服務(Function as a Service,FaaS):開發(fā)者實現的服務器端應用邏輯(微服務甚至粒度更小的服務)以事件驅動的方式運行在無狀態(tài)的臨時容器中,這些容器和計算資源完全由云提供商管理。如圖1-7所示,從開發(fā)者角度來看,FaaS和IaaS/PaaS相比,其擴容的維度從應用級別降低到函數級別,開發(fā)者只需關心和維護業(yè)務層面的正常運行,其他部分如運行時、容器、操作系統、硬件等,都由云提供商來解決。

FaaS與IaaS、PaaS的區(qū)別
后端即服務(Backend as a Service,BaaS):基于API的三方服務,用來取代應用程序中功能的核心子集。由于這些API是作為自動擴展和透明運行的服務提供的,因此從開發(fā)者和運維工程師的角度來看似乎是無服務器的。非計算類的全托管服務,如消息隊列等中間件、NoSQL數據庫服務、身份驗證服務等,都可以認為是BaaS服務。
FaaS通常是承載業(yè)務邏輯代碼的服務,開發(fā)者會更為關心,它也是本書重點介紹的內容。
Serverless關鍵技術
下圖是典型的Serverless系統架構,從中可以看到一些Serverless的常用概念。

典型的Serverless架構
事件源(Event Sources):事件的生產者,可能是HTTP請求、消息隊列的事件等,通過同步或異步的方式去觸發(fā)函數。
觸發(fā)器(Trigger):函數的REST呈現,通常是RESTful URL。當事件源將事件推/拉到觸發(fā)器時,FaaS平臺會查找觸發(fā)器和函數的映射關系,從而啟動該函數實例,以響應被推/拉到觸發(fā)器的事件。
FaaS控制器(FaaS Controller):FaaS平臺的核心組件,管理函數的生命周期、擴容和縮容等。可以將函數實例縮容為0,同時在收到對函數的請求時迅速啟動新的函數實例。
函數實例(Function Instance):執(zhí)行函數的環(huán)境,包含函數代碼、函數運行環(huán)境(如JRE、Node.js)、上下文信息(如函數運行的配置,通常以環(huán)境變量注入)。一個函數實例可以同時處理1個或N個事件(取決于平臺的具體實現)。函數實例通常內置可觀測性,將日志和監(jiān)控信息上報到對應的日志和監(jiān)控服務中。
函數編程模型(Programming Model):通常表現為函數的編碼規(guī)范,如簽名、入口的方法名等。函數的編程模型一般會提供同步/異步/異常處理機制,開發(fā)者只需要處理輸入(事件、上下文),并返回結果即可。
BaaS平臺:函數通常是無狀態(tài)的,其狀態(tài)一般存儲在BaaS服務中,如NoSQL數據庫等。函數可以基于REST API或BaaS服務提供的SDK來訪問BaaS服務,而不用關心這些服務的擴容和縮容問題。
結合上圖中典型Serverless架構的架構元素,從Serverless系統的實現來看,其關鍵技術需求包括以下幾點。
函數編程模型:提供友好的編程模型,使開發(fā)者可以聚焦于業(yè)務邏輯,為開發(fā)者屏蔽編碼中最困難的部分,如并發(fā)編程等。同時,需要原生支持函數的編排,盡量減少開發(fā)者的學習成本。
快速擴容:傳統的基礎設施通常都是從1到n擴容的,而Serverless平臺需要支持從0到n擴容,以更快的擴容速度應對流量的變化。同時,傳統基礎設施基于資源的擴容決策周期(監(jiān)控周期)過長,而Serverless平臺可達到秒級甚至毫秒級的擴容速度。
快速啟動:函數被請求時才會創(chuàng)建實例,該準備過程會消耗較長的時間,影響函數的啟動性能。同理,對于新到達的并發(fā)請求,會產生并發(fā)的冷啟動問題。Serverless平臺需要降低冷啟動時延,以滿足應用對性能的訴求。
高效連接:函數需要將狀態(tài)或數據存放在后端BaaS服務中,而對接這些服務往往需要繁雜的API,造成開發(fā)人員的學習負擔。如果能提供統一的后端訪問接口,則可以降低開發(fā)和遷移成本。另外,Serverless平臺的函數實例生命周期通常較短,對于如RDS數據庫等后端服務無法保持長連接。然而,在并發(fā)冷啟動場景下,大量函數實例會同時創(chuàng)建與數據庫的連接,可能會導致數據庫負載增加而訪問失敗。為此,Serverless平臺需要為函數提供完備、高效、可靠的BaaS服務連接/訪問接口。
安全隔離:Serverless是邏輯多租的服務,租戶的函數代碼可能運行在同一臺服務器上。基于容器的方式,一旦單個租戶的函數遭受攻擊,造成容器逃逸,會影響服務器上所有租戶的函數安全。所以,通常Serverless平臺會采用安全容器的方式,引入輕量級虛擬化技術來保證隔離性,但這同時會引入額外的性能(啟動)和資源開銷等問題。因此,Serverless平臺需要兼顧極致性能和安全隔離。
雖然業(yè)界涌現的各種Serverless系統在實現上可能有所不同(如本節(jié)介紹的多個函數計算平臺),但基本的概念、原理和關鍵技術是相通的,各個系統在實現時都需要應對以上所述的技術挑戰(zhàn)。
Serverless帶來的核心變化
從開發(fā)者或商業(yè)的角度看來,Serverless的價值在于全托管及創(chuàng)新的計費模式。但從技術的角度看,Serverless從架構、開發(fā)模式、基礎設施等層面都有不同程度的創(chuàng)新。
Serverless的技術創(chuàng)新
Serverless基于事件驅動的架構,它的編程模型和運行模式簡化了開發(fā)模式,融入了不可變基礎設施的最佳實踐。
1.Serverless是事件驅動架構的延伸
Serverless更容易實現事件驅動的應用。在分布式系統中,請求/響應的方式和事件驅動的方式都存在。請求/響應是指客戶端會發(fā)出一個請求并等待一個響應,該過程允許同步或異步方式。雖然請求者可以允許該響應異步到達,但對響應到達的預期本身就在一個響應和另一個響應之間建立了直接的依賴關系。事件驅動的架構是指在松耦合系統中通過生產和消費事件來互相交換信息。相比請求/響應的方式,事件的方式更解耦,并且更加自治。例如,在圖片上傳后進行轉換處理的場景,以往需要一個長時運行的服務去輪詢是否有新圖片產生,而在Serverless下,用戶不需要進行編碼輪詢,只需要通過配置將對象存儲服務中的上傳事件對接到函數即可,文件上傳后會自動觸發(fā)函數進行圖片轉換。
Serverless架構的基本單元從微服務變?yōu)楹瘮怠N⒎盏拿總€API的非功能屬性有差異,比如對性能、擴展性、部署頻率的要求并不相同,進一步拆分的確有助于系統的持續(xù)演進,但相應會帶來指數級的服務數量增長,導致微服務的基礎設施和運維體系難以支撐。Serverless架構可以將微服務的粒度進一步降低到函數級,同時不會對基礎設施和運維產生新的負擔,只是增加了少量的函數管理成本,相比其帶來的收益這是完全可以接受的。
基于Serverless更容易構建3-Tier架構應用。3-Tier是指將應用分為3層,即展示層、業(yè)務層及數據層,并且會部署在不同的物理位置。如Web應用,其展示層和業(yè)務層在物理層面往往會在一起部署。以下圖中的寵物商店應用為例,在基于微服務的部署視圖中,其業(yè)務層和展示層在一起部署;而在基于Serverless的部署視圖中,展示層可以托管在對象存儲服務中,業(yè)務層由FaaS托管,數據層由云數據庫托管,實現了3-Tier在物理上的獨立部署。同時,各層獨立擴展,技術獨自演進。

通過Serverless構建三層架構的寵物商店應用
2.Serverless簡化了開發(fā)模式
微服務提供了豐富的框架,方便開發(fā)者進行開發(fā),但同時也增加了開發(fā)者的認知負擔,同樣是使用Java,基于Serverless開發(fā)服務,開發(fā)者只需掌握Java的基礎特性、函數編程框架及BaaS的SDK即可,如下圖所示。

基于Java的微服務開發(fā)和函數開發(fā)差異
函數的編程框架相比Spring/SpringBoot要簡單很多,開發(fā)者只需了解輸入輸出處理(通常為JSON)及如何處理業(yè)務邏輯。如下圖所示,Serverless系統可以是1∶1的觸發(fā)模型,每個請求被一個單獨的函數實例處理,每個實例可以被視為一個單獨的線程,系統自動根據請求數量擴展函數實例,開發(fā)者不用理解Java的并發(fā)編程也可以輕松實現對高并發(fā)應用的支持。

Serverless支持應用的高并發(fā)
基于函數的編程模型,可以繼續(xù)對數據進行抽象操作。例如,Azure Function提供的Data Binding功能,允許開發(fā)者用一套配置和一種編程模型操作不同存儲服務的數據,讓開發(fā)服務變得更加簡單,降低開發(fā)人員的認知負擔,進而提升開發(fā)效率。
3.Serverless是不可變基礎設施的最佳實踐
Serverless直接以代碼方式部署,開發(fā)者不用再考慮容器鏡像打包、鏡像維護等問題。系統通常在部署時重新創(chuàng)建函數實例,在不使用時回收實例,每次處理用戶請求的可能都是全新的實例,降低了因為環(huán)境變化出錯的風險。而這些部署及變更的過程,對用戶來說只是更新代碼,其復雜度相比使用容器及Kubernetes大大降低。Serverless在擴展性方面也具有優(yōu)勢。FaaS和BaaS對開發(fā)人員來說沒有“預先計劃容量”的概念,也不需要配置“自動擴展”觸發(fā)器或規(guī)則。縮放由Serverless平臺自動發(fā)生,無須開發(fā)人員干預。請求處理完成后,Serverless平臺會自動壓縮計算資源,當面對突發(fā)流量時,Serverless可以做到毫秒級擴容,保證及時響應。
基于Serverless的服務治理也更簡單。例如,通過API網關服務可以對函數進行SLA(服務水平協議)設置限流,函數請求出錯后會自動重試,直至進入死信隊列,開發(fā)者可以針對死信隊列進行重放,最終保證請求得到處理。
Serverless平臺默認對接了監(jiān)控、日志、調用鏈系統,開發(fā)者無須再費力單獨維護運維的基礎設施。雖然當前Serverless的監(jiān)控指標并不如傳統的監(jiān)控指標豐富,但是其更關注的是應用的黃金指標,如延遲、流量、錯誤和飽和度。這樣可以減少復雜的干擾信息,使開發(fā)者專注在用戶體驗相關的指標上。
Serverless的其他優(yōu)點
除了以上的技術創(chuàng)新,Serverless還有一些額外的優(yōu)點。
加快交付的速度:函數的代碼規(guī)模、測試規(guī)模相比微服務又降低了一個量級,可以更快地開發(fā)、驗證及通過持續(xù)交付流水線發(fā)布。
全功能團隊構建更加容易:微服務實施的關鍵之一在于全功能團隊。全功能團隊通常由不同角色(前后端開發(fā)人員、DevOps等)組成。如果一段時間內前端開發(fā)任務較多,可能會出現前端開發(fā)人員不足導致交付延期的情況,反之亦然。采用全棧工程師是一個有效的解決方案,但這樣的工程師比較稀缺,培養(yǎng)周期較長。Serverless讓前后端技術棧統一變得更簡單,比如使用Node.js、Swift、Flutter等統一前后端技術,開發(fā)者從而可以使用一門技術實現前后端業(yè)務的開發(fā),最終使團隊效率倍增。
Serverless和微服務的差異
為了說明Severless開發(fā)與微服務開發(fā)的區(qū)別,表1-1對比了整個軟件開發(fā)流程中微服務和Serverless在每個階段的活動,從設計、開發(fā)、上線到持續(xù)服務,Serverless相比微服務在開發(fā)難度及工作量上大幅降低,最終體現為更少的業(yè)務上線時間和更穩(wěn)定的運行質量。
微服務和Serverless開發(fā)的差異
* 本文節(jié)選自《華為Serverless核心技術與實踐》一書,歡迎閱讀此書了解更多內容!
— 本文結束 —

關注我,回復 「加群」 加入各種主題討論群。
對「服務端思維」有期待,請在文末點個在看
喜歡這篇文章,歡迎轉發(fā)、分享朋友圈


