如何設計一個優秀的分佈式系統?重要因素、工具、策略都在這裡

關注我,可以獲取最新知識、經典面試題以及技術分享

介 紹

今天的應用程序可以說是分佈式系統開發中的一項奇蹟。基於不同的系統架構,構成應用程序的每個功能或服務可能在不同的系統上執行,而系統位於不同的地理位置,使用不同的計算機語言編寫。應用程序的組件可能託管在一個功能強大的系統上,該系統由用戶自己攜帶,並且可以和世界各地的應用程序組件或服務進行通信(他們都是數據中心的副本)。

而令人驚訝的是,使用這些應用程序的用戶通常並不會對複雜環境的請求作出響應。這樣的請求包含了像本地時間、本地天氣或前往酒店的方向等等。

讓我們慢慢開始介紹,看看使這一切成為可能的工業魔法,並思考開發人員在處理這種複雜性時應該牢記哪些思想和規則。

系統設計的演變史

如何設計一個優秀的分佈式系統?重要因素、工具、策略都在這裡

從程序員編寫應用程序,手工將它們編譯成他們正在使用的機器的語言,然後使用切換開關將單個機器指令和數據直接輸入到計算機的內存開始,應用程序開發已經走過了漫長的道路

隨著處理器越來越強大,系統內存和在線存儲容量增加,計算機網絡能力顯著增強,開發方法也產生了變化。現在,數據可以從地球的一段傳遞到另一端,而速度比早期電腦將數據從系統內存轉移到處理器本身的速度還要快!

讓我們看看這一驚人轉變中的一些亮點。

單體設計

早期的計算機程序都是基於單體設計的,所有的應用程序組件都被設計成在一臺機器上執行。這意味著像用戶界面(如果用戶實際能與程序交互)、應用程序處理規則、數據管理、存儲管理和網絡管理(如果計算機連接到計算機網路上)等功能都包含在了程序中。

這些雖然編寫起來簡單,但這些程序會變得越來越複雜,越來越難以形成文檔,也難以更新和更改。這時,機器本身對企業來說就成了最大的開銷,因此應用程序的設計是為了盡最大可能使用機器。

客戶端/服務器架構

隨著處理器越來越強大,系統和在線存儲容量增加,數據通信更快、更經濟,應用程序的設計也隨之發展,以適應發展的速度。應用程序邏輯被重構或分解,允許每個應用程序在不同的機器上執行,並且在組件之間插入了不斷改進的網絡。這使得一些特性可以遷移到當前可用的成本最低的計算環境中。這一演變經歷了一下幾個階段:

  • 終端和終端模擬早期的分佈式計算依賴於特別用途的用戶訪問設備——終端。應用程序必須理解它們使用的通信協議,並直接向設備發出命令。當廉價的個人計算機(PC)出現時,終端被運行終端模擬程序的PC所取代。此時,應用程序的所有組件仍然駐留在單個大型機或小型計算機上
  • 輕量客戶端隨著PC的功能越來越強大,支持更大的內部和在線存儲,網絡性能進一步提高,企業對其應用程序進行了細分或分解,以便在本地PC上提取和執行用戶界面。應用程序的其餘部分則繼續在數據中心的系統上執行。這些PC通常比它們所替代的終端便宜,並且它們還有額外的優點。這些PC是多功能設備,它們可以運行在它們所替換的終端上無法運行的、卻能提高辦公效率的應用程序。這種組合促使企業在更新或刷新應用程序時,開始傾向於客戶端/服務器應用體系結構。

  • 中型客戶端PC的發展仍在快速進行。一旦出現了更強大、存儲容量更大的系統,企業就會使用它們,將更多的處理操作從數據中心昂貴的系統遷移到便宜的用戶辦公桌上。這時,用戶界面和一些計算任務就遷移到了本地的PC上。這樣大型機和小型計算機(現在成為服務器)就有了更長的使用壽命,從而降低了企業總體的計算成本。
  • 重型客戶端隨著PC變得越來越強大,更多的應用程序度可以從後端服務器遷移過來。在這裡,除了數據和存儲管理功能之外的所有功能都已遷移。
  • 進入互聯網和萬維網這時,公共互聯網和萬維網出現了。客戶端/服務器計算的方式仍然在使用。為了降低總體成本,一些企業開始重新架構它們的分佈式應用程序,便於使用標準的internet協議進行通信,並使用Web瀏覽器代替之前定製的用戶界面功能。後來,一些應用程序的特性通過Javascript語言重新編寫,這樣它們就可以在客戶端的計算機上本地執行。

  • 服務器的改進行業創新並不僅僅關注客戶端側的通信鏈路,對服務器也做了很大的改進。企業開始利用許多更小、更便宜的符合行業標準的服務器,通過它們強大的功能來支持部分或者全部原來基於大型機的功能。這樣它們可以減少需要部署的昂貴主機系統的數量。接著,遠程PC就可以和許多服務器通信,每個服務器都支持自己的應用程序組件。在此環境中使用了專用的數據庫和文件服務器。之後,再將其他應用程序功能遷移到應用程序服務器。網絡是另一個業界高度關注的領域。企業開始使用提供防火牆以及其他安全功能的專用網絡服務器、文件緩存功能來加速應用程序的數據訪問,電子郵件服務器、web服務器、web應用程序服務器、分佈式命名服務器這些服務器跟蹤和控制用戶憑證,用於訪問數據和應用程序。封裝在設備服務器中的網絡服務列表一直在增長。

