構建高可擴Web架構和分布式系統實戰

jopen 9年前發布 | 12K 次閱讀 分布式 分布式/云計算/大數據

1 Web分布式系統設計的原則

構建并運營一個可伸縮的Web站點或應用程序到底是指什么?在最初,僅是通過互聯網連接用戶和訪問遠程資源。

和大多數事情一樣,當構建一個Web服務時,需要提前抽出時間進行規劃。了解大型網站創建背后的注意事項以及學會權衡,會給你帶來更加明智的決策。下面是設計大型Web系統時,需要注意的一些核心原則:

  • 可用性
  • 性能
  • 可靠性
  • 可擴展
  • 易管理
  • 成本
  • </ul>

    上面的這些原則給設計分布式Web架構提供了一定的基礎和理論指導。然而,它們也可能彼此相左,例如實現這個目標的代價是犧牲成本。一個簡單的例子:選擇地址容量,僅通過添加更多的服務器(可伸縮性),這個可能以易管理(你不得不操作額外的服務器)和成本作為代價(服務器價格)。

    無論你想設計哪種類型的Web應用程序,這些原則都是非常重要的,甚至這些原則之間也會互相羈絆,做好它們之間的權衡也非常重要。

    1.1 基礎

    當涉及到系統架構問題時,這幾件事情是必須要考慮清楚的:什么樣的模塊比較合適?如何把它們組合在一起?如何進行恰當地權衡?在擴大投資之前,它通常需要的并不是一個精明的商業命題,然而,一些深謀遠慮的設計可以幫你在未來節省大量的時間和資源。

    本文討論的重點幾乎是構建所有大型Web應用程序的核心:服務、冗余、分區和故障處理能力。這里的每個因素都會涉及到選擇和妥協,特別是前面所討論的那些原則。解釋這些核心的最佳辦法就是舉例子。

    1.2 圖片托管應用程序

    有時,你會在線上傳圖片,而一些大型網站需要托管和傳送大量的圖片,這對于構建一個具有成本效益、高可用性并具有低延時(快速檢索)的架構是一項挑戰。

    在一個圖片系統中,用戶可以上傳圖片到一個中央服務器里,通過網絡連接或API對這些圖片進行請求,就像Flickr或者Picasa。簡單點,我們就假設這個應用程序只包含兩個核心部分:上傳(寫)圖片和檢索圖片。圖片上傳時最好能夠做到高效,傳輸速度也是我們最關心的,當有人向圖片發出請求時(例如是一個Web頁面或其他應用程序)。這是非常相似的功能,提供Web服務或內容分發網絡(一個CDN服務器可以在許多地方存儲內容,所以無論是在地理上還是物理上都更加接近用戶,從而導致更快的性能)邊緣服務器。

    該系統需要考慮的其他重要方面:

    • 圖片存儲的數量是沒有限制的,所以存儲應具備可伸縮,另外圖片計算也需要考慮
    • 下載/請求需要做到低延遲
    • 用戶上傳一張圖片,那么圖片就應該始終在那里(圖片數據的可靠性)
    • 系統應該易于維護(易管理)
    • 由于圖片托管不會有太高的利潤空間,所以系統需要具備成本效益
    • </ul>

      簡化的功能圖,如下:

      構建高可擴Web架構和分布式系統實戰

      在這個例子中,系統必須具備快速、數據存儲必須做到可靠和高度可擴展。構建一個小型的應用程序就微不足道了,一臺服務器即可實現托管。如果這樣,這篇文章就毫無興趣和吸引力了。假設我們要做的應用程序會逐漸成長成Flickr那么大。

      1.3 服務

      當我們考慮構建可伸縮的系統時,它應有助于解耦功能,系統的每個部分都可以作為自己的服務并且擁有清晰的接口定義。在實踐中,這種系統設計被稱作面向服務的體系結構(SOA)。對于此類系統,每個服務都有它自己的獨特功能,通過一個抽象接口可以與外面的任何內容進行互動,通常是面向公眾的另一個服務API。

      把系統分解成一組互補性的服務,在互相解耦這些操作塊。這種抽象有助于在服務、基本環境和消費者服務之間建立非常清晰的關系。這種分解可以有效地隔離問題,每個塊也可以互相伸縮。這種面向服務的系統設計與面向對象設計非常相似。

      在我們的例子中,所有上傳和檢索請求都在同一臺服務器上處理。然而,因為系統需要具備可伸縮性,所以把這兩個功能打破并集成到自己的服務中是有意義的。

      快進并假設服務正在大量使用;在這種情況下,很容易看到寫圖片的時間對讀圖片時間會產生多大影響(他們兩個功能在彼此競爭共享資源)。根據各自體系,這種影響會是巨大的。即使上傳和下載速度相同(這是不可能的,對于大多數的IP網絡來說,下載速度:上傳速度至少是3:1),通常,文件可以從緩存中讀取,而寫入,最終是寫到磁盤中(也許在最終一致的情況下,可以被多寫幾次)。即使是從緩存或者磁盤(類似SSD)中讀取,數據寫入都會比讀慢(Pole Position,一個開源DB基準的開源工具和結果)。

      這種設計的另一個潛在問題是像Apache或者Lighttpd這些Web服務器通常都會有一個并發連接數上限(默認是500,但也可以更多),這可能會花費高流量,寫可能會迅速消掉所有。 既然讀可以異步或利用其他性能優化,比如gzip壓縮或分塊傳輸代碼,Web服務可以快速切換讀取和客戶端來服務于更多的請求,超過每秒的最大連接數 (Apache的最大連接數設置為500,這種情況并不常見,每秒可以服務幾千個讀取請求)。另一方面,寫通常傾向于保持一個開放的鏈接進行持續上傳,所 以,使用家庭網絡上傳一個1 MB的文件花費的時間可能會超過1秒,所以,這樣的服務器只能同時滿足500個寫請求。

      構建高可擴Web架構和分布式系統實戰

      規劃這種瓶頸的一個非常好的做法是把讀和寫進行分離,如上圖所示。這樣我們就可以對它們單獨進行擴展(一直以來讀都比寫多)但也有助于弄明白每個點的意思。這種分離更易于排除故障和解決規模方面問題,如慢讀。

      這種方法的優點就是我們能夠彼此獨立解決問題——在同種情況下,無需寫入和檢索操作。這兩種服務仍然利用全球語料庫的圖像,但是他們可以自由地優化性能和服務方法(例如排隊請求或者緩存流行圖片——下面會介紹更多)。從維護和成本角度來看,每一個服務都可以根據需要獨立進行擴展,但如果把它們進行合并或交織在一起,那么有可能無意中就會對另一個性能產生影響,如上面討論的情景。

      當然,如果你有兩個不同的端點,上面的例子可能會運行的很好(事實上,這非常類似于幾個云存儲供應商之間的實現和內容分發網絡)。雖然有很多種方法可以解決這些瓶頸,但每個人都會有不同的權衡,所以采用適合你的方法才是最重要的。

      1.4 冗余

      為了可以正確處理錯誤,一個Web架構的服務和數據必須具備適當的冗余。例如,如果只有一個副本文件存儲在這臺單獨的服務器上,那么如果這臺服務器出現問題或丟失,那么該文件也隨即一起丟失。丟失數據并不是什么好事情,避免數據丟失的常用方法就是多創建幾個文件或副本或冗余。

      同樣也適用于服務器。如果一個應用程序有個核心功能,應確保有多個副本或版本在同時運行,這樣可以避免單節點失敗。

      在系統中創建冗余,當系統發生危機時,如果需要,可以消除單點故障并提供備份或備用功能。例如,這里有兩個相同的服務示例在生產環境中運行,如果其中一個發生故障或者降低,那么該系統容錯轉移至那個健康的副本上。容錯轉移可以自動發生也可以手動干預。

      服務冗余的另一重要組成部分是創建一個無共享架構。在這種體系結構中,每個節點都能相互獨立運行,并且沒有所謂的中央“大腦”管理狀態或協調活動其他節點。這對系統的可擴展幫助很大,因為新節點在沒有特殊要求或知識的前提下被添加。然而,最重要的是,這些系統是沒有單點故障的,所以失敗的彈性就更大。

      例如在我們的圖片服務器應用程序中,所有的圖片在另一個硬件上都有冗余副本(理想情況下是在不同的地理位置,避免在數據中心發生一些火災、地震等自然事故),服務去訪問圖片將被冗余,所有潛在的服務請求。(采用負載均衡是實現這點的最好方法,在下面還會介紹更多方法)

      構建高可擴Web架構和分布式系統實戰

      1.5 分區

      數據集有可能非常大,無法安裝在一臺服務器上。也有可能這樣,某操作需要太多的計算資源、性能降低并且有必要增加容量。在這兩種情況下,你有兩種選擇:縱向擴展或橫向擴展。

      縱向擴展意味著在單個服務器上添加更多的資源。所以,對于一個非常大的數據集來說,這可能意味著添加更多(或更大)的硬件設備,來使一臺服務器能容下整個數據集。在計算操作下,這可能意味著移動計算到一個更大的服務器上,擁有更快的CPU或更大的內存。在各種情況下,縱向擴展可以通過提升單個資源的處理能力來完成。

      橫向擴展在另一方面是添加更多的節點,在大數據集下,這可能會使用第二服務器來存儲部分數據集,對于計算資源來說,這意味著分割操作或跨節點加載。為了充分利用橫向擴展,它應作為一種內在的系統架構設計原則,否則修改或拆分操作將會非常麻煩。

      當談到橫向擴展時,最常見的做法是把服務進行分區或碎片。分區可以被派發,這樣每個邏輯組的功能就是獨立的。可以通過地理界限或其他標準,如非付費與付費用戶來完成分區。這些方案的優點是他們會隨著容量的增加提供一個服務或數據存儲。

      在我們的圖片服務器案例中,用來存儲圖片的單個文件服務器可能被多個文件服務器取代,每個里面都會包含一套自己獨特的圖像。這種架構將允許系統來填充每一個文件/圖片服務器,當磁盤填滿時會添加額外的服務器。這樣的設計需要一個命名方案,用來捆綁圖片文件名到其相應的服務器上。圖像名字可以形成一個一致的哈希方案并映射到整個服務器上;或者給每張圖片分配一個增量ID,當客戶端對圖片發出請求時,圖片檢索服務只需要檢索映射到每個服務器上(例如索引)的ID。

      構建高可擴Web架構和分布式系統實戰

      當然,跨越多個服務器對數據或功能進行分區還是有許多挑戰的。其中的關鍵問題是數據本地化。在分布式系統中,數據操作或計算點越接近,系統性能就會越好。因此,它也可能是個潛在問題,當數據分散在多個服務器上時。有時數據不是在本地,那么就要迫使服務器通過網絡來獲取所需的信息,這個獲取的過程就會設計到成本。

      另一潛在問題是不一致。當這里有多個服務對一個共享資源執行讀寫操作時,潛在可能會有另一個服務器或數據存儲參與進來, 作為競選條件——一些數據需要更新,但是讀的優先級高于更新——在這種情況下,數據就是不一致的。例如在圖片托管方案中,有可能出現的不一致是:如果一個 客戶端發送更新“狗”圖片請求,進行重新命名,把“Dog”改成“Gizmo”,但同時,另一個客戶端正在讀這張圖片。在這種情況下,標題就是不清楚的。 “Dog”或“Gizmo”應該被第二個客戶端接收。【可以通過分布式事務解決】

      當然,在進行數據分區時會產生一些障礙,但是分區允許把每個問題拆分到管理群里——通過數據、負載、使用模式等。這樣對可擴展和易管理都是有幫助的,但也不是沒有風險的。這里有很多方式來降低風險和故障處理;

      來自:http://my.oschina.net/xianggao/blog/529013

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!