摘要:本文將對核心引擎的源碼進行剖析。在筆者看來,能夠快速迭代的原因首先是來自于每位工程師的辛勤付出。在中,還有一類很有意思的代碼,一般稱之為。筆者有機會將會在之后的系列文章分析其中的典型案例以及在代碼中使用極其頻繁的核心工具。
本文首發于泊浮目的專欄:https://segmentfault.com/blog...前言
ZStack是下一代開源的云計算IaaS(基礎架構即服務)軟件。它主要面向的是未來的智能數據中心,通過提供的API來管理包括計算、存儲和網絡在內的數據中心的各種資源。跟OpenStack相比,ZStack具有易用、穩定、靈活、超高性能等特點。其單管理節點可以管理1萬臺物理機規模集群,多個管理節點構建的集群可以做到使用一個數據庫、一套消息總線管理10萬臺物理機、數百萬個虛擬機節點、并發處理數萬個API。
以下是ZStackV2.2的服務架構圖
官網地址:http://www.zstack.io/核心開源引擎ZStack GitHub:https://github.com/zstackio/z...
ZStack-Utility GitHub:https://github.com/zstackio/z...
閱讀源碼如果不想使用IDE,建議配合https://github.com/buunguyen/...。
本文將對核心引擎-ZStack的源碼進行剖析。在ZStack官網上我們可以看到其每個版本的發布都是攜帶了許多的新特性。在筆者看來,能夠快速迭代的原因首先是來自于每位工程師的辛勤付出。除此之外,因其還有些軟件工程領域中沉淀下來的最佳實踐:
良好的架構設計
覆蓋較為全面的測試
恰當好處的使用設計模式
良好的架構設計 異步架構Iaas的核心應該做的是管控層,而不是數據層。故ZStack僅僅也是做出一些“決策”而已——在設計系統的時候,應不考慮在這些決策的執行上消耗大量的資源。在面對大量請求或者“決策”的時候,如果使用多線程來處理阻塞式IO模型時會遇到一些問題:
阻塞模型的吞吐量受到線程池大小的限制;
創建并使用許多線程會耗費額外的時間用于上下文切換,影響系統性能。
而非阻塞、異步的消息驅動系統可以只運行少量的線程,并且不阻塞這些線程,只在需要計算資源時才使用它們。這大大提高了系統的響應速度,并且能夠更高效地利用系統資源。
故,ZStack采用了異步架構,分別由三個部分組成:
異步消息
異步方法
異步HTTP 請求
如果在系統中的一部分采用異步設計,是不行的。這樣還是會因為同步而沒法享受異步帶來的“福利”。故此整個系統都得采用異步架構。
相對的,開發者們在編寫異步代碼的時候得格外小心。
在系統設計中,異步調用可以減少系統在IO上出現瓶頸的可能性。
擴展鏈接 : ZStack--可拓展性的秘密武器1:異步架構無狀態服務
在ZStack中,每一個服務都是獨立存在的。為了方便的管理更多的物理機,ZStack推薦采用集群部署MN。但這樣就會遇到一個問題,不同MN下面有著不同的幾個服務存在,在這里我們設其為X個服務。在10個MN部署的情況下,可能就是10X個服務。那么在一個資源需要操作時,我需要發送向對應的MN。那么如何找到那個MN呢?最直觀的想法就是在各個MN中保存相應的“服務表”,這即是一種狀態。那么在分布式系統中,采用有狀態的服務絕對不是一個好的選擇,它會嚴重影響系統的擴展性。ZStack巧妙的采用了一致性哈希算法+MQ解決了這個問題。
這在系統設計中實為是一種使用一致性hash技術的負載均衡
擴展鏈接:ZStack—可拓展性秘密武器2:無狀態的服務無鎖架構
解決并發的問題不一定要用顯式的鎖,也可以對同一資源做操作的任務做成隊列使其串行執行。
注意:并發 != 并行松耦合架構 項目模塊化
擴展鏈接:ZStack--可拓展性秘密武器3:無鎖架構
在Intellij中打開ZStack的代碼,會發現大多數目錄底下都會有一個pom.xml文件,ZStack采用了模塊化項目。模塊化的好處在工程實踐中不言而喻的,比如:
可以在不影響整個系統的情況下替換某個模塊
開發者只要專心的在自己的模塊中工作即可
減少系統耦合度,提高內聚,減少資源循環依賴,增強系統框架設計
...
下面來看一下ZStack中代碼的結構:
代碼結構截圖于2017.9.22
名稱 | 簡介 |
---|---|
build | 用于Java部分的編譯、打包、部署等 |
conf | 配置文件及SQL文件的放置;Spring Service配置存放;持久化文件配置 |
core | 核心模塊。實現系統的核心功能——包括數據庫、消息總線、工作流實現等等 |
coregroovy | ZStack的最新測試采用了Groovy,這里是對測試庫做的支持 |
header | 消息以及Entity的定義 |
plugin | 顧名思義。其中不少組件都以插件化開發,提供較高的靈活性 |
sdk | 測試庫使用的SDK |
simulator | 對于測試庫支持的又一模塊,主要用戶simulator agent的行為 |
testlib | 測試庫 |
test | 測試模塊 |
工具類 | 工具包。目前僅僅支持了doc生成 |
utils | 代碼中使用的工具類 |
其他 | 功能實現模塊 |
在ZStack中,每個功能實現模塊都會被稱為服務——一個獨立的服務。各個服務之間的通信由MQ來承擔。這就像是傳統的CSE,C和E是不耦合的,通過S來交互。同樣的,一個服務需要向另一個服務發起調用,只需往消息總線發送消息,并指定這個服務ID(Service ID)即可。如果某個服務的代碼需要大量重構或者做成微服務,只要提供相同的服務并注冊到MQ上就可以了。這就是事件驅動架構(Event Driven Architecture)的一種典型實現。
CSE:Controller、Service、Entity。注:稱作Domain或者Model都是不專業的。Domain是一個領域對象,往往我們再做傳統Java軟件web開發中,這些Domain都是貧血模型,是沒有行為的,或是沒有足夠的領域模型的行為的,所以,以這個理論來講,這些Domain都應該是一個普通的entity對象,并非領域對象,所以請把包名改為:com.xxx.entity。
舉個簡單明了的例子。如果每個對象的行為都是通過消息來決定的(比如一個方法需要message得到回復后才能do something...),那么這個對象僅僅對消息總線產生了依賴。在測試中,將會發揮巨大的威力——我們只需要改變handle message處的行為,就可以使一個對象行為做出相應的變化。這樣可以使mock的單位變得更小,同時也可以變得更加靈活。
試想如果通過函數調用:
//方法a中的代碼 xxService.method1(); xx2Service.method2();
在測試中該如何解耦?但如果通過MQ——即一個消息來調用xxService.method1(),那么方法a對xxService就沒有了直接的依賴。
使用Spring不了解Spring的人可以看:看起來很長但還是有用的Spring學習筆記
在代碼中,每當我們New出一個對象時,這個模塊便對這個對象產生了依賴。當我們需要測試的時候就不得不去Mock它。當依賴的對象or Field 有成千上萬個的時候,這就是一場災難了。代碼變得愈發不可測,坑就越多,開發者在擴展or維護項目的時候就會愈發的乏力。這就像是我們之前提到的MQ,服務1->MQ->服務2,由于中間隔了一個MQ,于是服務1和服務2沒有必然的關系。同樣的,從對象1->調用->對象2到對象1->調用->Spring提供的IOC容器->對象2,這樣使對象與對象之間也沒有了直接調用關系,對象1只要知道它要調用的對象實現了其需要的Interface就是可以調用的。
除了Autowired的正確使用姿勢。在ZStack中,還有一類很有意思的代碼,一般稱之為xxxExtensionPoint。其本質就是定義一個接口,然后其實現類作為Bean通過XML注冊到IOC中。在需要使用的時候,通過Spring獲取到所有實現該接口的對象,調用其函數。這樣就會使代碼變得非常的靈活。
例如,ZStack分為多個版本——開源版、企業版、混合云版等。如果一個服務在不同版本中的處理邏輯需要稍許不同,那么就可以在開源版的代碼中注冊一個接口,在另一個版本的服務中實現該接口。這樣也不會影響到開源版的原有邏輯。從模塊上看我們代碼的是松耦合并且無法直接調用的,但是在內存中,卻是可以調用得到的。
覆蓋較為全面的測試在ZStack中
開發者Fix每一個Bug都是需要補充相應的Case;
每一個Feature在進去之前更會由開發工程師與QA工程師同時制定測試場景并Cover;
每一個PR(pull request)進去之前都會通過PR系統跑過所有的Case,以防止Bug的Regression;
由于ZStack源碼做到了一定的解耦合(上述提到)與無狀態,使得集成測試得以進行。
其首席架構師Frank.Zhang曾說過:我們開發者在寫代碼的時候往往就應該考慮該怎么寫測試了。恰當好處的使用設計模式想了解ZStack的測試框架,可以看: ZStack WiKi :管理節點基于模擬器的Integration Test框架
在ZStack中,設計模式有較為良好的實踐。筆者有機會將會在之后的系列文章分析其中的典型案例以及在代碼中使用極其頻繁的核心工具。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/40868.html
摘要:本文將對核心引擎的源碼進行剖析。在筆者看來,能夠快速迭代的原因首先是來自于每位工程師的辛勤付出。在中,還有一類很有意思的代碼,一般稱之為。筆者有機會將會在之后的系列文章分析其中的典型案例以及在代碼中使用極其頻繁的核心工具。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 ZStack是下一代開源的云計算IaaS(基礎架構即服務)軟件。它...
摘要:本文將對核心引擎的源碼進行剖析。在筆者看來,能夠快速迭代的原因首先是來自于每位工程師的辛勤付出。在中,還有一類很有意思的代碼,一般稱之為。筆者有機會將會在之后的系列文章分析其中的典型案例以及在代碼中使用極其頻繁的核心工具。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 ZStack是下一代開源的云計算IaaS(基礎架構即服務)軟件。它...
摘要:下面將開始分析它的源碼。僅僅定義了一個最小應有的行為。更好的選擇由于該庫是為定制而生,故此有一些防御性判斷,源碼顯得略為。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 在ZStack(或者說產品化的IaaS軟件)中的任務通常有很長的執行路徑,錯誤可能發生在路徑的任意一處。為了保證系統的正確性,需提供一種較為完善的回滾機制——在ZSt...
摘要:但新增模塊的結構卻還是大致相同,此即是的經典設計模式這套模式也被開發者稱為三駕馬車。領域層定義負責表達業務概念,業務狀態信息以及業務規則。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 隨著ZStack的版本迭代,其可以掌管的資源也越來越多。但新增模塊的結構卻還是大致相同,此即是ZStack的經典設計模式——這套模式也被開發者稱為ZS...
摘要:但在實際的二次開發中,這些做法未必能夠完全滿足需求。在源碼剖析之核心庫鑒賞一文中,我們了解到是的基礎設施之一,同時也允許通過顯示聲明的方式來聲明。同理,一些也可以使用繼承進行擴展。 本文首發于泊浮目的專欄:https://segmentfault.com/blog... 前言 在ZStack博文-5.通用插件系統中,官方提出了幾個較為經典的擴展方式。但在實際的二次開發中,這些做法未必...
閱讀 844·2021-11-24 10:44
閱讀 2778·2021-11-11 16:54
閱讀 3160·2021-10-08 10:21
閱讀 2067·2021-08-25 09:39
閱讀 2899·2019-08-30 15:56
閱讀 3459·2019-08-30 13:46
閱讀 3493·2019-08-23 18:09
閱讀 2066·2019-08-23 17:05