天天看點

高可用 - 隔離原則

作者:京東雲開發者

前言

當讨論高可用時,那麼必然有與之對應的低可用甚至不可用,但無論是哪種可用描述,其中都暗含了一個大衆共識,即不存在永久穩定運作的系統程式。

事實上,幾十年前圖靈也論證過類似的問題,稱為“停機問題”,具體的描述是:能否為A計算機程式設計,使得程式才能在有限時間内推斷出計算機B是否會停止運作?圖靈使用了十分簡潔但嚴謹的反證法論證了停機問題,具體論證方式在這裡就不贅述了,最終的結論就是不存在這種程式,也就是說,很不幸,我們無法一種可計算的方式解決停機問題。

是以無論是經驗共識還是邏輯論證,我們不得不面對一個現實,即世界上不存在能夠時刻保持穩定的系統程式。

基于這個現實,有無數的天才和應用實踐試圖盡可能的降低機器不可用的機率。是以我想當下談論到高可用時,就是在不斷試錯的路上交流經驗,但幸運的是,在我們之前有無數天才和實踐經驗供我們學習參考。

一、高可用

高可用這一概念是伴随着計算機系統的發展和需求的增長逐漸形成。随着分布式系統的發展和網際網路的普及,需求與技術也在不斷演進和增長,高可用性已經成為現代軟體系統架構中不可或缺的重要組成部分。

對于高可用的定義有很多種描述,但都是圍繞一個主題,即抵禦不确定性,Distributed systems中定義可用性為系統處于正常運作狀态的時間比例,如果使用者無法通路系統,則稱該系統不可用。

如果高可用的問題治理以時間次元劃分,可以大緻分為一下4個階段:分為:事前(故障發生以前)、事發(故障發生到系統或人感覺到故障)、事中(故障發生到故障處理這段時間)、事後(故障結束之後)。按照上述分類,不同的階段可以對應不同的技巧

1.事前:副本、隔離、配額、提前預案、探知

2.事發:監控、報警

3.事中:降級、復原、應急預案,failXXX系列

4.事後:複盤、思考、技改

相比于其他高可用原則而言,隔離原則是十分通用且易懂的,作為保障高可用系統的基石,因為隔離原則最大的作用就是應對為系統提高抵禦各種“黑天鵝事件”的保障原則。

二、隔離原則(Isolation Principle)

2.1、定義

隔離原則作為一個抽象的指導原則,并不屬于某一個具體的研究方向或領域,而是一個跨領域的設計概念。"隔離"字面意義已經描述的很充分,猶如艙壁隔離(Bulkhead Isolation)。

如果要形象的比喻隔離原則在保證系統高可用中的作用,我想可以描述為一艘航行在大海上的巨輪與底層船艙的關系,當風平浪靜時,巨輪安穩前行;一旦遭遇海底暗礁、碰撞等嚴重災害是,船艙之間的隔離與堅固程度就是巨輪穩定前行的生命保證。

高可用 - 隔離原則



具體來說,隔離原則在系統設計中采取一系列方法,将系統元件、服務、資源和資料等隔離,盡可能減少互相影響,進而使得系統在對抗各種不确定性時,可以更好的将系統風險分散,提高系統整體可用性。

2.2、實作

雖然隔離原則十分易懂和重要,但它隻是一種抽象的原則或設計方式,并不是一種嚴格的理論架構,實踐過程中,我們很難通過量化的方式說系統已經完全做到了充分隔離。

作為系統設計的一部分,在微服務架構(Microservices Architecture)、資料庫系統(Database Systems)、網絡安全與隔離(Network Security and Isolation)、服務網格(Service Mesh)、應用程式隔離(Application Isolation)、環境隔離(Environment Isolation)、虛拟化技術(Virtualization Technology)等領域都可以稱為隔離原則的具體實作。

上述描述有些過于抽象,以日常開發所能接觸到的實際應用為例,如服務拆分、color網關、jsf對應着微服務架構領域;事務隔離、資料庫分區是資料庫系統的具體展現;jdos、編排部署則是容器技術實作;租戶隔離、垂直機房是環境隔離方向應用。

仔細分析下來,隔離原則指導下的技術産物在日常開發中無處不在,甚至于讓我們有了一種技術本身就該如此的錯覺,使用了最新的技術似乎就能保證系統的高可用。但現實經驗告訴我們,維持系統的高可用沒有這麼簡單。

事實上,我們可以帶着隔離原則重新審視一下日常的開發過程,重新感受隔離原則在現有技術架構下有哪些展現。

2.3 經驗與原則

對于一個抽象的原則而言,在工程實踐中往往會被總結為一系列的規則建議。隔離原則在實際的開發設計中,隔離原則通常存在以下的實作方式和建議,我們可以從簡單的并發程式設計開始,感受隔離原則的具象化展現。

•線程隔離

日常開發中,我們總會遇到機器數量受限場景,通常的做法就是并發程式設計,簡單的通過幾個線程互動完成對某項工作的處理。但當工作比較複雜時,我們一般會選擇自定義線程池,或者自己造輪子、引入外部開源元件等。

之是以我們使用線程池,實際上就是想實作多個線程的獨立運作,以一當百。這種也稱為線程隔離指的是線程池隔離,核心業務線程與非核心業務線程隔離,一個請求出現問題不會影響到其他線程池。如Netty的主從多線程,Dubbo的Connection Ordered Dispatcher的線程模型(圖檔來源于網絡)

高可用 - 隔離原則
高可用 - 隔離原則



但當我們的工作或需求複雜時,增加線程或線程池往往不是最明智的選擇,畢竟線程之間的通信過程以來的共享變量與環境耦合過于嚴重。此時我們通常會考慮将多個線程封裝到某個程序中,利用多個線程來時間複雜操作。

•程序隔離

比如把項目拆分成一個一個的子項目,互相實體隔離,或使用命名空間、資源控制以及其他程序隔離技術進行隔離。如前後端分離項目、容器隔離。(圖檔來源于網絡)

高可用 - 隔離原則



但無論我們的程式設計的如何優雅,總有一個繞不開的緻命問題,機器才是程式的實體,嚴重依賴硬體資源就是緻命的問題。是以大家往往會選擇更新軟體架構,比如采用微服務架構,将程式與硬體資源進一步結構

•叢集隔離

叢集部署與更新時我們目前日常開發中必不可少的流程之一,将應用部署到多個容器,使用叢集隔離開不同服務,使互相不影響,可以看作是程序隔離的進一步更新。(圖檔來源于網絡)

高可用 - 隔離原則



叢集隔離示例圖

但這種方式受限于機器的部署環境,畢竟在地球上,一隻海鷗扇動翅膀就可能能夠永遠改變天氣變化。

•機房隔離

更進一步,我們通常會把機器分不同的機房進行部署,如我們常用的廊坊與彙天機房。

從程式到機器,從機器到空間,雖然技術日新月異,我們仍然需要依賴這種樸素的方式抵禦風險。如果較真會發現,我們仍然可以繼續增大隔離性,但我們先到此為止,我們可以再簡單的将視角從實體層面轉換到資料流量次元。

•讀寫隔離

網際網路項目中大多是讀多寫少,我們正常的處理方式就是讀寫分離,一方面避免讀取邏輯對寫入邏輯的幹擾,同時擴充讀的能力,提高性能,提高可用性。在這種架構下,核心的出發點就是資料與操作之間隔離,隻是已認證不同技術手段完成。實際上,分庫分表、冷熱隔離等,都是具體的實作方式。(圖檔來源于網絡)

高可用 - 隔離原則



•熱點隔離

當我們用同樣的方式審視業務或流量入口時,仍然可以總結出一些規律,如将熱點業務獨立成系統或服務進行隔離,如秒殺,搶購。

3.3、業務實踐

上述讨論的都是圍繞現有開發技術與經驗的探究,可以發現隔離原則确實無處不在,但無處不在并不等于一定存在,比如我們持續疊代更新的業務系統。

1、垂直機房改造

對于系統的可用性風險事故,給我印象最深的就是在22年剛入職時,就經曆過一次嚴重的線上事故,總的來說就是某個應用的機房挂了,且是機房硬體問題,導緻研發人員束手無策,整個交易服務鍊路完全熔斷。事實上,在後續的斷網演練與混沌工程中,偶爾也會發現類似的問題。這類“黑天鵝事件”對系統的影響是緻命的,是以曆經長時間的治理,我想jd的研發同學所負責的系統都應該已經完成垂直機房改造了。

時至今日,再也沒有發生過類似的問題了,這應該就是隔離原則最簡單最直接的展現了。

背景

跨機房容災即某機房完全斷網後業務不受影響,降低機房故障影響,提升跨機房容災能力。

技術方案

1)JSF垂直調用改造:服務端提供不同機房不同别名,調用方配置同機房别名調用;

2)NP挂載跨機房多VIP:跨機房多VIP 且 與負載均衡/服務容器IP所在同機房;

3)JIMDB讀垂直調用改造:廊坊應用容器讀廊坊jimdb節點;彙天應用容器讀彙天jimdb節點;不能采用讀随機方式。

4)ES雙機房主備叢集;

5)應用跨多機房對等部署;

6)直接對接color上注冊的JSF服務修改成注冊HTTP服務。如果JSF直接對接合轍,按機房垂直調用原則在合轍配置不同服務别名即可。

2、es雙叢集改造

當我們用同樣的方式來審視我們的應用系統,我們同樣會發現一些風險。比如積理訂單的es雙叢集,對于積理訂單es而言,存儲着交易鍊路的訂單資訊,提供外部系統訂單清單資訊查詢的基礎服務,一向是重中之重,以至于我們在es之上的建立了一個專門提供es查詢和寫入應用服務。

訂單es在之前就是雙叢集,每個叢集都是一主兩從, 日常也有着均分流量配置,完備的降級切流預案。但緻命的問題就在于,雙叢集都在某個機房之中。是的,類似于垂直機房改造前的風險,雖然從來沒有發生過,但這種風險存在是不可接受的。

是以在去年雙十一,我們啟動了es雙叢集改造工作,目前已經是兩套獨立機房的穩定叢集提供資料服務。

背景

積理訂單系統作為黃金鍊路中的重要0級系統,其核心流程強依賴的ES為單機房單叢集,容災能力弱,恢複能力差;是以對積理訂單ES系統做雙叢集改造及多種容災恢複政策,以提升系統可用性。

技術方案

上半部分是我們為了相容老資料所做的一些切流邏輯,下半部分則是垂直機房改造之後的效果。

在之前,積理訂單es應用會接受來自積理訂單中間件異步事件消息,通過不同消息軌迹分别寫入到不同叢集之中,使用消息體中的版本号作為資料最終一緻性的保障。

我們仍然沿用這種寫邏輯,重新在廊坊和彙天獨立申請了兩套es叢集服務。

而針對讀邏輯,我們進行了垂直機房與叢集調用的改造,保留了之前的百分比流量配置,同時增加了垂直互備調用,防止某一機房網絡抖動或事故導緻垂直鍊路的可用性降低,增加了垂直互備調用邏輯。

如果有同學感興趣詳細的設計思路和實作細節,可以檢視我們組童鞋編寫的這篇治理文章:ES高可用-雙叢集改造

高可用 - 隔離原則



容災讀政策使用
政策選擇 場景 備注
百分比模式 單邊機房性能受限 調低受限機房百分比
百分比模式 單邊機房掉線 全量切到正常機房
垂直調用互備模式 日常場景 減少毛刺抖動帶來的逾時影響
垂直調用 高性能場景 就近調用、快速響應

3、流量隔離 - 分組

上面聊到的兩個案例實際上都是空間層面的隔離,可以發現我們的系統在嚴格的審視下,總能發現一些問題,同樣的,我們也可以切換視角到應用流量上。

積理訂單作為全管道黃金鍊路中的重要0級系統,即支援了線上業态,同僚也承接着大量的線下業務流量,

但都是使用相同的代碼部署。一方面,日常需求的疊代更新中,很難保證代碼持續的可靠,這一點,前文已經有所描述。一旦某次線上或者線下業務需求的改造發生問題,也會導緻整體鍊路不可用。更重要的是,線上與線下業态在流量峰值、及時性和業務模式上都存在很大差別,

是以這種場景下,針對流量的隔離就顯得十分重要。

背景

線下POS場景的訂單交易流程要求極高的可用性與及時性,為了防止線上流量影響線下門店的即時消費,需要将流量進行區分,針對線下場景提供專用容器服務。除了積理訂單以外,快退、交易結算等都存線上上與線下分組隔離。

技術方案

高可用 - 隔離原則



4、資料隔離 - 冷熱資料歸檔

最後,我想以一個房間裡的大象作為結尾。當我們在機房、應用、流量角度考慮系統的高可用時,通常會想,系統為什麼之前不這麼做。事實上,我們的技術總是在進步的,而研發系統的架構也是在不斷實際的,有些問題可能也隻有随着業務的不斷豐富才會暴露出來的,軟體系統如同随着業務更新不斷生長的。

這個資料隔離的應用是訂單ums,這個應用實際上提供的功能十分簡單,甚至于寫入方隻有訂單系統内部幾個系統寫入,儲存着訂單全生命周期中的跟蹤資訊,全稱是訂單全流程跟蹤資訊。對外提供者簡單的查詢服務。甚至于很久都沒有需求改造,持續穩定的提供的服務,從沒有發生過線上問題和告警。

但去年的雙十一我們終于發現了這頭房間裡的大象,之是以發現,是因為他已經擁有了1億條訂單跟蹤資料,讓我們不得不心驚膽戰的完成歸檔改造。

背景

1、 1000000000+條資料,資料量大

2、 日常調用頻繁,QPS-50/ms

是以設計做歸檔的處理,做冷熱隔離、熱庫表隻保留90天内的訂單資訊。

技術方案

高可用 - 隔離原則



三、結語

通過以上對日常開發與業務實踐的讨論,我們會發現,隔離原則雖然無處不在,但并不是一定存在的;系統能穩定運作,但不會一直穩定運作。我想這也是研發同學的價值所在:持續的關注系統,持續的審視系統,持續的優化系統。

繼續閱讀