開放源代碼已經成爲一些大型網站的基本原則。而在這些網站成長的過程當中,一些優秀的實踐經驗和規則也出如今他們的結構中。本文旨在介紹一些在大型網站結構設計的過程當中須要注意的關鍵問題以及實現目標的基礎工做。html 本文側重於介紹網絡系統,儘管一些準則在其餘分佈式系統中也是適用的。web |
|
1.1. web分佈式系統的設計原則搭建和運營一個可伸縮的web站點或者應用程序意味着什麼?在原始層面上這僅僅是用戶經過互聯網鏈接到遠程資源-使系統變得可伸縮的部分是將資源、或者訪問的資源,分佈於多個服務器上。數據庫 像生活中大多數事情同樣,當構建一個web服務時花時間提早作好計劃從長遠看來仍是頗有幫助的;瞭解一些注意事項和大網站背後的權衡原則能夠在建立小型網站時作出更明智的決定。如下是一些影響大規模web系統設計的關鍵原則:編程
|
|
以上每一個原則都爲設計分佈式web架構提供了基礎決策。然而,他們也能彼此互斥,例如要實現某個目標就要以另外的做爲代價。一個基本的例子:選擇經過單純 增長更多的服務器(可擴展性)來增長地址容量,是以可管理性(你必須操做增長的服務器)和成本(服務器的價格)爲代價的。緩存 當設計任何的web應用程序時,考慮這些關鍵原則都是很重要的,即便得認可一個設計可能要犧牲它們之中的一個或者多個。性能優化 |
1.2. 基礎當設計一個系統架構時,有一些東西是要考慮的:正確的部分是什麼,怎樣讓這些部分很好地融合在一塊兒,以及好的折中方法是什麼。一般在系統架構須要以前就爲它的可擴展性投資不是一個聰明的商業抉擇;然而,在設計上的深謀遠慮能在將來節省大量的時間和資源。服務器 這部分關注點是幾乎全部大型web應用程序中心的一些核心因素:服務、冗餘、劃分和錯誤處理。每個因素都包含了選擇和妥協,特別是上部分提到的設計原則。爲了詳細的解析這些,最好是用一個例子來開始。網絡 |
實例:圖片託管應用有時候你可能會在線上傳一張圖片。對於那些託管並負責分發大量圖片的網站來講,要搭建一個既節省成本又高效還能具有較低的延遲性(你能快速的獲圖片)的網站架構確實是一種挑戰。架構 咱們來假設一個系統,用戶能夠上傳他們的圖片到中心服務器,這些圖片又可以讓一些web連接或者API獲取這些圖片,就如同如今的Flickr或者 Picasa。爲了簡化的須要,咱們假設應用程序分爲兩個主要的部分:一個是上傳圖片到服務器的能力(一般說的寫操做),另外一個是查詢一個圖片的能力。然 而,咱們固然想上傳功能很高效,可是咱們更關心的是可以快速分發能力,也就是說當某我的請求一個圖片的時候(好比,一個web頁面或者其它應用程序請求圖 片)可以快速的知足。這種分發能力很像web服務器或者CDN鏈接服務器(CDN服務器通常用來在多個位置存儲內容一邊這些內容可以從地理位置或者物理上 更靠近訪問它的用戶,已達到高效訪問的目的)氣的做用。併發 |
|
系統其餘重要方面:
Figure 1.1是一個簡化的功能圖。
![]() 在這個圖片主機的例子裏,可碰見系統必需快速,它的數據存儲要可靠以及這些全部的屬性都應該高度的可擴展。創建這個應用程序的一個小版本不是很重要並且很 容易部署在單一的服務器上;然而,這不是這節裏的感興趣部分。假設下咱們想建一個會增加到和Flickr痛讓規模的東西。 |
當要考慮設計一個可擴展的系統時,爲功能解耦和考慮下系統每部分的服務都定義一個清晰的接口都是頗有幫助的。在實際中,在這種方式下的系統設計被成爲面向 服務架構(SOA)。對於這類型的系統,每一個服務有本身獨立的方法上下文,以及使用抽象接口與上下文的外部任何東西進行交互,典型的是別的服務的公共 API。 把一個系統解構爲一些列互補的服務,可以爲這些部分從別的部分的操做解耦。這樣的抽象幫助在這些服務服、它的基礎環境和服務的消費者之間創建清晰的關係。 創建這種清晰的輪廓能幫助隔離問題,但也容許各模塊相對其它部分獨立擴展。這類面向服務設計系統是很是相似面向對象設計編程的。 |
在咱們的例子中,上傳和檢索圖像的請求都是由同一個服務器處理的;然而,由於系統須要具備伸縮性,有理由要將這兩個功能分解爲各由本身的服務進行處理。 快速轉發(Fast-forward)假定服務處於大量使用中;在這種狀況下就很容易看到,讀取圖像所花的時間中有多少是因爲受到了寫入操做的影響(由於 這兩個功能將競爭使用它們共享的資源)。取決於所採用的體系結構,這種影響多是巨大的。即便上傳和下載的速度徹底相同(在絕大多數IP網絡中都不是這樣 的狀況,大部分下載速度和上傳速度之比都至少設計爲3:1),文件讀取操做通常都是從高速緩存中進行的,而寫操做卻不得不進行最終的磁盤操做(並且可能要 寫幾回才能達成最後的一致狀態)。即便全部內容都已在內存中,或者從磁盤(好比SSD磁盤)中進行讀取,數據庫寫入操做幾乎每每都要慢於讀取操做。 (Pole Position是一個開源的DB基準測試工具,http://polepos.org/,測試結果參見 http://polepos.sourceforge.net/results/PolePositionClientServer.pdf) |
這種設計另外一個潛在的問題出在web服務器上,像Apache或者lighttpd一般都有一個可以維持的併發鏈接數上限(默認狀況下在500左右,不過 能夠更高)和最高流量數,它們會很快被寫操做消耗掉。由於讀操做能夠異步進行,或者採用其它一些像gizp壓縮的性能優化或者塊傳輸編碼方式,web服務 器能夠經過在多個請求服務之間切換來知足比最大鏈接數更多的請求(一臺Apache的最大鏈接數設置爲500,它每秒鐘提供近千次讀請求服務也是正常 的)。寫操做則不一樣,它須要在上傳過程當中保持鏈接,因此大多數家庭網絡環境下,上傳一個1MB的文件可能須要超過1秒的時間,因此web服務器只能處理 500個這樣併發寫操做請求。
![]() |
對於這種瓶頸,一個好的規劃案例是將讀取和寫入圖片分離爲兩個獨立的服務,如圖Figure 1.2.所示。這讓咱們能夠單獨的擴展其中任意一個(由於有可能咱們讀操做比寫操做要頻繁不少),同時也有助於咱們理清每一個節點在作什麼。最後,這也避免了將來的憂慮,這使得故障診斷和查找問題更簡單,像慢讀問題。
這種方法的優勢是咱們可以單獨的解決各個模塊的問題-咱們不用擔憂寫入和檢索新圖片在同一個上下文環境中。這兩種服務仍然使用全球資料庫的圖片,可是它們 可經過適當的服務接口自由優化它們本身的性能(好比,請求隊列,或者緩存熱點圖片-在這之上的優化)。從維護和成本角度來看,每一個服務按需進行獨立規模的 規劃,這點很是有用,試想若是它們都組合混雜在一塊兒,其中一個無心間影響到了性能,另外的也會受影響。