淺析流量洪峰下的云開發(fā)高可用架構(gòu)設(shè)計(jì)
1. 寫在前面
疫情期間,隨著返崗復(fù)工人員大幅流動,疫情擴(kuò)散傳播風(fēng)險(xiǎn)巨大,疫情防控也面臨新的嚴(yán)峻挑戰(zhàn)。為了更好地統(tǒng)計(jì)流動人口信息,云南省公安廳面向社會公共場所推出“云南抗疫情”小程序,對公共場所的流動人口進(jìn)行信息登記。具體措施是:每個(gè)場所都事先申請場所進(jìn)出二維碼,人員在進(jìn)入某公共場所時(shí),掃描“進(jìn)場”二維碼進(jìn)入場所;離開時(shí)則需掃描“離場”二維碼離開場所。二維碼里面有單位及相關(guān)負(fù)責(zé)人的關(guān)聯(lián)信息,人員進(jìn)出公共場所都需要掃碼。
上線不到一個(gè)月,截至 3 月 12 日,“云南抗疫情”掃碼小程序公共場所累計(jì)注冊 103 萬余個(gè),掃碼登記 3.65 億人次,掃碼用戶數(shù)達(dá) 1755 萬余人。各個(gè)公共場所登記生成二維碼的請求量超過 10w/min,掃碼登記請求量超過 80W/min。云開發(fā)服務(wù)的高效穩(wěn)定將直接影響廣大人民群眾進(jìn)出各個(gè)場所的效率。
那么,如何應(yīng)對短時(shí)間的流量洪峰,確保小程序功能的正常使用?如何優(yōu)化小程序響應(yīng)速度,在高并發(fā)下仍舊保持快速響應(yīng)?
2. 高并發(fā),不可忽視的業(yè)務(wù)技術(shù)挑戰(zhàn)
高并發(fā)對于任何服務(wù)來說都具有不小的技術(shù)挑戰(zhàn)。
在傳統(tǒng)模式下,一方面,要求業(yè)務(wù)的研發(fā)人員有一定的業(yè)務(wù)預(yù)見性,能夠提前對業(yè)務(wù)峰值做相對準(zhǔn)確的預(yù)估,過多則造成資源浪費(fèi),過少則影響業(yè)務(wù)效果。另一方面,要求研發(fā)人員對業(yè)務(wù)架構(gòu)進(jìn)行合理設(shè)計(jì),提前部署大量資源,甚至要進(jìn)行大量壓測以確??煽啃?。不僅如此,還需要開發(fā)運(yùn)維等人員參與??梢哉f,應(yīng)對高并發(fā)問題,在傳統(tǒng)開發(fā)模式下,需要耗費(fèi)很多的人力物力,成本昂貴。
然而,這些高并發(fā)問題,在云開發(fā)模式下,相對確簡單了很多。云開發(fā)作為一個(gè)支持多端開發(fā)的云 + 端一體化解決方案,采用 serverless 架構(gòu),架構(gòu)具備足夠的輕量和彈性,可以無限自動水平擴(kuò)容,支持海量并發(fā)請求。對開發(fā)者來說,使用云開發(fā)就是典型的 NoOps 實(shí)踐。隨著請求量的不斷增長,云開發(fā)可以進(jìn)行自動擴(kuò)縮容量,確保允許在云開發(fā)上面的業(yè)務(wù)高性能、高可用,按需使用資源使得開發(fā)者不需要為了應(yīng)對高并發(fā)而提前部署大量資源,這大大節(jié)約了資源成本。
此外,通過云開發(fā)各類端側(cè) SDK 就可以輕松實(shí)現(xiàn)包括微信小程序、QQ 小程序、WEB 端、移動應(yīng)用等多端開發(fā),僅需專注于開發(fā)者自身的業(yè)務(wù)實(shí)現(xiàn),而無需關(guān)心傳統(tǒng) C/S 架構(gòu)中的服務(wù)端基礎(chǔ)架構(gòu),業(yè)務(wù)可以快速開發(fā)上線,極大地提高開發(fā)效率,降低研發(fā)成本。
當(dāng)前,云開發(fā)日均調(diào)用超過七億次,其中微信讀書、拼多多等客戶單個(gè)環(huán)境的請求量已經(jīng)達(dá)到過億級別。
3. 云開發(fā)的高性能高可用架構(gòu)設(shè)計(jì)
云開發(fā)作為一個(gè)公有云服務(wù),不僅要能為開發(fā)者提供各類能力支持,更重要的是能為客戶業(yè)務(wù)提供連續(xù)不間斷的服務(wù)。這里,云開發(fā)的高可用就包括兩個(gè)方面:一是確保云開發(fā)自身服務(wù)的高可用,可以不間斷提供服務(wù);二是為客戶提供支持高并發(fā)的能力支持,確??蛻魳I(yè)務(wù)不斷上漲過程中,客戶業(yè)務(wù)高可用。
而云開發(fā)服務(wù)調(diào)用鏈路上有非常多的功能模塊,這就要求云開發(fā)內(nèi)部的所有功能模塊都是高性能和高可用的,目前云開服務(wù)內(nèi)部依賴模塊,日常均達(dá)到遠(yuǎn)超過 99.99% 的服務(wù)可用性和極低的響應(yīng)時(shí)間。
那么云開發(fā)如何保證高可用高性能呢?
下面先來看一下云開發(fā)整體架構(gòu):
從圖中可以看到用戶的一次服務(wù)調(diào)用需經(jīng)過多個(gè)中間層服務(wù),最終到的客戶資源層,所以云開發(fā)服務(wù)的高可用高性能從大的層面上可分為 “數(shù)據(jù)鏈路” 和 “底層資源” 兩個(gè)方面。目前,云開發(fā)系統(tǒng) “數(shù)據(jù)鏈路” 和 “底層資源” 均超過 99.99% 以上的可用性。
數(shù)據(jù)鏈路
應(yīng)用從端側(cè) SDK 開始訪問云資源(云函數(shù)、數(shù)據(jù)庫、文件存儲)需經(jīng)過的一系列服務(wù)模塊最終到的資源層,這一調(diào)用鏈路對開發(fā)者來說是透明無感知的,所以這里將這一部分統(tǒng)稱為 “數(shù)據(jù)鏈路”。
數(shù)據(jù)鏈路為用戶提供 端側(cè) 和 云資源側(cè) 的連通能力,數(shù)據(jù)鏈路也并不僅僅進(jìn)行數(shù)據(jù)轉(zhuǎn)發(fā)和傳輸,還包括一系列的處理邏輯,如微信登錄鑒權(quán)、票據(jù)生成與校驗(yàn)、數(shù)據(jù)編解碼、云賬戶身份鑒權(quán)、集群路由、云資源信息綁定、安全規(guī)則、數(shù)據(jù)簽名與校驗(yàn)、上下文環(huán)境信息注入、訪問記數(shù)、并發(fā)控制等多方面的能力支持模塊。
云開發(fā)服務(wù)各層服務(wù)模塊均按多集群進(jìn)行部署,集群內(nèi)各層及各服務(wù)模塊也均進(jìn)行了跨多機(jī)房的冗余部署,提供充分的冗余,并且自動發(fā)現(xiàn)和剔除故障主機(jī),確保在服務(wù)故障時(shí)能夠進(jìn)行快速屏蔽,保證云開發(fā)服務(wù)的高可用性。另外數(shù)據(jù)管道在資源部署上也提供了充足的容量支持,并備有一定量的 Buffer,當(dāng)有用容量需求時(shí),可進(jìn)行快速擴(kuò)容。部分模塊也開始嘗試容器化部署,能夠更快速彈性擴(kuò)容。
鏈路是用戶請求能否成功到達(dá)客戶資源的關(guān)鍵,鏈路耗時(shí)也會對用戶請求總耗時(shí)產(chǎn)生直接影響。所以保證鏈路的高可用性和高性能非常關(guān)鍵,云開發(fā)團(tuán)隊(duì)在性能和可用性方面也做了很多的設(shè)計(jì)優(yōu)化,以下為部分設(shè)計(jì)和優(yōu)化點(diǎn):
- 盡可能簡單,不引入不必要的依賴,盡可能減少依賴;
- 無狀態(tài)設(shè)計(jì),各個(gè)模塊均是無狀態(tài)的,便于在系統(tǒng)請求量上升時(shí)快速進(jìn)行橫向擴(kuò)容;
- 可降級設(shè)計(jì),鏈路中各個(gè)模塊均進(jìn)行可降級設(shè)計(jì),在單個(gè)模塊出現(xiàn)問題時(shí),可自動或手動降級到備用方案,并且有兜底方案;
- 多級緩存設(shè)計(jì),在系統(tǒng)內(nèi)部存在多級別的緩存設(shè)計(jì),提升系統(tǒng)性能;
- 自動故障轉(zhuǎn)移,鏈路上下游主機(jī)可以自動發(fā)現(xiàn)和剔除故障主機(jī),快速恢復(fù)服務(wù);
- 多集群部署,鏈路中各個(gè)模塊均進(jìn)行了跨機(jī)房的多集群部署,在故障時(shí)能夠進(jìn)行切換;
- 重試策略,針對系統(tǒng)中可重試的場景設(shè)計(jì)重試機(jī)制,保證成功率;
- 網(wǎng)絡(luò)策略優(yōu)化,長連接優(yōu)化,部分模塊內(nèi)部采用更高效的 RPC 調(diào)用;
- 采用更高性能的實(shí)現(xiàn)方式,減少耗時(shí);
- 快慢請求分離,快請求同步慢請求異步的方式提高性能。
底層資源
底層資源的高可用是云開發(fā)服務(wù)高可用的關(guān)鍵一環(huán),這一部分將對 “云函數(shù) ”和 “云數(shù)據(jù)庫” 進(jìn)行分別介紹。
云函數(shù)優(yōu)化
云函數(shù)在高可用性方面進(jìn)行了充分的架構(gòu)考量,在部署上做了充分的冗余,下圖為云函數(shù)高可用的部署架構(gòu)。
從圖中可以看到,云函數(shù)從接入層到資源層,各層均進(jìn)行了多集群的部署,每個(gè)集群都按跨機(jī)房的方式部署。集群內(nèi)單機(jī)或單機(jī)房故障系統(tǒng)能夠自動發(fā)現(xiàn)并且快速剔除,這種部署方式可以應(yīng)對單機(jī)故障、機(jī)房網(wǎng)絡(luò)故障等設(shè)施類故障。集群故障也能夠快速的切換用戶集群來快速恢復(fù)服務(wù),縮短故障時(shí)間,保證高可用性。另外這種部署上的設(shè)計(jì),也便于進(jìn)行更大范圍的橫向擴(kuò)容,提供更大的系統(tǒng)并發(fā)容量,以滿足客戶不斷上漲的業(yè)務(wù)需求。
在云函數(shù)資源底層,面多高并發(fā)請求,首先就需要有充足的能夠承擔(dān)高并發(fā)的計(jì)算資源,云開發(fā)的云函數(shù)底層建立了規(guī)模非常大的資源池,同時(shí)也預(yù)留的大量的 Buffer 資源,云函數(shù)系統(tǒng)從資源池分配資源給函數(shù)實(shí)例,在資源池消耗到一定程度時(shí),系統(tǒng)可以自動化申請?jiān)粕?VM 資源,快速擴(kuò)容資源池,實(shí)現(xiàn)多層次的水平彈性伸縮,以應(yīng)對開發(fā)者可能的海量業(yè)務(wù)需求。
同時(shí),在發(fā)布策略上,按集群進(jìn)行逐步的灰度,如果出現(xiàn)系統(tǒng) Bug,能夠只影響少量請求。
目前,云函數(shù)已經(jīng)完成了新一輪的系統(tǒng)架構(gòu)升級,以更高的可用性和性能,應(yīng)對未來更大并發(fā)的挑戰(zhàn)。
云函數(shù)在執(zhí)行性能方面,也做了非常多的優(yōu)化。熟悉云開發(fā)的開發(fā)者應(yīng)該了解,函數(shù)在一次調(diào)用中會涉及到函數(shù)的啟動,啟動又可以分為冷啟動和熱啟動,熱啟動是非??焖俚?,而冷啟動則相對較慢。
冷啟動的過程如圖所示,對比可以看出,冷啟動需要?jiǎng)?chuàng)建函數(shù)實(shí)例,創(chuàng)建過程又包含多個(gè)子任務(wù),如下載函數(shù)代碼、部署函數(shù)等,通常需要幾百毫秒的耗時(shí)。
啟動耗時(shí)對于云函數(shù)性能來說是非常關(guān)鍵的,所以云函數(shù)性能的優(yōu)化重點(diǎn)之一就在于減少冷啟動率和冷啟動耗時(shí)。云函數(shù)在啟動耗時(shí)方面也做了諸多優(yōu)化:
- 優(yōu)化代碼下載耗時(shí),在虛擬機(jī)內(nèi)和可用區(qū)內(nèi)建立多級緩存,提升下載云函數(shù)代碼包下載速度;
- 優(yōu)化函數(shù)網(wǎng)絡(luò)部署策略,降低部署耗時(shí);
- 優(yōu)化容器啟動,降低啟動時(shí)間;
- 基于用戶請求量變化趨勢和周期性的請求量變化規(guī)律,對云函數(shù)并發(fā)量進(jìn)行準(zhǔn)實(shí)時(shí)預(yù)測,提前進(jìn)行擴(kuò)縮容量;
- 支持版本別名,用戶更新代碼, 以 Rolling Update 方式進(jìn)行新舊版本替換,保證熱啟動率;
- 優(yōu)化函數(shù)實(shí)例預(yù)留時(shí)間,保證整體的低冷啟動率。
云函數(shù)底層也采用了騰訊云自研的輕量級虛擬化技術(shù),MicroVm 啟動時(shí)間縮短至 90 毫秒,函數(shù)冷啟動減低至 200 毫秒,并且支持上萬臺計(jì)算節(jié)點(diǎn)同時(shí)擴(kuò)容;
目前,經(jīng)過函數(shù)底架構(gòu)上和性能上的不斷優(yōu)化,部署云函數(shù)實(shí)例的各階段耗時(shí)也在不斷減少,進(jìn)而云函數(shù)的冷啟動時(shí)間不斷降低。為客戶提供更高的可用性和性能支持。
云開發(fā)目前為開發(fā)者提供單個(gè)云函數(shù) 1000 并發(fā)的能力支持,假設(shè)云函數(shù)的執(zhí)行時(shí)間為 100ms,單個(gè)云函數(shù)可以達(dá)到 10000 QPS,這已經(jīng)可以滿足大部分用戶場景的需求了,50 個(gè)云函數(shù)的總 QPS 將可以達(dá)到 50W QPS。
云數(shù)據(jù)庫優(yōu)化
云數(shù)據(jù)庫在接入層和數(shù)據(jù)庫底層也做了非常多的專項(xiàng)優(yōu)化,同時(shí)也在部署方面進(jìn)行了諸多方面的設(shè)計(jì)。云數(shù)據(jù)庫的部署架構(gòu)如圖所示。
從架構(gòu)圖中可以看到,云數(shù)據(jù)庫接入層進(jìn)行了分層設(shè)計(jì)并支持水平橫向擴(kuò)容,所有用戶請求會被分配到不同的主機(jī)上,每個(gè)主機(jī)都獨(dú)立的維護(hù)用戶數(shù)據(jù)庫連接,這種方式保證了數(shù)據(jù)庫接入層能夠大規(guī)模進(jìn)行水平擴(kuò)展。另外,在部署上也進(jìn)行了多集群的策略部署,集群內(nèi)部能夠自動發(fā)現(xiàn)故障主機(jī)并剔除。不同用戶分配到不同的接入集群,用戶請求可在多集群上進(jìn)行靈活調(diào)度,以應(yīng)對可能出現(xiàn)的服務(wù)故障,提供更高的可用性和更短的恢復(fù)時(shí)間。
在發(fā)布策略上也能做到更加可靠,按集群進(jìn)行進(jìn)行灰度,影響范圍小。
數(shù)據(jù)庫引擎實(shí)例也均進(jìn)行了跨主機(jī)的多數(shù)據(jù)庫實(shí)例的部署,在單數(shù)據(jù)庫實(shí)例故障時(shí)能夠進(jìn)行自動化的轉(zhuǎn)移。
數(shù)據(jù)為每個(gè)數(shù)據(jù)實(shí)例進(jìn)行每日的全量備份并保存到對象存儲中,以保證用戶數(shù)據(jù)安全,當(dāng)用戶數(shù)據(jù)出現(xiàn)問題時(shí),可進(jìn)行數(shù)據(jù)回檔,也間接的為用戶提供了一定的業(yè)務(wù)可用性支持。
數(shù)據(jù)底層也將支持在線熱遷移,在出現(xiàn)主機(jī)負(fù)載過較高時(shí),自動在線熱遷移用戶實(shí)例到負(fù)載低的主機(jī),此過程用戶幾乎是無感知的。熱遷移同時(shí)也能夠支持全局的數(shù)據(jù)庫主機(jī)間的負(fù)載均衡。
數(shù)據(jù)庫目前也已經(jīng)提供自動加索引能力,自動化的分析用戶慢查詢請求并針對性的進(jìn)行自動索引優(yōu)化,能夠在用戶無感知的情況下優(yōu)化用戶查詢性能,使開發(fā)者可以更少的關(guān)心數(shù)據(jù)庫性能優(yōu)化就可以有優(yōu)良的性能體驗(yàn),降低客戶負(fù)擔(dān),更加專注于自身的業(yè)務(wù)邏輯。
4. 高并發(fā)業(yè)務(wù)如何利用云開發(fā)進(jìn)行優(yōu)化?
雖然云開發(fā)為開發(fā)者提供便利的云服務(wù)能力,同時(shí)也期望能夠盡可能的解決開發(fā)者在使用過程中遇到的所有問題,但顯然,這是一個(gè)永無止境的長期追求。
其實(shí)開發(fā)者在這方面也可以有很大的想象和發(fā)揮空間。開發(fā)者在面對高并發(fā)需求時(shí),可以通過云開發(fā)做哪些優(yōu)化呢?
通常高并發(fā)業(yè)務(wù)按并發(fā)量上漲模型來劃分,可以分為以下兩種形式:
- 業(yè)務(wù)量相對平緩上漲,并發(fā)量逐步上升,上升速度平緩,系統(tǒng)有充足的預(yù)熱時(shí)間;
- 業(yè)務(wù)并發(fā)量爆發(fā)上漲,并發(fā)量瞬間上升,上升速度很快,例如常見的秒殺類業(yè)務(wù)。
對于第一種并發(fā)量以較均勻的速度上漲的業(yè)務(wù),直接使用云開發(fā)就可以輕松應(yīng)對。對于第二種呈爆發(fā)式上漲的業(yè)務(wù),通過一定的策略和技術(shù)上的優(yōu)化,也能較輕松應(yīng)對。
云函數(shù)在應(yīng)對高并發(fā)請求的難點(diǎn)在于彈性,彈性支持了服務(wù)資源的按需部署,因此可以為開發(fā)者節(jié)省了大量資源花費(fèi)。但也是因?yàn)閺椥?,在面對瞬時(shí)高并發(fā)需求時(shí),服務(wù)瞬間面對比上之前大幾十倍甚至上百倍的并發(fā)請求,云函數(shù)伸縮系統(tǒng)難以預(yù)料這種爆發(fā)性上漲,因?yàn)槔鋯雍臅r(shí)相對較長,彈性擴(kuò)容機(jī)制難以在秒級時(shí)間內(nèi)實(shí)現(xiàn)大量云函數(shù)實(shí)例部署,無法跟上并發(fā)上漲的速度,熱啟動率降低,啟動時(shí)間變長,進(jìn)而導(dǎo)致部分請求超時(shí),甚至出現(xiàn)超并發(fā)的情況,進(jìn)而導(dǎo)致活動參與者因參與失敗而放棄,活動效果達(dá)不到預(yù)期。如何解決這個(gè)問題呢?
策略上的優(yōu)化方案
- 提前評估活動并發(fā)量及 QPS 等指標(biāo);
- 充分進(jìn)行活動預(yù)熱,在活動越熱階段統(tǒng)計(jì)和再評估參與人數(shù)及并發(fā)量;
- 在活動預(yù)熱頁面通過埋點(diǎn)代碼的方式對業(yè)務(wù)云函數(shù)進(jìn)行預(yù)熱,通過參數(shù)控制不執(zhí)行業(yè)務(wù)邏輯即可,也可以通過其他方式或多種方式進(jìn)行預(yù)熱;
- 在評估并發(fā)量之后也別忘記評估套餐是否能滿足業(yè)務(wù)需求,云開發(fā)提供按量計(jì)費(fèi)和包年包月兩種計(jì)費(fèi)模式,業(yè)務(wù)方可以根據(jù)實(shí)際情況調(diào)整套餐,或者切換為按量計(jì)費(fèi),避免因套餐限制影響業(yè)務(wù)。
技術(shù)上的優(yōu)化方案
技術(shù)上的優(yōu)化核心就一點(diǎn):降低耗時(shí)。
云函數(shù)方面,可通過以下方式進(jìn)行優(yōu)化:
- 減少調(diào)用依賴服務(wù)的次數(shù),如進(jìn)行請求合并;
- 降低依賴服務(wù)的響應(yīng)時(shí)間,如數(shù)據(jù)查詢耗時(shí),其他接口調(diào)用耗時(shí)等;
- 并發(fā)調(diào)用依賴服務(wù);
- 根據(jù)業(yè)務(wù)邏輯合并多個(gè)函數(shù)到單個(gè)函數(shù)、或拆分單云函數(shù)到多個(gè)云函數(shù);
- 精簡代碼、減少依賴、降低函數(shù)體積,縮短冷啟動時(shí)間。
數(shù)據(jù)庫方面,盡管云開發(fā)已經(jīng)針對數(shù)據(jù)庫查詢進(jìn)行了自動化的索引優(yōu)化,但是系統(tǒng)對于用戶業(yè)務(wù)邏輯和數(shù)據(jù)的設(shè)計(jì)是遠(yuǎn)遠(yuǎn)不能及業(yè)務(wù)方的,所以業(yè)務(wù)方研發(fā)團(tuán)隊(duì)可以在查詢性能等多方面進(jìn)行優(yōu)化。針對高并發(fā)的場景,一些優(yōu)化建議如下:
- 通過創(chuàng)建高效索引,提升數(shù)據(jù)庫查詢效率;
- 通過優(yōu)化設(shè)計(jì),減少數(shù)據(jù)庫查詢;
- 采用高效的查詢條件;
- 減少返回?cái)?shù)據(jù)的條數(shù)以及字段數(shù),降低數(shù)據(jù)庫的查詢時(shí)間以及網(wǎng)絡(luò)數(shù)據(jù)傳輸時(shí)間;
- 減少事務(wù)的使用,盡量用替代方式;
- 聚合類需求如排行榜等,可保存中間結(jié)果到數(shù)據(jù)庫或緩存,避免每次進(jìn)行統(tǒng)計(jì)計(jì)算;
- 數(shù)據(jù)量較大,可對集合水平拆分,降低單集合數(shù)據(jù)量,提升查詢效率。
實(shí)際上,盡管云開發(fā)數(shù)據(jù)庫資源層從云服務(wù)的角度來說是海量的,但是單個(gè)數(shù)據(jù)庫實(shí)例計(jì)算能力是有硬件上限的,當(dāng)出現(xiàn)較多慢查詢時(shí),數(shù)據(jù)庫系統(tǒng)將會大打折扣,將會影響大量數(shù)據(jù)庫操作,整體上會拖慢開發(fā)者自身業(yè)務(wù)響應(yīng)時(shí)間,影響業(yè)務(wù)能力。云開發(fā)也計(jì)劃推出慢查詢?nèi)罩?、慢查詢告警等方面的能力,提供?shù)據(jù)庫優(yōu)化最佳實(shí)踐。
其他建議:
- 對系統(tǒng)進(jìn)行一定程度的實(shí)際壓測,驗(yàn)證設(shè)計(jì)實(shí)現(xiàn)是否符合預(yù)期,并提前解決,避免活動上線之后達(dá)不到效果;
- 獨(dú)立活動業(yè)務(wù)實(shí)現(xiàn),避免活動影響現(xiàn)有業(yè)務(wù)。
5. 作者介紹
艷杰,騰訊高級前端開發(fā)工程師,云開發(fā)團(tuán)隊(duì)核心開發(fā)專注于中后臺系統(tǒng)開發(fā)以及系統(tǒng)架構(gòu)設(shè)計(jì)。