- 微服務(wù)設(shè)計(jì)原理與架構(gòu)
- 鄭天民
- 4228字
- 2019-09-10 13:22:33
1.1 分布式系統(tǒng)
微服務(wù)架構(gòu)首先表現(xiàn)為一種分布式系統(tǒng)(Distributed System),而分布式系統(tǒng)是對傳統(tǒng)單塊系統(tǒng)(Monolith System)的一種演進(jìn)。為了更好地理解和掌握微服務(wù)架構(gòu)的特點(diǎn),本節(jié)對單塊系統(tǒng)和分布式系統(tǒng)做簡要介紹。
1.1.1 單塊系統(tǒng)的問題
在軟件技術(shù)發(fā)展過程的很長一段時間內(nèi),軟件系統(tǒng)都表現(xiàn)為一種單塊系統(tǒng)。時至今日,很多單塊系統(tǒng)仍然在一些行業(yè)和組織中得到開發(fā)和維護(hù)。所謂單塊系統(tǒng),簡單講就是把一個系統(tǒng)所涉及的各個組件都打包成一個一體化結(jié)構(gòu)并進(jìn)行部署和運(yùn)行。在Java EE領(lǐng)域,這種一體化結(jié)構(gòu)很多時候就體現(xiàn)為一個WAR包,而部署和運(yùn)行的環(huán)境就是以Tomcat為代表的各種應(yīng)用服務(wù)器。圖1-1所示的就是一個典型的單塊系統(tǒng)。我們可以看到在應(yīng)用服務(wù)器上同時運(yùn)行著面向用戶的Web組件、封裝業(yè)務(wù)邏輯的Service組件和完成數(shù)據(jù)訪問的DAO(Data Access Object,數(shù)據(jù)訪問對象)組件。這些組件都作為一個整體進(jìn)行統(tǒng)一的開發(fā)、部署和維護(hù)。

圖1-1 單塊系統(tǒng)示意圖
顯然,圖1-1所示的單塊系統(tǒng)有其存在和發(fā)展的固有優(yōu)勢。當(dāng)團(tuán)隊(duì)規(guī)模并不是太大的時候,一個單塊應(yīng)用可以由一個開發(fā)者團(tuán)隊(duì)進(jìn)行獨(dú)立維護(hù)。該團(tuán)隊(duì)的成員能夠?qū)螇K應(yīng)用快速學(xué)習(xí)、理解和修改,因?yàn)槠浣Y(jié)構(gòu)非常簡單。同時,因?yàn)閱螇K系統(tǒng)的表現(xiàn)形式就是一個獨(dú)立的WAR包,想要對它進(jìn)行集成、部署以及實(shí)現(xiàn)無狀態(tài)集群相對也比較簡單,通常只要采用負(fù)載均衡機(jī)制并運(yùn)行該單塊系統(tǒng)的多個實(shí)例就能達(dá)到系統(tǒng)伸縮性要求。
但在另一方面,隨著公司或者組織業(yè)務(wù)的不斷擴(kuò)張、業(yè)務(wù)結(jié)構(gòu)的不斷變化以及用戶量的不斷增加,單塊架構(gòu)的優(yōu)勢已逐漸無法適應(yīng)互聯(lián)網(wǎng)時代的快速發(fā)展,面臨著越來越多的挑戰(zhàn)。在使用單塊系統(tǒng)時,我們不得不面對以下問題。
1.業(yè)務(wù)復(fù)雜度
對于大多數(shù)系統(tǒng)而言,架構(gòu)設(shè)計(jì)是為了滿足業(yè)務(wù)需求的。衡量架構(gòu)好壞與否的一個重要方面是看其面對復(fù)雜業(yè)務(wù)變更時所應(yīng)該具有的靈活性,也就是我們通常所說的可擴(kuò)展性(Extensibility)??蓴U(kuò)展性是指系統(tǒng)在經(jīng)歷不可避免的變更時所具有的靈活性,與針對提供這樣的靈活性所要付出的成本進(jìn)行平衡的能力。所謂可擴(kuò)展,可擴(kuò)展的是業(yè)務(wù)。即當(dāng)往SystemA中添加新業(yè)務(wù)NewSubSystem時,如果不需要改變原有的各個子系統(tǒng)而只需把新業(yè)務(wù)封閉在一個新的子系統(tǒng)中就能完成整體業(yè)務(wù)的升級,我們就可以認(rèn)為系統(tǒng)具有較好的可擴(kuò)展性,可擴(kuò)展性示意圖如圖1-2 所示。顯然,單塊系統(tǒng)不具備良好的可擴(kuò)展性,因?yàn)閷ο到y(tǒng)業(yè)務(wù)的任何一處進(jìn)行修改,都需要重新構(gòu)建整個系統(tǒng)并進(jìn)行發(fā)布。單塊系統(tǒng)內(nèi)部沒有根據(jù)業(yè)務(wù)結(jié)構(gòu)進(jìn)行合理的業(yè)務(wù)拆分是導(dǎo)致其可擴(kuò)展性低下的主要原因。

圖1-2 可擴(kuò)展性示意圖
2.代碼腐化
在軟件開發(fā)過程中,代碼腐化在一定程度上是一種不可避免的現(xiàn)象,關(guān)鍵是腐化的時間和程度與整個產(chǎn)品生命周期之間的關(guān)聯(lián)關(guān)系。在產(chǎn)品的鼎盛時期,如果出現(xiàn)大量的代碼腐化會對產(chǎn)品的發(fā)展帶來巨大危害。在單塊系統(tǒng)中,由于缺乏合理的業(yè)務(wù)和技術(shù)實(shí)現(xiàn)邊界,隨著產(chǎn)品業(yè)務(wù)功能的增多,當(dāng)出現(xiàn)缺陷時,有可能引起缺陷的原因組合就會比較多,這會導(dǎo)致分析、定位和修復(fù)缺陷的成本相應(yīng)增高,也就意味著缺陷的平均修復(fù)周期可能會花費(fèi)更長時間,從而影響到產(chǎn)品的正常迭代和演進(jìn)。同時,隨著功能不斷疊加,單塊系統(tǒng)的代碼結(jié)構(gòu)也日益復(fù)雜,在開發(fā)人員對全局功能缺乏深度理解的情況下,修復(fù)一個缺陷的同時還有可能引入其他的缺陷,在很多技術(shù)團(tuán)隊(duì)并不具備完善的自動化測試機(jī)制的客觀條件下,很可能導(dǎo)致問題越修越多的不良循環(huán)。
3.團(tuán)隊(duì)問題
互聯(lián)網(wǎng)行業(yè)由于產(chǎn)品價值與市場時機(jī)密切相關(guān),普遍崇尚快速試錯和迭代發(fā)布,很多公司或組織會在比較短的時間內(nèi)擴(kuò)充產(chǎn)品功能和開發(fā)團(tuán)隊(duì),也就意味著對于過程資產(chǎn)建設(shè)和人才培養(yǎng)等方面并不會投入太多的成本,這就要求新加入團(tuán)隊(duì)的成員能夠快速融入團(tuán)隊(duì)并進(jìn)行代碼開發(fā)和維護(hù)。然而,由于在單塊系統(tǒng)中所有的業(yè)務(wù)和代碼在很大程度上無序地混合在一起,存在大量錯綜復(fù)雜的業(yè)務(wù)和代碼結(jié)構(gòu)、由于歷史原因所造成的迥然不同的開發(fā)風(fēng)格以及看似復(fù)雜但已經(jīng)不被使用的遺留代碼,使得新員工了解行業(yè)背景、熟悉應(yīng)用程序業(yè)務(wù)、配置本地開發(fā)環(huán)境等看似簡單的任務(wù)都變得并不簡單。
另外,單塊系統(tǒng)的集中式管理方式,使得系統(tǒng)內(nèi)部的技術(shù)體系和開發(fā)方式很難得到擴(kuò)展。隨著應(yīng)用程序的復(fù)雜性逐漸增加以及功能越來越多,如果團(tuán)隊(duì)希望嘗試引入新的框架和技術(shù),或者對現(xiàn)有技術(shù)棧升級,通常都會面臨不小的風(fēng)險。也即意味著初始的技術(shù)選型嚴(yán)重限制了單塊系統(tǒng)將來采用不同開發(fā)語言或框架的能力。但互聯(lián)網(wǎng)行業(yè)中技術(shù)體系變化和業(yè)務(wù)體系變化一樣快速,技術(shù)體系的無法擴(kuò)展和升級也會導(dǎo)致現(xiàn)有團(tuán)隊(duì)中不同出身和開發(fā)背景的成員對系統(tǒng)代碼產(chǎn)生一種開發(fā)惰性,也無法吸引到優(yōu)秀的開發(fā)人員。
4.伸縮性問題
前面講到單塊系統(tǒng)的可擴(kuò)展性很差,實(shí)際上它的可伸縮性同樣很有問題。所謂可伸縮(Scalability),伸縮的是性能,即當(dāng)系統(tǒng)性能出現(xiàn)問題時,如果我們只需要簡單添加應(yīng)用服務(wù)器等硬件設(shè)備就能避免系統(tǒng)出現(xiàn)性能瓶頸,那么該系統(tǒng)無疑具備較高的可伸縮性。通常,我們會考慮采用水平伸縮的方法實(shí)現(xiàn)可伸縮性。當(dāng)考慮水平伸縮時,一般的做法是建立一個集群,通過在集群中不斷地添加新節(jié)點(diǎn),然后借助前端的負(fù)載均衡器,將用戶的請求按照某種算法分配到不同的節(jié)點(diǎn)上。但是,由于單塊系統(tǒng)的所有程序代碼都運(yùn)行在服務(wù)器上的同一個進(jìn)程中,內(nèi)存密集型和CPU密集型并存,也就要求所有應(yīng)用的服務(wù)器都必須有足夠的內(nèi)存和強(qiáng)勁的 CPU 來滿足需求。這種方法的成本會比較高,而且資源利用率通常都比較低下。
以圖1-3為例,單塊系統(tǒng)中的組件A的負(fù)載已經(jīng)達(dá)到了80%,也就是到了不得不對系統(tǒng)運(yùn)行能力進(jìn)行擴(kuò)容的時候。但同一系統(tǒng)的其他兩個組件B和C的負(fù)載還沒有達(dá)到其處理能力的20%。由于單塊系統(tǒng)中的各個組件是打包在同一個WAR包中的,因此通過添加一個額外的系統(tǒng)實(shí)例雖然可以將需要擴(kuò)容組件的負(fù)載降低一半,但是顯然其他組件的利用率變得更為低下,造成資源浪費(fèi)。另外,對于那些需要保持類似會話(Session)數(shù)據(jù)的需求而言,擴(kuò)容之后的運(yùn)行機(jī)制在如何保持各個服務(wù)器之間數(shù)據(jù)的一致性上,也存在較大的實(shí)現(xiàn)難度。