基於對象的開發

PC和服務器功能的快速變化,加上處理能力、內存和網絡這三者的價格的大幅下降,這些都對應用程序開發產生了重大影響。IT領域中最大的成本開銷不再是硬件和軟件,而是變成了通信、IT服務(員工)、電力以及冷卻系統。


軟件開發、軟件維護和IT操作出現了新的重要性,開發過程也發生了變化以迎合新的形勢,即系統便宜,而人員、通信和電力越來越貴。

如何設計一個優秀的分佈式系統?重要因素、工具、策略都在這裡

企業希望通過改進數據和應用程序架構來充分發揮員工的價值。其結果就是面向對象的應用程序和開發方法。許多編程語言,例如下面的語言,都支持這種方式:

C++、C#、COBOL、Java、PHP、Python、Ruby

在定義和記錄數據結構時,應用程序開發者的編寫變得更加系統化來適應變化。這種方式還使得維護和改進應用程序更加容易。

開源軟件

Opensource.com為開源軟件提供了以下定義:“開源軟件是帶有源代碼的軟件,任何人都可以檢查、修改和增強代碼。”“而有些軟件的源代碼只有創建它的個人、團隊或組織才能修改——並且保有對它的獨佔控制。人們稱這種軟件為‘專有’或‘閉源’軟件。”

只有專有軟件的原始作者才能合法地複製、檢查和修改該軟件。為了使用專有軟件,計算機用戶必須同意(通常通過接受首次運行該軟件時顯示的許可證),如果軟件作者沒有明確允許的話,他們不會對軟件做任何的修改。微軟Office和Adobe Photoshop都是專有軟件的例子。

雖然開源軟件在計算機早期就已經存在,但直到20世紀90年代,當完整的開源操作系統、虛擬化技術、開發工具、數據庫引擎和其他重要功能出現時,它才走到了前臺。開源技術通常是基於web和分佈式計算的關鍵組件。其中,以下類別的開源軟件很受歡迎:

  • 開發工具
  • 應用支持
  • 數據庫(flat文件,SQL,No-SQL,以及內存)
  • 分佈式文件系統
  • 消息傳輸/隊列
  • 操作系統
  • 聚類

分佈式計算

強大的系統、快速的網絡以及複雜軟件可用性的結合,已經將主要的應用程序開發從單一轉向了更加分佈式的形式。然而企業已經意識到,有時候從頭開始比嘗試重構或分解舊的應用程序要更好。

當企業進行創建分佈式應用程序的工作時,常常會發現一些有趣的副產品。一個設計得當的應用程序,它已經分解成單獨的功能或服務,可以由單獨的團隊並行開發。

快速應用程序開發和部署(也稱為DevOps)就是一種利用新環境的方法。

面向服務的架構

隨著行業從客戶端/服務器的計算模式,發展到更加分佈式的方法,“面向服務的架構”一詞出現了。這種方法基於分佈式系統的概念、消息隊列和交付中的標準,以及將XML消息傳遞作為共享數據和數據定義的標準方法。

各個應用程序的功能被打包成面向網絡的服務,這些服務接收一條消息,請求它們執行特定的服務,在它們執行服務之後,將響應發送回請求該服務的函數。

這種方法還提供了另一個好處,即可以將給定的服務託管在網絡的多個位置。這既提高了整體性能,又增強了可靠性。

除此之外,現在還有很多工作負載管理工具,它用於接收服務請求、檢查可用容量、將請求轉發給具有最大可用容量的服務,然後將響應發送回請求者。如果特定的服務器沒有及時響應,工作負載管理器會簡單地向服務轉發另一個實例。它還會將沒有響應的服務標記為失敗,並且在它收到一條表明服務仍在運行的消息之前,不會向它發送額外的請求。


設計分佈式系統的重要考慮因素

現在我們已經走過了50多年的計算機歷史,下面讓我們來看看分佈式系統開發人員的一些經驗法則。需要考慮的東西很多,因為分佈式解決方案可能有組件和服務在許多地方、不同類型的系統中運行,而且必須來回傳遞消息才能執行工作。要想成功創建這些解決方案,謹慎思考是必須的。除此之外還必須為所使用的每種主機系統、開發工具和消息傳遞系統提供專門的知識。

確定需要做什麼

我們首先要考慮的事情,是我們究竟需要完成什麼。雖然這聽起來很簡單,但卻非常重要。

令人驚訝的是,許多開發人員在知道具體需要什麼之前就開始構建東西。通常情況下,這意味著他們構建了不必要的功能,浪費了時間。引用Yogi Berra的話就是:“如果你不知道自己要去哪裡,你最終會去往別的地方”。

首先需要知道要做什麼,已經有哪些工具和服務可用,以及使用最終解決方案的人應該看到什麼。

交互和批處理

快速響應和低延遲常常是我們的需求,因此比較明智的做法是考慮在用戶等待時應該做什麼,以及可以將什麼放入批處理過程中,而這些批處理執行在事件驅動或時間驅動的計劃中。

在考慮了功能的初始分割之後,比較好的做法是計劃何時需要執行後臺、批處理進程、這些功能操作哪些數據、以及如何確保這些功能是可靠的、何時可用以及如何防止數據丟失。

功能應該託管在哪裡

只有在詳細計劃了“完成什麼”之後,才應該考慮“在哪裡”以及“如何做”。開發人員有各自最喜歡的工具和方法,並且經常會調用它們,即使可能不是最佳的選擇。Bernard Baruch說過:“如果你只有一把錘子,那麼所有東西看起來都像釘子”。

瞭解企業開發的企業標準也很重要。僅僅因為工具目前很流行就選擇它是不明智的。這個工具可以完成這些工作,但是需要記住的是,它構建的所有東西都需要維護。如果你構建了一些只有自己才能理解或者維護的東西,那麼在你職業生涯的剩下時間中,你可能已經把自己束縛在這一功能上了。我自己也有過這種經歷,自認為自己創建的功能工作正常、輕量而且可靠。但在我離開那家公司後的十年裡,我不斷地收到關於這些功能的電話,因為後來的開發人員無法理解這些功能是如何實現的,而我寫的文件又早就被丟掉了。

在分佈式解決方案中,每個功能或服務都應該分別考慮。該功能應該在企業數據中心?還是使用雲服務提供商?還是兩者兼有?另外還要考慮到在某些行業中存在法規要求,這些要求指導我們選擇需要在何處以及如何維護和存儲數據。

其他需要考慮的東西還包括:

  • 該功能的主機應該是什麼類型的系統。有沒有系統架構更合適該功能?系統應該基於ARM、x86、SPARC、Precision、Power,還是大型機?
  • 會有某種特定的操作系統為該功能提供了更好的計算環境嗎?Linux、Windows、UNIX、System I,或是System Z會是更好的平臺嗎?
  • 某特定的開發語言是否更適合該功能?它是一種特定類型的數據管理工具嗎?該用Flat文件、SQL數據庫還是No-SQL數據庫?還是說非結構化的存儲機制更好?
  • 功能應該託管在虛擬機中還是容器中,方便遷移、自動化以及編排嗎?

在本世紀初,運行Windows或Linux虛擬機往往是首選。雖然它們為方法提供了重要的隔離,並且在必要時很容易重啟或移動他們,但是他們的處理、內存以及存儲要求相當高。容器是處理虛擬化的另一種方式,它提供了類似的隔離級別,能夠重新啟動和遷移方法,而且消耗的處理能力、內存或存儲都要小得多。

性能

性能是另一個重要的考慮因素。在定義組成解決方案的功能或服務時,開發人員應該注意它們是否有重要處理、內存或存儲需求。仔細研究這些問題非常重要,這樣才能知道是否可以進一步細分或分解這些功能。

進一步的分割會允許並行處理的增加,這樣能很大可能地提供性能上的改進。當然,這樣做的代價是,它也增加了複雜性,可能會更加難以管理和保證安全。

可靠性

在高風險的企業環境中,解決方案的可靠性至關重要。開發人員必須考慮何時可以要求人們重新輸入數據、重新運行功能,或者何時功能將不可用。

數據庫開發人員在20世紀60年代就遇到了這個問題,並開發了原子功能的概念。也就是說,功能必須完成或者部分的更新必須回滾,以使得數據處於功能開始前的狀態。分佈式系統也需要這種思維方式,確保即使在出現服務故障和事物中斷的情況下也能保證數據完整性。

例如,在關鍵消息傳遞系統中,在確認消息已經被接收方收到之前,消息必須被一直存儲好。如果消息沒能成功收到,則必須重新發送原始消息,並向系統管理報告故障。

可管理性

儘管沒有核心應用程序功能那麼有趣,但可管理性仍然是保證應用程序正常運轉的關鍵因素。所有分佈式功能都必須得到充分的檢測,讓管理員瞭解每個功能的當前狀態,並在需要時更改功能的參數。畢竟,分佈式系統是由比它們所替代的單片系統更多的活動部件組成的。開發人員必須時刻注意讓這個分佈式計算環境易於使用和維護。

這給我們帶來了一個絕對的要求,即必須對所有分佈式功能進行充分的工具化,讓管理員瞭解到它們的當前狀態。畢竟,分佈式系統本質上比它們所替代的單片系統更加複雜,並且有更多的活動部件。

安全性

確保分佈式系統安全性,比單片環境中安全問題的難度高了一個數量級。每個功能都必須單獨保密,功能之間的通信連接也必須保密。隨著網絡規模和複雜性的增長,開發人員必須考慮如何控制對功能的訪問,如何確保只有授權用戶才能訪問這些功能,以及如何將服務與其他服務隔離開來。

安全性是一個關鍵元素,必須添加到每個功能中而不是之後才加入。必須避免和彙報對功能和數據的未經授權訪問。

隱私性

關於隱私性的話題有越來越多的規範。對與每個面向客戶系統的開發人員來說,歐盟的GDPR以及美國的HIPPA法規都是重要的考慮因素。

掌控複雜性

開發人員必須花時間考慮如何將複雜計算環境中全部的內容組合在一起。服務應該被封裝成一個單一的功能 ,或者少量緊密相關的功能,想要維護這樣的規則非常困難。如果一個功能在多個地方實現,那麼想要維護和更新就會很困難。當一個功能的實例沒有更新會怎樣?這個問題非常具有挑戰性

這就意味著,對於複雜應用程序的開發人員來說,維護一個用於顯示每個功能所在位置的可視化模型就非常有用了,這樣,如果規則或業務需求發生變化,就可以對其進行更新。

通常情況下,開發人員就必須花時間記錄他們做了什麼,什麼時候做了更改,以及這些更改的目的是什麼,這樣其他人員就不必為了瞭解一個功能在哪裡或者它是如何工作的而費心思去理解成堆的代碼。

要成為分佈式系統的架構師,開發人員就必須要掌握複雜性。

開發人員必須掌握的方法

開發人員必須掌握分解和重構應用程序體系結構,從團隊的角度思考問題,並提高他們在快速應用程序開發和部署(DevOps)方法方面的技能。畢竟,他們必須能夠系統地思考哪些功能彼此獨立,哪些功能依賴於其他功能的輸出來工作。依賴於其他功能的這部分功能最好作為單個服務來實現。將它們作為獨立的功能實現,可能會產生不必要的複雜性,導致應用程序性能低下,並且給網絡帶來不必要的負擔。

虛擬化技術涵蓋了許多基礎

虛擬化是一個比虛擬機軟件或容器更大的類別。這兩個功能都被認為是虛擬化技術。在目前的應用程序中,至少有7種不同類型的虛擬化技術在使用。虛擬化技術可用於增強用戶訪問應用程序的方式、應用程序在何處以及如何執行、處理在何處以及如何執行、網絡功能怎麼樣、數據在哪裡以及如何存儲、安全性如何實現以及管理功能如何實現。下面的虛擬化技術模型可能有助於開發人員理解虛擬化的概念。

如何設計一個優秀的分佈式系統?重要因素、工具、策略都在這裡

從軟件定義的解決方案角度考慮

對於開發人員來說,從“軟件定義的”解決方案的角度來考慮也是非常重要的。這也就是說,將控制從實際的處理中分割出來,這樣功能就可以被自動化以及編排了。

有哪些工具和策略可供使用

當開發人員步入這個複雜的世界時,他們不應該覺得自己是獨立的。供應商和開源社區提供了許多強大的工具。各種形式的虛擬化技術都可以成為開發人員最好的朋友。

1.虛擬化技術是你最好的朋友

  • 容器讓輕鬆地開發功能成為可能,這些功能可以在不互相干擾的情況下執行,並且可以根據工作負載需求從一個系統遷移到另一個系統。
  • 編排技術讓控制多個功能成為可能,確保它們運行良好且可靠。它還可以在失敗的情況下重啟或移動它們。
  • 支持增量開發:功能可以並行開發,並在準備好時部署。它們還可以用新特性進行更新,而不需要在其他地方進行更改。
  • 支持高度分佈式系統:既可以在企業數據中心本地部署功能,也可以在雲服務提供商的數據中心遠程部署功能。

2.從服務的角度考慮

這意味著開發人員必須考慮服務以及服務之間如何通信。

定義良好的API

定義良好的API可以讓多個團隊更好地協同工作,並且確保一切都能按照計劃組合在一起。通常情況下這意味著要做更多的前期工作,但最終是非常值得的。為什麼?因為整體開發可以更快。而且它還可以減少文檔工作的工作量。

支持快速應用程序開發

這種方法對於快速應用程序開發和快速原型開發(即DevOps)來說也是完美的。如果執行得當,DevOps還可以只需很短的部署時間。

從標準的角度思考

分佈式系統的開發人員應該充分考慮多供應商的國際標準,而不是單單依賴於一個供應商。這種方法避免了廠商的鎖定,並且可以找到在不同領域最出彩的那個供應商。

總 結

值得注意的一點是,快速應用程序開發和分佈式系統部署的指南,是從“慢慢來”開始的。最明智的做法就是先計劃好你要去哪裡,你要做什麼,否則你很可能最終沒能達成目標、開發預算耗盡並且毫無成果。

覺得此文對你有幫助的話,點個贊,點個關注唄!!


分享到:


相關文章: