作為一個后端研發(fā)人員,開發(fā)服務接口是我正常不過的工作了,這些接口不管是面向前端 HTTP 或者是供其他服務 RPC 遠程調(diào)用的,都繞不開一個共同的話題就是“高可用”,接口開發(fā)往往看似簡單,但保證高可用這塊實現(xiàn)起來卻不并沒有想想的那么容易,接下來我們就看一下,一個高可用的接口是該考慮哪些內(nèi)容,同時文中有不足的歡迎批評指正。
基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
到底啥是高可用
用一句簡單的話來概就是我們的系統(tǒng)具不具備應對和規(guī)避風險的能力。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
項目地址:https://github.com/YunaiV/yudao-cloud
視頻教程:https://doc.iocoder.cn/video/
為啥做高可用
程序都是有人開發(fā)的,在開發(fā)過程中會犯錯從而導致線上事故的發(fā)生
系統(tǒng)運行依賴各種運行環(huán)境:CPU、內(nèi)存、硬盤、網(wǎng)絡等等,而這些都有可能損壞
業(yè)務拉新用戶正在注冊賬號,結果注冊接口掛了用戶體驗受影響
雙十一、618 等大促大量用戶下單,結果下單服務接口掛了 GMV 受影響等等
其他未知因素等等
總之為了應對這些不可控因素的發(fā)生,我們必須要做高可用
高可用的關鍵點
我們說過高可用的本質(zhì)是系統(tǒng)是否具備應對和規(guī)避風險的能力,那么從這個角度出發(fā)來設計高可用接口的有以下幾個關鍵因素:Dependence(依賴)、Probability(概率)、Time(時長)、Scope(范圍)
依賴的資源相對少
風險的概率足夠低
影響的范圍足夠小
影響時長足夠短
接口高可用設計的幾個原則
結合這些關鍵點,我們來看一下具體具體注意事項
1、控制依賴
能少依賴就少依賴,能不強依賴就不強依賴
少依賴
例如:日常每分鐘 10 個請求,查詢 Mysql 數(shù)據(jù)即可滿足,此時盲目引入 Redis 中間件,不僅浪費資源而且增加系統(tǒng)復雜性
弱依賴
例如:用戶注冊服務強依賴新用戶優(yōu)惠券發(fā)放服務,當優(yōu)惠券發(fā)放服務故障后,整個注冊不可用,好的方式是采用弱依賴,使用異步化的方式,這樣優(yōu)惠券發(fā)送服務不可用時,不會影響注冊鏈路。
2、避免單點
避免單點故障的核心是通過備份或者冗余快速的進行容錯
我們采用多機房多實力部署我們應用來保障故障風險分攤,一旦有一臺服務器出現(xiàn)問題,其他服務仍然能夠繼續(xù)支撐我們的服務
每次上線我們都會保留上一次上線發(fā)布版本,這樣一旦上線的程序出現(xiàn)問題我們能夠快速回滾到上一版本
每個接口至少保障 2 人知道相關業(yè)務,一旦線上服務出現(xiàn)問題,其中任何一人一個能夠快速處理相關線上問題
不管是 Mysql 還是 Redis 等中間件都支持數(shù)據(jù)主備機群部署
類似的例子很多這里就不再一一列舉了
3、負載均衡
將風險進行分攤避免分險擴散
例如:無論是 Ngnix 或者 JSF 的,其負載均衡目的就是盡量的將流量分散到不同的服務器節(jié)點上,這樣可以有效的保障單節(jié)點因系統(tǒng)瓶頸問題而引發(fā)一系列的風險。
像上面這個例子我想每個研發(fā)人員都知道也都會這么做,但是是不是所有的場景我們都考慮到均衡這個問題?
例如:通常為了提高讀并發(fā)的能力,我們會把數(shù)據(jù)緩存到 JIMDB 中,但是因為緩存的 key 出現(xiàn)了熱點數(shù)據(jù)導致 JIMDB 單分片負載過高,恰好,這個分片上也緩存了其他數(shù)據(jù),但是因為 CPU 負載過高,導致查詢性能變差,大量的超時,影響了業(yè)務。所以,我們在接口設計的時候,假如遇到類似場景,也要充分考慮數(shù)據(jù)存儲的均衡性,同時針對熱點數(shù)據(jù)做好監(jiān)控,隨時支持動態(tài)均衡。
4、資源隔離
隔離的目的將風險控制在可控范圍內(nèi),避免風險擴散
例如:接口部署之間服務部署物理上是相互隔離的,避免單機房或者單服務器出現(xiàn)故障影響整個服務
例如:我們在存儲業(yè)務數(shù)據(jù)的時候會將數(shù)據(jù)分庫分表,數(shù)據(jù)通過不同分片存儲,這樣就不會導致某個服務器掛掉影響到整個服務
5、接口限流
限流是一種保護措施,目的是將風險控制在可控范圍內(nèi)
我們在開發(fā)接口的時候,一定要結合業(yè)務流量情況進行限流措施,限流一方面處于對自身服務資源的保護,同時也是對依賴資源的一種保護措施。
目前集團 JSF 在流量控制這塊已經(jīng)有了對應的限流處理能力,同時我們也可以結合實際業(yè)務進行限流模塊的開發(fā)。
6、服務熔斷
熔斷也是一種保護措施,目的是將風險控制在可控范圍內(nèi),避免風險擴散
例如:經(jīng)常我們服務 A 會同時調(diào)用 B、C、D 多個服務,當我們依賴的服務其中一個出現(xiàn)故障或者性能下降的時候,就是導致整體服務可用率下降,所以我們在開發(fā)此類服務的時候,一定要注意接口之間的隔離。我們可以利用類似 Hystrix 組件實現(xiàn),也可以借助 DUCC 進行手動隔離。其實熔斷也是一種控制資源依賴的一種,將強依賴降級為弱依賴
7、異步處理
將同步操作轉(zhuǎn)為異步操作
例如:用戶頁面領取一些權益,針對領取這個服務在大促期間因為用戶流量較大,為了避免系統(tǒng)負載,此時采用 MQ 異步接收用戶領取請求然后進行優(yōu)惠券發(fā)放,這樣不僅極大的減少了事故的影響范圍,也減少問題發(fā)生概率。
8、降級方案
服務降級屬于一種問題發(fā)生后的補救措施,通過服務降級可以減少一部分風險影響范圍
對于重要的服務接口我們都要具備完善的降級方案,這里需要說明的是,降級有損的,我們一定要在系統(tǒng)開發(fā)前就要考慮各種問題發(fā)生的可能,降級的前提是通過降級非核心業(yè)務保證核心業(yè)務運行。
例如:大促峰值期間,一般會提前降級掉很多功能,同時限流,主要是為了保護峰值絕大部分人的交易支付體驗。
9、灰度發(fā)布
通過灰度發(fā)布降低風險影響范圍
例如:我們上線一個新服務,通過一定的灰度策略,讓用戶先行體驗新版本的應用,通過收集這部分用戶對新版本應用的反饋以及對新版本功能、性能、穩(wěn)定性等指標進行評論,進而決定繼續(xù)放大新版本投放范圍直至全量升級或回滾至老版本。根據(jù)線上反饋結果,做到查漏補缺,發(fā)現(xiàn)重大問題,可回滾“舊版本”
10、混沌工程
通過提前對系統(tǒng)進行一些破壞性的手段,提前發(fā)現(xiàn)潛在問題
例如:一個復雜接口系統(tǒng)依賴了太多的服務和組件,這些組件隨時隨地都可能會發(fā)生故障,而一旦它們發(fā)生故障,會不會如蝴蝶效應一般造成整體服務不可用呢,我們并不知道,因此我們可以借助泰山平臺混沌工程進行演練,針對發(fā)生的場景制定各種預案,將風險控制在可控范圍內(nèi)。
編輯:黃飛
評論
查看更多