圖1-3 單塊系統(tǒng)的伸縮性問題
針對以上集中式單塊系統(tǒng)所普遍存在的問題,基本的解決方案就要依賴于分布式系統(tǒng)的合理構(gòu)建。
1.1.2 分布式系統(tǒng)的基本特征
分布式系統(tǒng),是指硬件或軟件組件分布在不同的網(wǎng)絡(luò)計(jì)算機(jī)上,彼此之間僅僅通過消息傳遞進(jìn)行通信和協(xié)調(diào)的系統(tǒng)。我們從這個定義中可以看出分布式系統(tǒng)包含兩個區(qū)別于單塊系統(tǒng)的本質(zhì)性特征:一個是網(wǎng)絡(luò),分布式系統(tǒng)的所有組件都位于網(wǎng)絡(luò)之中,對于互聯(lián)網(wǎng)應(yīng)用而言,則位于更為復(fù)雜的互聯(lián)網(wǎng)環(huán)境中;另一個是通信和協(xié)調(diào),與單塊系統(tǒng)不同,位于分布式系統(tǒng)中的各個組件只有通過約定、高效且可靠的通信機(jī)制進(jìn)行相關(guān)協(xié)作才能完成某一項(xiàng)業(yè)務(wù)功能。這是我們在設(shè)計(jì)和實(shí)現(xiàn)分布式系統(tǒng)時首先需要考慮的兩個方面。圖1-4所示的就是從軟件開發(fā)視圖出發(fā)得到的一個典型的分布式系統(tǒng),包含了分布式服務(wù)、消息中間件和分布式緩存等常見的用于構(gòu)建分布式系統(tǒng)的技術(shù)實(shí)現(xiàn)方式。顯然,這些工具位于一個封閉或開放的網(wǎng)絡(luò)環(huán)境中,相互之間通過服務(wù)的注冊和發(fā)現(xiàn)、消息傳遞、數(shù)據(jù)的緩存共享等機(jī)制完成協(xié)作。

圖1-4 分布式系統(tǒng)示意圖
在分布式系統(tǒng)中,為了打破單塊系統(tǒng)中集中式的系統(tǒng)架構(gòu),我們引入系統(tǒng)拆分的思想和實(shí)踐。拆分的需求來自組織結(jié)構(gòu)變化、交付速度、業(yè)務(wù)需求以及技術(shù)需求所引起的變化。一般認(rèn)為系統(tǒng)拆分的基本思路有兩種,即縱向(Vertical)拆分和橫向(Horizontal)拆分。
所謂縱向拆分,就是將一個大應(yīng)用拆分為多個小應(yīng)用,如果新業(yè)務(wù)較為獨(dú)立,那么就直接將其設(shè)計(jì)部署為一個獨(dú)立的應(yīng)用系統(tǒng)即可。如圖1-5所示,我們可以將移動醫(yī)療系統(tǒng)中的預(yù)約掛號業(yè)務(wù)拆分成訂單、醫(yī)院和用戶等獨(dú)立業(yè)務(wù)子系統(tǒng)??v向拆分關(guān)注于業(yè)務(wù),通過梳理產(chǎn)品線,將內(nèi)聚度較高的相關(guān)業(yè)務(wù)進(jìn)行剝離從而形成不同的子系統(tǒng)。

圖1-5 分布式縱向拆分示意圖
相對于縱向拆分的面向業(yè)務(wù)特性,橫向拆分更多地關(guān)注于技術(shù)。所謂橫向拆分,就是通過將可以復(fù)用的業(yè)務(wù)拆分出來,獨(dú)立部署為分布式服務(wù),調(diào)用這些分布式服務(wù),構(gòu)建復(fù)雜的新業(yè)務(wù)。所以,橫向拆分的關(guān)鍵在于識別可復(fù)用的業(yè)務(wù),設(shè)計(jì)服務(wù)接口并規(guī)范服務(wù)依賴關(guān)系。橫向拆分的基本實(shí)現(xiàn)方式是構(gòu)建分布式服務(wù)體系,圖1-6是對圖1-5所示的預(yù)約掛號業(yè)務(wù)進(jìn)行橫向拆分的結(jié)果??梢钥吹?,當(dāng)我們把訂單、醫(yī)生、號源和用戶等業(yè)務(wù)抽象成獨(dú)立的垂直化服務(wù),并在各個服務(wù)上層實(shí)現(xiàn)分布式環(huán)境下的調(diào)用和管理框架,系統(tǒng)的業(yè)務(wù)就可以轉(zhuǎn)變?yōu)橐环N排列組合的構(gòu)建方式。如基于訂單和支付服務(wù),我們可以構(gòu)建出業(yè)務(wù)1,而業(yè)務(wù)2可能只依賴于醫(yī)院和用戶管理服務(wù)。分布式服務(wù)框架提供了一種按需構(gòu)建的機(jī)制,在保證各個分布式服務(wù)的技術(shù)、團(tuán)隊(duì)、交付獨(dú)立發(fā)展的前提下,確保業(yè)務(wù)整合的靈活性和高效性。

圖1-6 分布式橫向拆分示意圖
然而,分布式系統(tǒng)相較于單塊系統(tǒng)而言具備優(yōu)勢的同時,也存在一些不得不考慮的特性,包括但不限于以下幾點(diǎn)。
網(wǎng)絡(luò)傳輸?shù)娜龖B(tài)性
構(gòu)建分布式系統(tǒng)依賴網(wǎng)絡(luò)通信,而網(wǎng)絡(luò)通信表現(xiàn)為一個復(fù)雜且不可控的過程。相比于單機(jī)系統(tǒng)中函數(shù)式調(diào)用的失敗或者成功,網(wǎng)絡(luò)通信會出現(xiàn)“三態(tài)”的概念,即成功、失敗與超時。由于網(wǎng)絡(luò)原因,消息沒有成功發(fā)送到接收方,而是在發(fā)送過程就發(fā)生了丟失現(xiàn)象;或者接收方處理后,響應(yīng)給發(fā)送方的過程中發(fā)生消息丟失現(xiàn)象。這些問題都會增加通信的代價。如何使通信的代價降到用戶可以忍耐的層次是分布式系統(tǒng)設(shè)計(jì)的重要目標(biāo)。
異構(gòu)性
相較單塊系統(tǒng),分布式系統(tǒng)由于基于不同的網(wǎng)絡(luò)、不同的操作系統(tǒng)、不同的軟件實(shí)現(xiàn)技術(shù)體系,必須要考慮一種通用的服務(wù)集成和交互方式來屏蔽異構(gòu)系統(tǒng)之間的差異。異構(gòu)系統(tǒng)之間的不同處理方式會對系統(tǒng)設(shè)計(jì)和開發(fā)帶來難度和挑戰(zhàn)。
負(fù)載均衡
在集中式系統(tǒng)中,各部件的任務(wù)明確。由于分布式系統(tǒng)是多機(jī)協(xié)同工作的系統(tǒng),為了提高系統(tǒng)的整體效率和吞吐量,必須考慮最大程度發(fā)揮每個節(jié)點(diǎn)的作用。負(fù)載均衡是保證系統(tǒng)運(yùn)行效率的關(guān)鍵技術(shù)。
數(shù)據(jù)一致性
在分布式系統(tǒng)中,數(shù)據(jù)被分散或者復(fù)制到不同的機(jī)器上,如何保證各臺主機(jī)之間的數(shù)據(jù)一致性將成為一個難點(diǎn)。因?yàn)榫W(wǎng)絡(luò)的異常會導(dǎo)致分布式系統(tǒng)中只有部分節(jié)點(diǎn)能夠正常通信,從而形成了網(wǎng)絡(luò)分區(qū)(Network Partition)。
服務(wù)的可用性
分布式系統(tǒng)中的任何服務(wù)器都有可能出現(xiàn)故障,且各種故障不盡相同。而運(yùn)行在服務(wù)器上的服務(wù)也可能出現(xiàn)各種異常情況,服務(wù)之間出現(xiàn)故障的時機(jī)也會相互獨(dú)立。通常,分布式系統(tǒng)要設(shè)計(jì)成允許出現(xiàn)部分故障而不影響整個系統(tǒng)的正常可用。
以上問題是分布式系統(tǒng)的基本特性,我們無法避免,只能想辦法進(jìn)行利用和管理,這就給我們設(shè)計(jì)和實(shí)現(xiàn)分布式系統(tǒng)提出了挑戰(zhàn)。微服務(wù)架構(gòu)本質(zhì)上也是一種分布式系統(tǒng),但在遵循通用分布式特性的基礎(chǔ)上,微服務(wù)架構(gòu)還表現(xiàn)出一定的特殊特性。下一節(jié),我們將圍繞微服務(wù)架構(gòu)的特殊特性展開討論。
- 零基礎(chǔ)搭建量化投資系統(tǒng):以Python為工具
- C語言程序設(shè)計(jì)(第2版)
- AngularJS深度剖析與最佳實(shí)踐
- Swift 3 New Features
- Flux Architecture
- H5頁面設(shè)計(jì):Mugeda版(微課版)
- Selenium Testing Tools Cookbook(Second Edition)
- C語言程序設(shè)計(jì)
- 基于SpringBoot實(shí)現(xiàn):Java分布式中間件開發(fā)入門與實(shí)戰(zhàn)
- 小程序,巧應(yīng)用:微信小程序開發(fā)實(shí)戰(zhàn)(第2版)
- Flowable流程引擎實(shí)戰(zhàn)
- 區(qū)塊鏈架構(gòu)之美:從比特幣、以太坊、超級賬本看區(qū)塊鏈架構(gòu)設(shè)計(jì)
- INSTANT Apache ServiceMix How-to
- Keil Cx51 V7.0單片機(jī)高級語言編程與μVision2應(yīng)用實(shí)踐
- 游戲設(shè)計(jì)的底層邏輯