ZStack是下一代開源的雲計算IaaS(基礎架構即服務)軟件。它主要面向將來的智能數據中心,經過提供靈活完善的APIs來管理包括計算、存儲和網絡在內的數據中心資源。用戶能夠利用ZStack快速構建本身的智能雲數據中心,也能夠在穩定的ZStack之上搭建靈活的雲應用場景,例如VDI(虛擬桌面基礎架構)、PaaS(平臺即服務)、SaaS(軟件即服務)等。html
上期5分鐘和你們分享了ZStack的核心架構設計特色,本期重點介紹:ZStack 核心架構設計特色之可拓展性祕密武器2—無狀態的服務。算法
前言數據庫
每個ZStack服務都是無狀態的,簡單的開啓一個富餘的服務實例而後使之負載均衡,就能實現服務的高可用和可橫向拓展;此外,ZStack把全部服務封裝進一個稱爲管理節點的進程中,使得部署和管理服務變得尤爲簡單。api
動機網絡
在「ZStack的可拓展性祕密武器1:全異步架構」中,咱們論述了異步的架構使得單一的ZStack管理節點足以承擔大多數雲的負載量;然而當用戶想要去建立一個高可用的生產環境或處理很是大的併發工做負載,一個管理節點是不夠的。解決方案是創建一個負載均衡的分佈式系統,這種經過添加新節點來拓展整個系統的能力的方法被稱爲橫向拓展。架構
問題併發
設計一個分佈式系統不是一件簡單的事情。一個分佈式系統,特別是一個有狀態的系統,必須處理一致性(consistency)、可用性(availability)和分區容忍性(partition tolerance)(CAP理論)的問題,每個問題都是很是複雜的。與之相反,一個無狀態的分佈式系統必定程度上下降了複雜度。第一,由於節點不用分享狀態,整個系統的一致性是能夠保證的。第二,由於節點都是類似的,對於分區問題系統一般是能夠容忍的。所以,一般把一個分佈式系統設計爲無狀態的而不是有狀態的。可是設計一個無狀態的分佈式系統一般比設計一個有狀態的分佈式系統可貴多。利用消息代理和數據庫的優勢,ZStack創建了一個包含各類無狀態服務的無狀態分佈式系統。負載均衡
使整個系統無狀態的基礎是無狀態的服務,在討論什麼是無狀態的服務以前,咱們首先理解什麼是「狀態」。在ZStack中,主機、虛擬機、鏡像和用戶等資源是被一個個服務管理的。當整個系統的服務實例不止一個的時候,資源會被分發到不一樣的服務實例中。假設有10000臺虛擬機和兩個虛擬機服務實例,理想狀態下每一個實例會管理5000臺虛擬機。less
由於有兩個服務實例,在向一個虛擬機發出請求前,請求者必須知道哪一個實例管理哪一個虛擬機,不然,他將不知道向哪一個實例發出請求。相似「哪一個服務實例管理哪一個資源」的信息就是咱們所說的狀態。若是一個服務是有狀態的,每一個服務維護本身的狀態。請求者必須能夠獲取到當前的狀態信息。當服務實例的數量改變的時候,服務須要去改變狀態。異步
狀態的改變是危險且易錯的,這一般限制了整個系統的可拓展性。爲了使整個系統的可靠性和橫向拓展性加強,把狀態和服務分離開,使得服務無狀態是比較理想的解決辦法(參考Service Statelessness Principle)。無狀態的服務使請求者不須要詢問向哪裏發送請求,當新添一個新的服務實例或者刪除一箇舊的服務實例的時候,服務之間也不用交換狀態。
備註:在如下文檔中,爲了簡便,「服務」和「服務實例」是能夠互換的。
服務和管理節點
經過中心消息代理-- RabbitMQ彼此通訊的服務,在ZStack中是一等公民。
與典型的microservice架構不一樣,典型的microservice架構中每一個服務一般運行在不一樣的進程或者不一樣的機器上,ZStack則把全部服務封裝在一個被稱爲管理節點的進程中。文章「進程內的microservice架構」解釋了咱們這麼作的緣由。
每一個管理節點都是一個功能齊全的ZStack軟件。由於包含的服務是無狀態的,管理節點不共享任何狀態,但仍然須要維護和其餘節點的心跳記錄,和一個一致性哈希環,咱們接下來將詳細介紹哈希環。心跳用來監視管理節點是否正常運行,一旦一個管理節點中止更新本身的心跳一段時間後,其餘的管理節點將會驅逐它而後接管他所管理的資源。
無狀態的服務
針對ZStack的業務邏輯,實現無狀態服務的核心技術,是一致性哈希算法。當系統啓動的時候,每個管理節點將被分配一個version 4 UUID(管理節點UUID),這個UUID將和服務名稱拼在一塊兒在消息代理上註冊一個服務隊列。(舉例代碼詳見閱讀原文)
備註:你應該已經注意到全部的隊列都是以一個相同的管理節點的UUID結尾的。
主機,磁盤,虛擬機等資源也有特定的UUID。和資源相關的消息一般在服務之間傳遞,在發送一個消息以前,發送者必須基於資源的UUID選擇一個接收服務,一致性哈希算法這時候就發揮做用了。
一致性哈希是一種較特別的哈希,當一個哈希表的大小發生變化時,只有一部分鍵須要被從新映射。深刻了解一致性哈希,請閱讀http://www.tom-e-white.com/2007/11/consistent-hashing.html,在ZStack中,管理節點組成了一個一致性哈希以下:
每個管理節點維護了一份包含系統中全部管理節點的UUID的環拷貝,當一個管理節點添加或刪除的時候,一個生命週期事件將經過消息代理廣播到其餘的管理節點,這將致使這些節點拓展或者收縮環去描述當前系統的狀態。當發送一條消息時,發送者將使用資源的UUID哈希得出目標管理節點的UUID。例如,當VM的UUID是932763162d054c04adaab6ab498c9139時發送一個StartVmInstanceMsg,(僞代碼詳見閱讀原文)
有了哈希環,資源UUID相同的消息將被映射到特定管理節點的相同服務中,這點是ZStack的無鎖架構的基礎(詳見下期5分鐘:ZStack的可拓展性祕密武器3:無鎖架構)。
當環收縮或者拓展的時候,由於哈希環的固有特性,僅有小部分節點將被影響。
由於使用一致性哈希環,發送者不須要知道哪一個服務實例將處理這條消息,由於服務實例將被哈希計算出來。服務也不用維護、交換他們管理的資源信息,而且由於選擇正確的服務實例能夠由哈希環完成,服務只須要單純的處理消息。所以,服務變得極其簡單且無狀態。
除了包含資源UUID的消息(例如StartVmInstanceMsg, DownloadImageMsg)之外,有一種不包含資源UUID的消息,這種消息一般是創造性的消息(例如CreateVolumeMsg)和不進行資源操做的消息(例如AllocateHostMsg),由於這些消息能夠被髮送到任意管理節點的服務中,他們就被髮送到本地的管理節點,由於發送者和接收者在同一個節點上,接收者在發送者發送消息時必定是可用的。
對於API消息(如APIStartVmInstanceMsg),有一個特別的處理方法是他們常常和一個重要的服務ID api.portal綁在一塊兒發送。在消息代理中,一個稱爲zstack.message.api.portal的全局的隊列被全部管理節點的API服務共享,帶有api.portal的消息將經過一致性哈希環把消息映射到正確的服務中,從而實現負載均衡。經過上面這種方式,ZStack隱藏了API客戶端消息選路的實現,減小了ZStack API客戶端代碼。(代碼詳見閱讀原文)
總結
本文演示了ZStack是如何經過構建一個無狀態的分佈式系統來進行橫向拓展的。由於管理節點共享的信息很是少,創建一個龐大的擁有幾十或上百個管理節點的集羣是很是容易的。然而,在現實中,對於私有云,兩個管理節點足夠知足高可用性和可拓展性的需求。對於公有云,管理者能夠依據負載量大量建立管理節點。由於異步架構和無狀態架構,ZStack可以處理現有的IaaS軟件處理不了的很是大的併發任務。
以上,就是本期的架構篇補習啦,對架構感興趣的小夥伴歡迎參考如下步驟自行到官網探索更多ZStack架構相關噢~
產品下載請戳:
https://www.zstack.io/help/product_manuals/maintenance_manual/2.html#c2_1
產品手冊:
https://www.zstack.io/help/product_manuals/
Question Time
問題答案都在今日的小課堂中,補習完成記得帶着答案到官微(ZStack雲計算)後臺回覆,咱們會隨機抽取5位愛學習的小夥伴送上一點當心意~
閱讀原文包含文中代碼噢,須要的小夥伴點擊進入官網‘知識庫-技術匯-可拓展性祕密武器2:無狀態的服務’自取便可!