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