可伸縮性原則是什么意思
系統(tǒng)架構(gòu)師是一個(gè)既需要掌控整體又需要洞悉局部瓶頸并依據(jù)具體的業(yè)務(wù)場(chǎng)景給出解決方案的團(tuán)隊(duì)領(lǐng)導(dǎo)型人物。下面是學(xué)習(xí)啦小編為你整理的架構(gòu)師面試題,希望對(duì)你有所幫助!
從最簡(jiǎn)單的水平來(lái)看,可伸縮性就是做更多的事情。更多的事情可以是響應(yīng)更多的用戶請(qǐng)求,執(zhí)行更多的工作,或處理更多的數(shù)據(jù)。設(shè)計(jì)軟件這件事本身是復(fù)雜的,而讓軟件做更多的工作也有其特有的問(wèn)題。這篇文章針對(duì)構(gòu)建可伸縮軟件系統(tǒng)提出了一些原則和方針。1. 減少處理時(shí)間增加應(yīng)用所做工作數(shù)量的一個(gè)方法就是減少完成單項(xiàng)工作所花費(fèi)的時(shí)間。舉例來(lái)說(shuō),減少處理一個(gè)用戶請(qǐng)求所需的時(shí)間意味著你能在同樣長(zhǎng)的時(shí)間內(nèi)處理更多的用戶請(qǐng)求。這里有一些本原則適用的例子和一些可能的實(shí)現(xiàn)策略。并置(Collocation):通過(guò)并置數(shù)據(jù)和代碼,減少因獲取所需數(shù)據(jù)而產(chǎn)生的必要開(kāi)銷。緩存:如果數(shù)據(jù)和代碼不能并置,就緩存數(shù)據(jù),以減少反復(fù)取數(shù)據(jù)的開(kāi)銷。池化:通過(guò)池化昂貴的資源,減少與其使用相關(guān)的開(kāi)銷。并行化:通過(guò)分解問(wèn)題、并行化獨(dú)立的步驟,減少完成一個(gè)工作單元所需的時(shí)間。分區(qū)處理:通過(guò)分割處理代碼、并置相關(guān)的分區(qū),盡可能將相關(guān)的處理過(guò)程集中在一起。遠(yuǎn)程處理:減少訪問(wèn)遠(yuǎn)程服務(wù)所花費(fèi)的時(shí)間,比如可以通過(guò)更粗粒度地劃分接口。遠(yuǎn)程還是本地是明確的設(shè)計(jì)決策,不能隨意來(lái)回更動(dòng),這一點(diǎn)應(yīng)當(dāng)牢記。還要考慮分布式計(jì)算的第一準(zhǔn)則——不要分布你的對(duì)象。軟件開(kāi)發(fā)人員總愛(ài)在不需要的地方引入抽象和層。是的,這些概念對(duì)軟件組件之間的解耦來(lái)說(shuō)是很好的工具,但它們可能會(huì)增加復(fù)雜性、影響性能,尤其是在每層的數(shù)據(jù)表示之間都需要轉(zhuǎn)換的情況下。因此,減少處理時(shí)間還要注意保證抽象不要過(guò)于抽象化,并且沒(méi)有過(guò)多的分層。另外,對(duì)于我們視為理所當(dāng)然的運(yùn)行時(shí)服務(wù),有必要理解其成本,因?yàn)槌撬鼈兲峁┝颂囟ǖ姆?wù)水平協(xié)議,否則很有可能最終會(huì)成為應(yīng)用中的瓶頸。2. 分區(qū)減少單個(gè)工作單元的處理時(shí)間能達(dá)到不錯(cuò)的效果,但當(dāng)你達(dá)到單進(jìn)程方案的極限,最終還是需要對(duì)系統(tǒng)作水平伸縮。在典型的Web應(yīng)用中,水平伸縮可能很簡(jiǎn)單,只要加入更多的Web服務(wù)器來(lái)處理用戶請(qǐng)求,再給它們加上負(fù)載均衡就行了。但是,你可能會(huì)發(fā)現(xiàn)總體架構(gòu)的某些部分會(huì)成為資源爭(zhēng)用的焦點(diǎn),因?yàn)橐磺袞|西都會(huì)在同一時(shí)間變得忙碌起來(lái)。一個(gè)很好的例子就是所有Web服務(wù)器后端的單一數(shù)據(jù)庫(kù)服務(wù)器。當(dāng)這個(gè)單一的數(shù)據(jù)庫(kù)服務(wù)器變成瓶頸時(shí),你必須改變方法,其中一種方式就是采用分區(qū)策略。簡(jiǎn)而言之,這涉及到將架構(gòu)的單個(gè)部分分解成更小、更容易管理的部分。將單個(gè)的元素分割成更小的部分能實(shí)現(xiàn)水平伸縮,這恰恰也是 eBay這樣的大型網(wǎng)站采用、以此來(lái)確保它們的架構(gòu)可伸縮的技術(shù)。分區(qū)是一個(gè)很好的解決辦法,盡管你可能會(huì)發(fā)現(xiàn)犧牲了一致性。至于如何分割你的系統(tǒng),那要看情形而定。真正無(wú)狀態(tài)的組件能簡(jiǎn)單地作水平伸縮,將工作負(fù)載分散到所有實(shí)例上,讓組件的所有實(shí)例都能有效地運(yùn)行。另一方面,如果需要維護(hù)某狀態(tài),你需要找到一種工作量分割策略能允許有狀態(tài)組件的多重實(shí)例,讓每個(gè)實(shí)例負(fù)責(zé)工作和/或數(shù)據(jù)的一個(gè)獨(dú)特的子集。3. 可伸縮性在于并發(fā)可伸縮性天生就和并發(fā)聯(lián)系在一起;畢竟,它就是要在同樣的時(shí)間內(nèi)做更多的工作。像EJB早期版本這樣的技術(shù)試圖提供一種簡(jiǎn)化的編程模型,鼓勵(lì)我們編寫單線程的組件。遺憾的是,組件往往要依賴于其它組件,還是導(dǎo)致了并發(fā)問(wèn)題。如果沒(méi)有考慮并發(fā),系統(tǒng)中的數(shù)據(jù)會(huì)很容易被損壞。另一方面,圍繞并發(fā)做了太多的保護(hù)會(huì)導(dǎo)致系統(tǒng)實(shí)質(zhì)上變成串行的,限制了伸縮的能力。并發(fā)編程不是很難做到,在構(gòu)建可伸縮系統(tǒng)的時(shí)候,有一些簡(jiǎn)單的原則會(huì)有所幫助。如果你確實(shí)需要持有鎖(比如本地對(duì)象、數(shù)據(jù)庫(kù)對(duì)象等),試著盡可能短地持有它們。設(shè)法減少對(duì)共享資源的爭(zhēng)用,并盡可能是爭(zhēng)用避開(kāi)關(guān)鍵處理路徑(比如通過(guò)異步調(diào)度工作)。任何針對(duì)并發(fā)的設(shè)計(jì)都需要預(yù)先完成,以便能被充分地理解哪些資源可以被安全共享、哪里可能會(huì)是潛在的可伸縮性瓶頸。4. 必須知道需求為了構(gòu)建一個(gè)成功的軟件系統(tǒng),你需要知道你的目標(biāo)是什么、你針對(duì)什么去做。盡管功能性需求往往是明確的,但常常會(huì)缺少非功能性需求(或系統(tǒng)質(zhì)量需求)。如果你真是需要構(gòu)建一套高可伸縮的軟件,那你首先需要調(diào)查清楚關(guān)鍵組件/工作流的以下特質(zhì):目標(biāo)平均性能和峰值性能(即響應(yīng)時(shí)間、延遲等)。目標(biāo)平均負(fù)荷和峰值負(fù)荷(即并發(fā)用戶、信息量等)。性能和可伸縮性可接受的極限。性能也許不是最緊要的方面,但你必須盡早知道這個(gè)信息,因?yàn)樘幚砜缮炜s性的方法會(huì)由性能需求決定。5. 持續(xù)測(cè)試?yán)斫饬诵枨缶涂梢蚤_(kāi)始設(shè)計(jì)和構(gòu)建解決方案。我們提出的設(shè)計(jì)、編寫的代碼實(shí)際上都是靜態(tài)的,所以你在執(zhí)行之前不能完全斷定它會(huì)怎樣運(yùn)轉(zhuǎn)。此外,所有關(guān)于性能和可伸縮性的決策應(yīng)該由證據(jù)支持的原因也在于此,而且應(yīng)當(dāng)從項(xiàng)目一開(kāi)始就收集和審核這些證據(jù),此后也要一直繼續(xù)。換句話說(shuō),就是設(shè)立貫穿系統(tǒng)的可度量目標(biāo),證實(shí)并度量實(shí)際的性能,并在項(xiàng)目的各個(gè)階段考慮性能。最常犯的錯(cuò)誤之一是,我們對(duì)系統(tǒng)性能和可伸縮性的見(jiàn)解會(huì)被我們自己的經(jīng)驗(yàn)或道聽(tīng)途說(shuō)所混淆。你可能要審核對(duì)工程做出的其它決策,這樣做的原因之一是要滿足系統(tǒng)的非功能性特性。比如說(shuō),非功能性需求可能會(huì)影響你選擇不使用標(biāo)準(zhǔn),改用非主流/流行的一些東西。非功能性需求可能會(huì)打破僵化的教條,證據(jù)勝過(guò)教條。6. 架構(gòu)先行或許對(duì)構(gòu)建可伸縮的系統(tǒng)來(lái)說(shuō)最重要的原則是,如果你需要使系統(tǒng)具備這樣的性質(zhì),就必須預(yù)先設(shè)計(jì)出這樣的性質(zhì)。很多人(包括我自己)陷入的陷阱,就是以為可以構(gòu)建一個(gè)應(yīng)用,它會(huì)自動(dòng)地垂直伸縮(scale up)或水平伸縮(scale out),尤其是在J2EE剛出現(xiàn)的時(shí)候。設(shè)計(jì)為可水平伸縮的應(yīng)用幾乎總能垂直伸縮,但是設(shè)計(jì)為垂直伸縮的應(yīng)用幾乎不可能水平伸縮。大多數(shù)應(yīng)用能通過(guò)在更加強(qiáng)大的硬件上運(yùn)行來(lái)垂直伸縮,但水平伸縮卻是一個(gè)更為復(fù)雜的問(wèn)題。比如說(shuō),你怎么確保數(shù)據(jù)在應(yīng)用實(shí)例之間保持一致性?你如何使你的單例和同步代碼塊跨線程工作?當(dāng)然,預(yù)先思考這件事情不一定等同于做一個(gè)瀑布式的、預(yù)先的大設(shè)計(jì)。迭代和敏捷過(guò)程都是助力,它們能提供一個(gè)框架幫助我們可以做出剛好夠用的設(shè)計(jì)來(lái)解決問(wèn)題。要?jiǎng)?wù)實(shí)。哦,不管我們自認(rèn)為是多么擅長(zhǎng)于設(shè)計(jì)可伸縮的應(yīng)用,不要相信自己、盡早地編寫/測(cè)試代碼才是最好的舉動(dòng)。7. 著眼于全局最后,記著要著眼于全局——看到樹(shù)木之前先看看森林。對(duì)我們來(lái)說(shuō),在細(xì)粒度代碼級(jí)別調(diào)整組件確實(shí)很容易,但最終需要優(yōu)化的卻是作為一個(gè)整體的系統(tǒng)。關(guān)注每一個(gè)環(huán)節(jié)的性能和可伸縮性,必要時(shí)犧牲局部的優(yōu)化。如果你需要使用性能分析工具確定瓶頸,不妨去做,但在對(duì)全局的性能有所認(rèn)識(shí)之前先不要急于動(dòng)手。由于性能與整個(gè)系統(tǒng)所有等待時(shí)間的集合成反比,任何等待時(shí)間增加得比負(fù)載還快的操作都會(huì)成為問(wèn)題。盡管說(shuō)了這么多,但我還想指出,如果你發(fā)現(xiàn)滿足性能和可伸縮性目標(biāo)很困難,那就有必要懷疑一下是否選擇了正確的架構(gòu)。還是那句話,著眼于全局,確保有人在承擔(dān)架構(gòu)師的責(zé)任??偨Y(jié)這篇文章針對(duì)構(gòu)建可伸縮應(yīng)用提出了一些原則和方針,覆蓋了軟件開(kāi)發(fā)過(guò)程中許多不同的方面。無(wú)論誰(shuí)要構(gòu)建可伸縮的系統(tǒng),我能給他的最好建議就是你需要明確地考慮并設(shè)計(jì)你的系統(tǒng)??缮炜s性不是魔術(shù),它也不會(huì)無(wú)償獲得。最后一點(diǎn),更快的硬件也許能救你于一時(shí),但還是不要依賴它為妙!關(guān)于本文2005年年底,英國(guó)倫敦舉辦了針對(duì)架構(gòu)師的非官方峰會(huì),本文中的大多數(shù)原則就來(lái)源于其中一場(chǎng)可伸縮性討論的一些筆記。該峰會(huì)由Alexis Richardson、Floyd Marinescu、Rod Johnson、John Davies、Steve Ross-Talbot組織。題為“JP Rangaswami談企業(yè)中的開(kāi)源與信息前景”的視頻也來(lái)源于此峰會(huì)。關(guān)于作者Simon是一名注重實(shí)踐的軟件架構(gòu)師,他在Detica’的全球金融市場(chǎng)集團(tuán)工作。Simon專心參與的項(xiàng)目有桌面客戶端和Web應(yīng)用,也有高度可伸縮的分布式系統(tǒng)和面向服務(wù)的體系架構(gòu)(SOA)。他的專攻技術(shù)是Java,作為一名注重實(shí)踐的權(quán)威,他被要求建議并設(shè)計(jì)解決方案;定義、交付并保證所選擇的架構(gòu)適合于目的,能滿足非功能性需求。Simon已經(jīng)編寫或與他人合著過(guò)很多Java EE Web技術(shù)相關(guān)的書籍,在數(shù)次會(huì)議上發(fā)表過(guò)演講,并創(chuàng)建了Coding the Architecture——一個(gè)介紹關(guān)于軟件架構(gòu)實(shí)用和務(wù)實(shí)觀點(diǎn)的網(wǎng)站。閱讀英文原文:Scalability Principles查看全文:http://www.w3ccollege.org/architecture/scalability-principles.html
面試題相關(guān)文章: