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