作者:計緣,阿裡雲解決方案架構師
雲原生架構是什麼
回顧過去十年,數字化轉型驅動着技術創新和商業元素的不斷融合和重構,可以說,現在已經不是由商業模式決定采用何種技術架構,而是由技術架構決定企業的商業模式。是以無論是行業巨頭還是中小微企業都面臨着數字化轉型帶來的未知機遇和挑戰。機遇是商業模式的創新,挑戰來自對整體技術架構的變革。
新一代的技術架構是什麼?如何變革?是很多網際網路企業面臨的問題。而雲原生架構則是這個問題最好的答案,因為雲原生架構對雲計算服務方式與網際網路架構進行整體性更新,深刻改變着整個商業世界的 IT 根基。
雖然雲原生的概念由來已久,很多人并不了解什麼是雲原生。從技術的角度來講,雲原生架構是基于雲原生技術的一組架構原則和設計模式的集合,旨在将雲應用中的非業務代碼部分進行最大化的剝離,進而讓雲設施接管應用中原有的大量非功能特性(如彈性、韌性、安全、 可觀測性、灰階等),使業務不再受非功能性業務中斷困擾的同時,具備輕量、靈活、高度自動化的特點。簡單的說,就是幫助企業的業務功能疊代更快、系統能承受住各種量級的流量沖擊的同時,建構系統的成本更低。
傳統架構與雲原生架構的差別
上圖展示了在代碼中通常包括的三部分内容,即業務代碼、第三方軟體、處理非功能特性的代碼。其中“業務代碼”指實作業務邏輯的代碼。“三方軟體”是業務代碼中依賴的所有三方庫,包括業務庫和基礎庫。“處理非功能性的代碼”指實作高可用、安全、可觀測性等非功能性能力的代碼。
這三部分中隻有業務代碼是對業務真正帶來價值的,另外兩個部分都隻算附屬物,但随着軟體規模的增大、業務子產品規模變大、部署環境增多、分布式複雜性增強,使得今天的軟體建構變得越來越複雜,對開發人員的技能要求也越來越高。雲原生架構相比較傳統架構前進了一大步,即從業務代碼中剝離了大量非功能性特性到 IaaS 和 PaaS 中,進而減少業務代碼開發人員的技術關注範圍,通過雲服務的專業性提升應用的非功能性能力。
這便是雲原生架構的核心思路。
為什麼需要雲原生架構
解釋完什麼是雲原生架構後,大家可能會有進一步的思考,即當今網際網路企業為什麼需要雲原生架構。分析下SaaS的市場規模可以發現,2019年SaaS市場規模為360億元,2020年仍保持可觀上漲趨勢,2022年SaaS市場規模預計破千億。
縱觀中國企業級SaaS行業發展曆程,大體分為四個階段:2015年之前,中國市場和絕大多數中國企業對“什麼是SaaS”缺乏基本認知,基于私有部署的傳統軟體形式仍為主流,企業級SaaS市場方興未艾。到了2015年,随着雲計算技術的進一步成熟,中國企業級SaaS行業進入快速成長階段,這個慢賽道逐漸為公衆所知。
時至今日,在疫情、經濟、社會環境的大背景下。網際網路企業開始尋求新的商業模式,一些抓住機會的SaaS企業實作了快速響應,結果是其業務呈現成倍增長,比如:
- 餐飲SaaS廠商幫助線下餐飲門店開發小程式點餐系統,實作無接觸點餐。
- 電商零售領域的ERP廠商幫助企業建立會員管 理系統。
- 營銷SaaS廠商通過流量平台幫助企業線上營銷,遠端觸達客戶。
是以,在“如何活下去”成為熱門議題的背景下,快速響應能力成為企業之間的核心競争優勢,SaaS企業需要及時滿足市場的新需求。而這正是前幾年中國SaaS企業為了快速占領市場、盲目跟風、一味借鑒國外産品所産生的天生缺陷。為彌補這些缺陷,SaaS廠商需要根據市場的需求快速調整産品服務方向,業務功能要多元化,業務體系需要新的枝杈,在技術上也有更大的挑戰。
除了市場帶來的壓力,SaaS企業自身也有諸多痛點:
- 大多SaaS産品隻做所謂的通用能力,或者隻是一味模仿國外産品,一旦深入到行業屬性比較重的場景時便無法滿足需求,是以被貼上了“半成品”的标簽,導緻市場接受程度不如預期。
- 産品子產品單一、功能相似的SaaS産品很容易陷入價格競争,最後隻能以虧損獲得網絡效應,但會終食惡果。
- 市場對SaaS産品的定制化需求過多,使得SaaS企業缺乏對産品打磨的精力,把一個SaaS型公司做成了項目型公司。
SaaS企業解決以上的外憂内患的核心就是專注在業務。要做好一款SaaS産品,對于業務管道、競争格局、使用者體驗等諸多方面都有更加嚴苛的要求,甚至從市場營運、産品經理到研發、運維都要專注在業務,所有這些角色的本職工作都應該為行業業務服務,行業的深度分析,快速響應市場,穩定的産品品質這些是必須要具備的。但這就要求技術具備更快的疊代速度,業務推出速度從按周提升到按小時,每月上線業務量從“幾十 / 月”提升到“幾百 / 天”,并且不可接受業務中斷。
另一個網際網路企業需要雲原生轉型的原因是中國的劉易斯拐點已經到來。劉易斯拐點,即勞動力過剩向短缺的轉折點,是指在工業化程序中,随着農村富餘勞動力向非農産業的逐漸轉移,農村富餘勞動力逐漸減少,最終達到瓶頸狀态。用大白話說就是中國的人口紅利已經逐漸消退,企業勞動力成本不斷增加,加上2020年疫情的影響,成本因素越來越成為企業的重要考量。而SaaS産品訂閱制付費、通用性強、低部署成本的特點,便成了企業降本增效的新選擇。這是SaaS企業在市場中的機會,而且對于SaaS企業本身來說,同樣有降本增效的需求,而且内部降本增效做得越好,SaaS産品在市場上的競争力會更加明顯。
以上這些現狀的解法和雲原生架構和核心能力不謀而合:
- 雲原生将三方軟體和非功能性能力的完全兜底,可以極大程度解放企業研發、運維人員的精力,并使其可以專注在業務上。
- 系統的橫向擴充性、高可用性、健壯性、SLA由雲原生架構兜底,解決了SaaS産品最忌諱的穩定性問題。
- 将一些自建的元件遷移至雲原生架構中,對傳統的部署方式和資源進行雲原生化,GitOps的落地,在資源成本和人力成本方面都有進一步的優化。
如何落地雲原生架構
在聊如何落地雲原生架構之前,我們先來看一看雲原生架構成熟度模型(SESORA):
雲原生架構成熟度模型
雲原生架構成熟度模型有六個評判次元,可以将成熟度劃分為4個級别。我會從自動化能力、無服務化能力、彈性能力、可觀測性、韌性能力這五個次元,貫穿說明如何落地雲原生架構。
傳統架構
上圖展示的是一個較傳統的Java+SpringCloud架構應用服務側的部署架構。除了SLB,基本上所有的元件都部署在ECS上。下面我們來一起看看如何将這個架構轉型為雲原生架構。
無服務化(Serverless)
Serverless的概念是什麼在這篇文章不在贅述,可以參閱
這篇文章進行了解。使用ECS叢集部署服務的架構有兩個顯著的短闆:
- 運維成本高:ECS的各項狀态、高可用都需要運維同學維護。
- 彈性能力不足:每次有大促活動時,都需要提前購買ECS,擴充服務的節點數,然後再釋放,并且這種情況隻适用于定時定點的活動,如果是不定時的流量脈沖則無法應對。
是以首先我們要将服務的部署方式Serverless化,我們可以選擇Serverless App Engine(SAE)作為服務應用的釋出、部署平台。SAE是面向應用的Serverless PaaS平台,能夠幫助使用者免運維IaaS、按需使用、按量計費,做到低門檻服務應用雲原生化,并且支援多種語言和高彈性能力。
命名空間
打開
SAE控制台,我們首先建立命名空間,SAE的命名空間可以将其下的應用進行網絡和資源的邏輯隔離,通常我們可使用命名空間來區分開發環境、測試環境、預發環境、生産環境。
建立應用
建立好命名空間後,我們進入應用清單,即可選擇不同的命名空間,看到其下的應用或者建立應用:
選擇對應的命名空間,然後建立應用:
- 應用名稱:服務名稱,使用者自行輸入。
- 專有網絡配置:
-
- 自動配置:自動幫使用者配置VPC、Vswitch、安全組。這些元件都會新建立。
- 自定義配置:使用者選擇命名空間,VPC,VSwitch以及安全組。一般選擇自定義配置,因為咱們的服務所屬的VPC肯定要和其他雲資源的VPC是相同的,這樣才能保證網絡暢通。這裡需要注意的一點是,當在新的命名空間下第一次建立好應用後,該命名空間就會和所選的VPC進行綁定,之後再建立應用時,該命名空間對應的VPC不可更改。如果需要更改,可以進入命名空間詳情進行更改。
- 應用執行個體數:應用(服務)節點數量,這裡的節點數量按需設定,而且不是最終設定,因為後續可以手動或者自動的擴縮節點數。
- VCPU/記憶體:該應用在運作過程中需要的CPU和記憶體的規格。這裡的規格是單個執行個體數的規格。既如果選擇了2C4G,那麼有2個執行個體的話,就是4C8G。
配置完基本資訊後,下一步進入應用部署配置:
- 技術棧語言:Java語言支援鏡像、War包、Jar包三種部署方式,其他語言支援鏡像部署方式。以Java Jar包方式為例:
-
- 應用運作環境:預設标準Java應用運作環境即可。
- Java環境:目前支援JDK7和JDK8。
- 檔案上傳方式:支援手動上傳Jar包或者配置可以下載下傳Jar包的位址。
- 版本:支援時間戳和手動輸入。
- 啟動指令設定:配置JVM參數。
- 環境變量設定:設定容器環境中的一些變量,便于應用部署後靈活的變更容器配置。
- Host綁定設定:設定Host綁定,便于通過域名通路應用。
- 應用健康檢查設定:用于判斷容器和使用者業務是否正常運作。
- 應用生命周期管理設定:容器側的生命周期腳本定義,管理應用在容器在運作前和關閉前的一些動作,比如環境準備、優雅下線等。
- 日志收集服務:和SLS日志服務內建,統一管理日志。
- 持久化存儲:綁定NAS。
- 配置管理:通過挂載配置檔案的方式向容器中注入配置資訊。
我使用Jar包的方式部署完應用後,在對應命名空間下就可以看到剛剛建立的應用了:
點選應用名稱可以檢視應用詳情:
綁定SLB
因為ServiceA在架構中是對外提供接口的服務,是以需要對該服務綁定公網SLB暴露IP和做負載均衡,在SAE中,綁定SLB非常簡單,在詳情頁中,即可看到應用通路設定:
添加SLB時可以選擇建立也可以選擇已經建立好的SLB:
服務/配置中心
對于微服務架構,服務中心和配置中心是必不可少的,大家常用到一般是Nacos、Eureka、ZooKeeper三種。對于雲原生架構來講,根據不同的場景,服務/配置中心可以有以下幾種選擇:
對于現狀就是使用Nacos的客戶而言,轉型雲原生架構,服務/配置中心如上面表格所示有兩種選擇:
- 需要快速轉型,對服務/配置中心高可用要求不是特别極緻的情況下,建議直接使用SAE自帶的Nacos即可,代碼不需要做改動,直接在SAE中建立應用即可。SAE控制台提供的配置管理在界面操作和功能上和開源Nacos的控制台基本一緻。
- 對服務/配置中心高可用要求比較高的情況下,建議使用MSE Nacos,它的優勢是獨享叢集,并且節點規格和節點數量可以根據實際情況動态的進行調整。唯一不足的一點就是需要修改Nacos的接入點,算是有一點代碼侵入。
對于現狀是使用Eureka和ZooKeeper的客戶而言,建議直接使用MSE Eureka和MSE ZooKeeper。
這裡我簡單介紹一下MSE。
微服務引擎MSE(Microservice Engine)是一個面向業界主流開源微服務架構Spring Cloud和Dubbo一站式微服務平台,提供治理中心、托管的注冊中心和托管的配置中心。這裡我們用到的是MSE的托管注冊中心和托管配置中心。
MSE有三塊核心的功能點:
- 支援三大主流服務中心,節點規格和數量靈活搭配,可在運作時動态調整節點規格/數量。
- 通過命名空間邏輯隔離不同環境。
- 配置變更實時推送并且可追蹤。
彈性能力(Elasticity)
雲原生架構成熟度模型中的彈性能力同樣依托于SAE來實作,因為Serverless的底層實作原理,是以在SAE中的應用執行個體數(節點數)擴縮速度非常快,可達到秒級。
進入應用詳情頁的執行個體部署資訊,可以看到應用的具體執行個體:
SAE提供了兩種擴縮應用執行個體數的方式,手動方式和自動方式。
手動擴縮
在控制台右上方有手動擴縮操作按鈕,然後選擇要擴縮到的執行個體數即可:
當進行擴縮時,我們可以看到具體執行個體的變更狀态:
自動擴縮
在控制台右上角有自動擴縮操作按鈕,然後可以看到建立擴縮規則的界面。SAE自動擴縮提供時間政策和名額政策兩種。
上圖是時間政策,即設定好具體的時間節點,在這個時間節點要将應用的執行個體數擴到幾個或者縮到幾個。這種政策适合流量高峰期有相對明确時間節點的場景,比如線上教育的客戶,通常流量高峰在晚上8點開始,11點逐漸結束,這種情況下,通過定時政策在7點半左右把應用的執行個體數擴起來,然後11點之後逐漸把應用執行個體數縮回正常。
上圖是名額政策,目前提供CPU使用率、記憶體使用率、應用的QPS閥值、應用接口平均響應時間(RT)閥值四種名額,這四種名額可以配合使用。當這四種名額其中有一種達到閥值後就會觸發擴容,會對應用執行個體進行逐漸擴容。當名額小于閥值後觸發縮容。這種政策适合流量高峰時間不固定的場景,比如市場營銷,遊戲營運。
成本優化
對于彈性能力,大家可能更多的是關注它能讓系統快速支撐流量脈沖,增加系統橫向擴充的能力。其實因為SAE有極緻的彈性能力,再加上按分鐘、按量計費的模式,對整體的資源成本是有一定優化的。
可觀測性(Observability)
應用側的可觀測性分兩個次元,一是縱向的Metrics名額,比如主機的CPU、記憶體、磁盤各項名額,Pod的CPU、記憶體各項名額,JVM的Full GC、堆記憶體、非堆記憶體各項名額。另一個次元是橫向的請求調用鍊路監測,上遊服務到下遊服務的調用、上遊接口到下遊接口的調用。
在監控微服務架構時,通常需要從三個角度來看:
- 應用的整體健康狀況。
- 應用每個執行個體的健康狀況。
- 應用每個接口的健康狀況。
而SAE對應用的監控也都覆寫了上述這兩個次元和三個角度。
應用整體健康狀況
進入應用詳情頁,點選左側菜單中的應用監控/應用總覽,便可以看到應用的整體狀況:
- 總請求量:可以一目了然的看到請求量是否明顯的異常,比如驟降或者陡升。
- 平均響應時間:應用整體接口的平均響應時間,這個名額直接反映最真實的應用健康狀況。
- Full GC:JVM裡比較重要的名額,也是會直接影響系統性能的因素。
- 慢SQL:智能抓取執行時間大于500ms的SQL。
- 一些曲線視圖:幫助我們掌握不同時段的應用情況。
應用執行個體節點健康狀況
進入應用詳情頁,點選左側菜單中的應用監控/應用詳情,便可以看到應用每個節點的資訊:
從上圖可以看到,左側會列出目前應用的所有執行個體節點,包括該節點的平均響應時間、請求次數、錯誤數、異常數。如果我們按照影響時間降序排序,比較靠上的節點就是響應時間較慢的節點,然後我們就需要分析是什麼原因導緻這些節點的響應時間較慢。是以,右側會提供了一些檢查次元來幫助我們分析排查問題。
比如檢視JVM名額:
應用接口健康狀況
進入應用詳情頁,點選左側菜單中的應用監控/接口調用,便可以看到應用每個接口的資訊:
接口監控和應用執行個體節點監控的思路一緻,左側會列出所有請求過的接口,同樣顯示了響應時間、請求數、錯誤數,右側同樣提供了一些檢查次元來幫助我們分析接口RT高的原因。
比如檢視SQL調用分析:
縱向Metrics名額
在上述三個角度中,其實已經涵蓋了絕大多數Metrics名額,比如有應用健康狀态的名額、JVM的名額、SQL名額、NoSQL名額等。
橫向調用鍊路
在很多時候,我們單純的看Metrics名額是無法确定問題的根本原因的,因為會涉及到不同服務之間的調用,不同接口之間的調用,是以需要檢視服務和服務之間、接口和接口之間的調用關系以及具體的代碼資訊。在這個次元上,SAE內建的ARMS的監控能力便可以實作。我們在應用監控/接口調用/接口快照中可以看到有請求的接口快照,通過TraceID便可以檢視該接口的整體調用鍊路:
從上面這個圖我們可以看出很多資訊:
- 該接口在服務級别的完整請求鍊路,比如ikf(前端)-> ikf-web(java服務)-> ikf-blog(java服務)-> ikf-blog(java服務)
- 每個服務的狀态情況,比如狀态一列是紅點,說明在這個環節是有異常出現的。
- 在每個服務中請求的接口名稱。
- 每個服務的請求耗時。
除了上述這些顯性的資訊以外,還有一些隐性的資訊:
- 上遊服務ikf-web的總耗時是2008ms,但下遊服務ikf-blog的總耗時是5052ms,而且耗時起點是一樣的,說明ikf-web到ikf-blog是一個異步調用。
- 既然ikf-web到ikf-blog是異步調用,然而ikf-web的耗時有2s之多,說明ikf-web服務中的接口也有問題。
- 在ikf-blog服務中,又有内部接口被調用,因為從調用鍊上出現了兩個ikf-blog,并且這個内部調用是同步調用,而且問題出現在最後一個接口調用上。
從以上這些資訊可以幫我們縮小和圈定問題根因出現在哪個環節的範圍,然後我們可以點選方法棧一列的放大鏡,檢視具體的方法棧代碼資訊:
從方法棧這裡我們又可以得到很多顯性資訊:
- 具體的方法。
- 每個方法的耗時。
- 方法産生的具體異常資訊。
- 資料庫操作的具體SQL語句,甚至SQL上的Binding Value。
當然除了顯性資訊外,還有一個比較重要的隐性資訊,比如我們可以看到
BlogController.findBlogByIsSelection(int isSelection)
這個方法的耗時是5s,但是該方法内部的資料庫操作的耗時很少,隻有1ms,說明耗時是屬于業務代碼的,畢竟業務代碼我們是抓不到也不會去抓取資訊的。這時我們可以有兩種方式去定位具體問題:
- 從方法棧資訊中已經知道了具體的服務和具體的方法,那麼直接打開IDE檢視、分析代碼。
- 檢視方法棧頁簽旁邊的線程剖析,也基本可以确定問題所在。比如上圖這個情況,我們檢視線程剖析後會發現他的耗時是因為
。java.lang.Thread.sleep( ):-2 [3000ms]
韌性能力(Resilience)
對于雲原生架構的韌性能力,我會從優雅上下線、多AZ部署、限流降級三個方面來聊一聊。
優雅上下線
一個好的産品,要能快速應對使用者對産品功能、能力具有普适性的回報和意見,能快速響應市場需求的變化。那麼産品的功能就需要快速的做疊代和優化,從IT層面來看,就是要有快速、高效、高品質的釋出變更流程,能夠随時進行生産環境的服務釋出。
但是這會帶來一個核心問題,即頻繁的服務釋出,并且不能影響使用者體驗,使用者的請求不能斷流。是以這就要求我們的系統部署架構中有優雅上下線的能力。
以微服務架構來說明,雖然開源的産品有能力和方案做到近似優雅上下線,但也是近似做到,當釋出服務節點較多的情況下依然會有斷流的情況。是以開源方案有諸多問題:
- 注冊中心不可靠、通知不及時。
- 用戶端輪訓不實時、用戶端緩存。
- 自定義鏡像非1号程序,Sigterm信号無法傳遞。
- 無預設優雅下線方案,需要添加actuator組建。
在無服務化/服務配置中心章節中,我闡述了SAE自帶的服務中心和MSE的服務中心,無論使用那種方案,我們都對優雅上下線做了進一步的優化。
從上圖可以看到,部署在SAE的應用具有主動通知服務中心和服務消費者的能力,再結合Liveness應用執行個體探活和Readiness應用業務探活的機制,能讓我們的服務在進行部署和因為其他原因挂掉時不會影響使用者的正常通路。
多AZ部署
本着雞蛋不能放在一個籃子裡的原則,一個應用的多個節點,應該分布在不同的可用區,這樣整體應用的高可用和健壯性才是足夠好的。SAE支援設定多個交換機(VSwitch),每個交換機可以在不同的可用區,這樣在部署、擴容應用的節點時會随機從可選的可用區拉起執行個體:
這就避免了當某個可用區出現問題挂掉時,整體系統因為在一個可用區而挂掉,這也是最基本的同城多活的實踐。
限流降級
限流降級是系統斷臂求生的能力,在遇到突發的流量脈沖時,可以及時限制流量,避免整個系統被擊穿,或者當流量超出預期時,及時切斷非核心業務,釋放資源來支撐核心業務。
目前對于Java應用,SAE也支援限流降級的能力,首先對應用的所有接口的請求名額進行抓取和監控:
然後我們可以針對每一個接口設定流控、隔離、熔斷的規則,比如我對
/checkHealth
接口設定一條流控規則:
當該接口的QPS達到50後,單個機器超過50的請求将快速失敗。比如我們對一個有6個節點的應用進行壓測時,可以看到每個節點的QPS情況:
當開啟流控規則後,可以立即看到限流的效果:
可以看到QPS被精準的控制到50,超過50的請求直接傳回失敗。
自動化能力(Automation)
在自動化能力方面,我主要從CICD流程這個次元來聊一聊。大家從上面章節的截圖可以看到,有很多是SAE控制台的截圖,在實際應用中肯定不會通過控制台來一個一個釋出應用,必然都是通過CICD流程來做自動化的應用打包和釋出流程。
SAE在這個方面提供兩種實作自動化運維的方式。
基于Gitlab和Jenkins
目前很多企業的CICD流程都是基于Gitlab和Jenkins來做的,那麼SAE也支援将釋出的操作內建到這種方案裡。這個方案的核心是SAE會提供一個Maven插件,同時對應有三個配置檔案,Maven插件通過這三個配置檔案中的資訊将打包好的Jar/War或者鏡像釋出到對應的SAE應用中。
- toolkit_profile.yaml:配置RegionID、AccessKey ID、AccessKey Secret。
- toolkit_package.yaml:配置比如應用部署包類型、部署包位址、鏡像位址。
- toolkit_deploy.yaml:配置比如SAE應用的ID、應用所屬命名空間ID、應用名稱、釋出方式等。
更詳細的配置資訊可以參閱該
文檔然後在Jenkins的任務中,對Maven設定如下的指令即可:
clean package toolkit:deploy -Dtoolkit_profile=toolkit_profile.yaml -Dtoolkit_package=toolkit_package.yaml -Dtoolkit_deploy=toolkit_deploy.yaml
這樣就可以很容易的将SAE的部署流程內建到基于Gitlab和Jenkins的CICD方案裡了。
基于Open API
還有一些企業會自己研發運維平台,運維賦能研發,由研發同學在運維平台上進行運維操作。面對這種場景,SAE提供了豐富的Open API,可以将SAE控制台上90%的能力通過Open API內建到客戶自己的運維平台中。詳細的OpenAPI說明可以參與該
總結
基于SAE武裝過系統後,整體的部署架構會變成這樣:
雲原生架構成熟度模型(SESORA)在我闡述的這五個次元一共是15分,基于SAE的雲原生架構在這五個次元會達到12分:
- 無服務化:3分
- 彈性能力:3分
- 可觀測性:2分
- 韌性能力:2分
- 自動化能力:2分
對于上手、實踐、落地快捷簡單,又能達到比較好的雲原生架構成熟度的SAE方案,大家還在等什麼呢?一起實踐起來吧。如果大家有任何問題,可以加入釘釘群:35712134來尋找答案,我們不見不散!
掃碼了解更多技術幹貨與客戶案例: