傳統的企業應用系統主要面對的技術挑戰是處理複雜凌亂、變幻無窮的所謂業務邏輯,而大型網站主要面對的技術挑戰是處理超大量的用戶訪問和海量的數據處理;前者的挑戰來自功能性需求,後者的挑戰來自非功能性需求;功能性需求也許還有「人月神話」聊以自慰,經過增長人手解決問題,而非功能需求大可能是實實在在的技術難題,不管有多少工程師,作不到就是作不到。前端
「好的設計絕對不是模仿、不是生搬硬套某個模式,而是在對問題深入理解之上的創造與創新,即便是‘微創新’,也是讓人耳目一新的似曾相識。web
京東促銷不能購買的例子:算法
可以正常訪問購物車,卻不能成功購買,問題應該是出在訂單系統,B 2C網站生成一個訂單須要經歷扣減庫存、扣減促銷資源、更新用戶帳戶等一系列操做,這些操做大可能是數據庫事務操做,沒有辦法經過緩存等手段來減輕數據庫服務器負載壓力,若是事前沒有設計好數據庫伸縮性架構,那麼京東的技術團隊將遇到一個大麻煩。數據庫
如何打造一個高可用、高性能、易擴展、可伸縮且安全的網站?如何讓網站隨應用所需靈活變更,即便是山寨他人的產品,也能夠山寨的更高、更快、更強,一年時間用戶數從零過億呢?編程
有如下特色:後端
1.高併發,大流量
2.高可用:系統24小時不間斷服務
3.海量數據
4.用戶分佈普遍,網絡狀況複雜
5.安全環境惡劣
6.需求快速變動,發佈頻繁
7.漸進式發展設計模式
1.初始階段的網站架構瀏覽器
應用程序,數據庫,文件等全部的資源都在一臺服務器上。緩存
2.應用服務和數據服務分離安全
應用和數據分離後整個網站使用三臺服務器:應用服務器,文件服務器和數據庫服務器。以下圖所示:
這三臺服務器對硬件資源的要求各不相同:
1.應用服務器須要處理大量的業務邏輯,所以須要更快更強大的CPU
2.數據庫服務器須要快速磁盤檢索和數據緩存,所以須要更快的硬盤和更大的內存
3.文件服務器須要存儲大量用戶上傳的文件,所以須要更大的磁盤
隨着用戶逐漸增多,網站又一次面臨挑戰:數據庫壓力太大致使訪問延遲,進而影響整個網站的性能,用戶體驗受到影響。
3.訪問緩存改善網站性能
網站訪問特色和現實世界的財富分配同樣遵循二八定律:80%的業務訪問集中在20%的數據上。
網站使用的緩存能夠分爲兩種:緩存在1.應用服務器上的本地緩存和緩存在專門的2.分佈式緩存服務器上的遠程緩存。本地緩存的訪問速度更快一些,可是受應用服務器內存限制,其緩存數據量有限,並且會出現和應用程序爭用內存的狀況。遠程分佈式緩存可使用集羣的方式,部署大內存的服務器做爲專門的緩存服務器,能夠在理論上作到不受內存容量限制的緩存服務,如圖:
使用緩存後,數據訪問壓力獲得有效緩解,可是單一應用服務器可以處理的請求鏈接有限,在網站高峯期,應用服務器成爲整個網站的瓶頸。
4.使用應用服務器集羣改善網站的併發處理能力
使用集羣是網站解決高併發、海量數據問題的經常使用手段。當一臺服務器的處理能力、存儲空間不足時,不要企圖去換更強大的服務器,對大型網站而言,無論多麼強大的服務器,都知足不了網站持續增加的業務需求。這種狀況下,更恰當的作法是增長一臺服務器分擔原有服務器的訪問及存儲壓力。架構如圖:
5.數據庫讀寫分離
目前大部分的主流數據庫都提供主從熱備功能,經過配置兩臺數據庫主從關係,能夠將一臺數據庫服務器的數據更新同步到另外一臺服務器上。網站利用數據庫的這一功能,實現數據庫讀寫分離,從而改善數據庫負載壓力。如圖:
6.使用反向代理和CDN加速網站響應
CDN和反向代理的基本原理都是緩存,區別在於CDN部署在網絡提供商的機房,使用戶在請求網站服務時,能夠從距離本身最近的網絡提供商機房獲取數據;而反向代理則部署在網站的中心機房,當用戶請求到達中心機房後,首先訪問的服務器是反向代理服務器,若是反向代理服務器中緩存着用戶請求的資源,就將其直接返回給用戶。架構如圖:
使用CDN和反向代理的目的是儘早返回數據給用戶,一方面加快用戶訪問速度,另外一方面也減輕了後端服務器的負載壓力。
7.使用分佈式文件系統和分佈式數據庫系統
分佈式數據庫是網站數據庫拆分的最後手段,只有在單表數據規模很是龐大的時候才使用。不到不得已時,網站更經常使用的數據庫拆分手段是業務分庫,將不一樣業務的數據庫部署在不一樣的物理服務器上。
8.使用NoSQL和搜索引擎
9.業務拆分
10.分佈式服務
既然每個應用系統都須要執行許多相同的業務操做,好比用戶管理、商品管理等,那麼能夠將這些共用的業務提取出來,獨立部署。由這些可複用的業務鏈接數據庫,提供共用業務服務,而應用系統只須要管理用戶界面,經過分佈式服務調用共用業務服務完成具體業務操做,如圖:
誤區:
1.一味追隨大公司的解決方案
2.爲了技術而技術
3.企圖用技術解決全部問題
好比說12306網站:
12306真正的問題其實不在於它的技術架構,而在於它的業務架構:12306根本就不該該在幾億中國人一票難求的狀況下以窗口售票的模式在網上售票(零點開始出售若干天后的車票)。12306須要重構的不只是它的技術架構,更重要的是它的業務架構:調整業務需求,換一種方式賣票,而不要去搞促銷秒殺這種噱頭式的遊戲。
後來證實12306確實是朝這個方向發展的:在售票方式上引入了排隊機制、整點售票調整爲分時段售票。其實若是能控制住併發訪問的量,不少棘手的技術問題也就不是什麼問題了。
關於什麼是模式,這個來自建築學的詞彙是這樣定義的:「每個模式描述了一個在咱們周圍不斷重複發生的問題及該問題解決方案的核心。這樣,你就能一次又一次地使用該方案而沒必要作重複工做」。模式的關鍵在於模式的可重複性,問題與場景的可重複性帶來解決方案的可重複使用。
1.分層
分層是企業應用系統中最多見的一種架構模式,將系統在橫向維度上切分紅幾個部分,每一個部分負責一部分相對比較單一的職責,而後經過上層對下層的依賴和調用組成一個完整的系統。
分層結構在計算機世界中無處不在,網絡的7層通訊協議是一種分層結構;計算機硬件、操做系統、應用軟件也能夠看做是一種分層結構。在大型網站架構中也採用分層結構,將網站軟件系統分爲1.應用層、2.服務層、3.數據層,如表:
可是分層架構也有一些挑戰,就是必須合理規劃層次邊界和接口,在開發過程當中,嚴格遵循分層架構的約束,禁止跨層次的調用(應用層直接調用數據層)及逆向調用(數據層調用服務層,或者服務層調用應用層)。
2.分割
對軟件進行縱向切分。
3.分佈式
對於大型網站,分層和分割的一個主要目的是爲了切分後的模塊便於分佈式部署,即將不一樣模塊部署在不一樣的服務器上,經過遠程調用協同工做。分佈式意味着可使用更多的計算機完成一樣的功能,計算機越多,CPU、內存、存儲資源也就越多,可以處理的併發訪問和數據量就越大,進而可以爲更多的用戶提供服務。
在網站應用中,經常使用的分佈式方案有以下幾種:
1.分佈式應用和服務
將分層和分割後的應用和服務模塊分佈式部署,除了能夠改善網站性能和併發性、加快開發和發佈速度、減小數據庫鏈接資源消耗外;還可使不一樣應用複用共同的服務,便於業務功能擴展。
2.分佈式靜態資源
網站的靜態資源如JS, CSS, Logo圖片等資源獨立分佈式部署,並採用獨立的域名,即人們常說的動靜分離。靜態資源分佈式部署能夠減輕應用服務器的負載壓力;經過使用獨立域名加快瀏覽器併發加載的速度;由負責用戶體驗的團隊進行開發維護有利於網站分工合做,使不一樣技術工種術業有專攻。
3.分佈式數據和存儲
大型網站須要處理以P爲單位的海量數據,單臺計算機沒法提供如此大的存儲空間,這些數據須要分佈式存儲。除了對傳統的關係數據庫進行分佈式部署外,爲網站應用而生的各類NoSQL產品幾乎都是分佈式的。
4.分佈式計算
目前網站廣泛使用Hadoop及其M apR educe分佈式計算框架進行此類批處理計算,其特色是移動計算而不是移動數據,將計算程序分發到數據所在的位置以加速計算和分佈式計算。
4.集羣
5.緩存
緩存就是將數據存放在距離計算最近的位置以加快處理速度。緩存是改善軟件性能的第一手段,現代CPU愈來愈快的一個重要因素就是使用了更多的緩存,在複雜的軟件設計中,緩存幾乎無處不在。大型網站架構設計在不少方面都使用了緩存設計。
使用緩存的例子:CDN,反向代理,本地緩存,分佈式緩存。
使用緩存有兩個前提條件:
1.數據訪問熱點不均衡。
2.數據在某個時間段內有效,不會很快過時,不然緩存的數據就會因已經失效而產生髒讀,影響告終果的正確性。
6.異步
7.冗餘
8.自動化
9.安全
新浪微博的架構在較短的時間內幾經重構,最終造成了如今的架構:
系統分爲三個層次,最下層是基礎服務層,提供數據庫,緩存,存儲,搜索等數據服務,以及其餘一些基礎技術服務,這些服務支撐了整個新浪微博的海量數據和高併發訪問,是整個系統的技術基礎。
中間層是平臺服務和應用服務層,新浪微博的核心服務是微博、關係和用戶,它們是新浪微博業務大廈的支柱。這些服務被分割爲獨立的服務模塊,經過依賴調用和共享基礎數據構成新浪微博的業務基礎。
最上層是API和新浪微博的業務層,各類客戶端(包括Web網站)和第三方應用,經過調用API集成到新浪微博的系統中,共同組成一個生態系統。
在新浪微博的早期架構中,微博發佈使用同步推模式,用戶發表微博後系統會當即將這條微博插入到數據庫全部粉絲的訂閱列表中,當用戶量比較大時,特別是明星用戶發佈微博時,會引發大量的數據庫寫操做,超出數據庫負載,系統性能急劇降低,用戶響應延遲加重。後來新浪微博改用異步推拉結合的模式,用戶發表微博後系統將微博寫入消息隊列後當即返回,用戶響應迅速,消息隊列消費者任務將微博推送給全部當前在線粉絲的訂閱列表中,非在線用戶登陸後再根據關注列表拉取微博訂閱列表。
關於什麼是架構,一種比較通俗的說法是「最高層次的規劃,難以改變的決定」,這些規劃和決定奠基了事物將來發展的方向和最終的藍圖。
性能是網站的一個重要指標,除非是沒得選擇(好比只能到www.12306.cn這一個網站上買火車票),不然用戶沒法忍受一個響應緩慢的網站。一個打開緩慢的網站會致使嚴重的用戶流失,不少時候網站性能問題是網站架構升級優化的觸發器。能夠說性能是網站架構設計的一個重要方面,任何軟件架構設計方案都必須考慮可能會帶來的性能問題。
也正是由於性能問題幾乎無處不在,因此優化網站性能的手段也很是多,從用戶瀏覽器到數據庫,影響用戶請求的全部環節均可以進行性能優化。
在瀏覽器端,能夠經過瀏覽器緩存、使用頁面壓縮、合理佈局頁面、減小Cookie傳輸等手段改善性能。
還可使用CDN,將網站靜態內容分發至離用戶最近的網絡服務商機房,使用戶經過最短訪問路徑獲取數據。能夠在網站機房部署反向代理服務器,緩存熱點文件,加快請求響應速度,減輕應用服務器負載壓力。
在應用服務器端,可使用服務器本地緩存和分佈式緩存,經過緩存在內存中的熱點數據處理用戶請求,加快請求處理過程,減輕數據庫負載壓力。
也能夠經過異步操做將用戶請求發送至消息隊列等待後續任務處理,而當前請求直接返回響應給用戶。
在網站有不少用戶高併發請求的狀況下,能夠將多臺應用服務器組成一個集羣共同對外服務,提升總體處理能力,改善性能。
在代碼層面,也能夠經過使用多線程、改善內存管理等手段優化性能。
在數據庫服務器端,索引、緩存、SQL優化等性能優化手段都已經比較成熟。而方興未艾的NoSQL數據庫經過優化數據模型、存儲結構、伸縮特性等手段在性能方面的優點也日趨明顯。
衡量網站性能有一系列指標,重要的有響應時間、TPS、系統性能計數器等,經過測試這些指標以肯定系統設計是否達到目標。這些指標也是網站監控的重要參數,經過監控這些指標能夠分析系統瓶頸,預測網站容量,並對異常指標進行報警,保障系統可用性。
網站高可用的主要手段是冗餘,應用部署在多臺服務器上同時提供訪問,數據存儲在多臺服務器上互相備份,任何一臺服務器宕機都不會影響應用的總體可用,也不會致使數據丟失。
對於應用服務器而言,多臺應用服務器經過負載均衡設備組成一個集羣共同對外提供服務,任何一臺服務器宕機,只需把請求切換到其餘服務器就可實現應用的高可用,可是一個前提條件是應用服務器上不能保存請求的會話信息。不然服務器宕機,會話丟失,即便將用戶請求轉發到其餘服務器上也沒法完成業務處理。
衡量架構伸縮性的主要標準就是是否能夠用多臺服務器構建集羣,是否容易向集羣中添加新的服務器。加入新的服務器後是否能夠提供和原來的服務器無差異的服務。集羣中可容納的總的服務器數量是否有限制。
不一樣於其餘架構要素主要關注非功能性需求,網站的擴展性架構直接關注網站的功能需求。網站快速發展,功能不斷擴展,如何設計網站的架構使其可以快速響應需求變化,是網站可擴展架構主要的目的。
網站可伸縮架構的主要手段是事件驅動架構和分佈式服務。
事件驅動架構在網站一般利用消息隊列實現,將用戶請求和其餘業務事件構形成消息發佈到消息隊列,消息的處理者做爲消費者從消息隊列中獲取消息進行處理。經過這種方式將消息產生和消息處理分離開來,能夠透明地增長新的消息生產者任務或者新的消息消費者任務。
分佈式服務則是將業務和可複用服務分離開來,經過分佈式服務框架調用。新增產品能夠經過調用可複用的服務實現自身的業務邏輯,而對現有產品沒有任何影響。可複用服務升級變動的時候,也能夠經過提供多版本服務對應用實現透明升級,不須要強制應用同步變動。
性能,可用性,伸縮性,擴展性和安全性是網站架構最核心的幾個要素。
網站性能是客觀的指標,能夠具體體現到響應時間、吞吐量等技術指標,同時也是主觀的感覺,而感覺則是一種與具體參與者相關的微妙的東西,用戶的感覺和工程師的感覺不一樣,不一樣的用戶感覺也不一樣。
2.性能測試指標
主要指標有響應時間,併發數,吞吐量,性能計數器等:
1.響應時間
指應用執行一個操做須要的時間,包括從發出請求開始收到最後響應數據所須要的時間。響應時間是系統最重要的性能指標,直觀地反映了系統的「快慢」。
2.併發數
指系統可以同時處理請求的數目,這個數字也反映了系統的負載特性。
注意釐清數量關係:
網站系統用戶數>>網站在線用戶數>>網站併發用戶數
3.吞吐量
指單位時間內系統處理的請求數量,體現了系統的總體處理能力。TPS(每秒事務數)是吞吐量的一個經常使用量化指標,此外還有HPS(每秒HTTP請求數)、QPS(每秒查詢數)等。
系統吞吐量和系統併發數,以及響應時間的關係能夠形象地理解爲高速公路的通行情況:
吞吐量是天天經過收費站的車輛數目(能夠換算成收費站收取的高速費),併發數是高速公路上的正在行駛的車輛數目,響應時間是車速。
車輛不多時,車速很快,可是收到的高速費也相應較少;隨着高速公路上車輛數目的增多,車速略受影響,可是收到的高速費增長很快;隨着車輛的繼續增長,車速變得愈來愈慢,高速公路愈來愈堵,收費不增反降;若是車流量繼續增長,超過某個極限後,任何偶然因素都會致使高速所有癱瘓,車走不動,費固然也收不着,而高速公路成了停車場(資源耗盡)。
4.性能計數器
System Load即系統負載,指當前正在被CPU執行和等待被CPU執行的進程數目總和,是反映系統忙閒程度的重要指標。多核CPU的狀況下,完美狀況是全部CPU都在使用,沒有進程在等待處理,因此Load的理想值是CPU的數目。當Load值低於CPU數目的時候,表示CPU有空閒,資源存在浪費;當Load值高於CPU數目的時候,表示進程在排隊等待CPU調度,表示系統資源不足,影響應用程序的執行性能。在Linux系統中使用top命令查看,該值是三個浮點數,表示最近1分鐘,10分鐘,15分鐘的運行隊列平均進程數。
3.性能測試方法
性能測試是一個總稱,具體能夠細分爲性能測試,負載測試,壓力測試,穩定性測試。
4.性能優化方法
定位產生性能問題的具體緣由後,就須要進行性能優化,根據網站分層架構,可分爲1.Web前端性能優化、2.應用服務器性能優化、**3.存儲服務器性能優化**3大類。
1.瀏覽器訪問優化
1.減小http請求
HTTP協議是無狀態的應用層協議,意味着每次HTTP請求都須要創建通訊鏈路、進行數據傳輸,而在服務器端,每一個HTTP都須要啓動獨立的線程去處理。這些通訊和服務的開銷都很昂貴,減小HTTP請求的數目可有效提升訪問性能。
減小HTTP的主要手段是合併CSS、合併JavaScript、合併圖片。將瀏覽器一次訪問須要的JavaScript、CSS合併成一個文件,這樣瀏覽器就只須要一次請求。圖片也能夠合併,多張圖片合併成一張,若是每張圖片都有不一樣的超連接,可經過CSS偏移響應鼠標點擊操做,構造不一樣的URL。
2.使用瀏覽器緩存
對於一個網站而言,CSS,JS,logo,圖標這些靜態資源文件更新的頻率都比較低,而這些文件又幾乎是每次HTTP請求都須要的,若是將這些文件緩存在瀏覽器中,能夠極好地改善性能。經過設置HTTP頭中的Cache-Control和Expires的屬性,可設定瀏覽器緩存,緩存時間能夠是數天,甚至是幾個月。
3.啓用壓縮
4.CSS放在頁面最上面,JS放在頁面最下面
5.減小Cookie傳輸
一方面,Cookie包含在每次請求和響應中,太大的C ookie會嚴重影響數據傳輸,所以哪些數據須要寫入C ookie須要慎重考慮,儘可能減小C ookie中傳輸的數據量。另外一方面,對於某些靜態資源的訪問,如CSS、Script等,發送C ookie沒有意義,能夠考慮靜態資源使用獨立域名訪問,避免請求靜態資源時發送C ookie,減小C ookie傳輸的次數。
2.CDN加速
CDN可以緩存的通常是靜態資源,如圖片、文件、CSS、Script腳本、靜態網頁等,可是這些文件訪問頻度很高,將其緩存在CDN可極大改善網頁的打開速度。
3.反向代理
應用服務器就是處理網站業務的服務器,網站的業務代碼都部署在這裏,是網站開發最複雜,變化最多的地方,優化手段主要是緩存,集羣,異步等。
1.分佈式緩存
緩存的基本原理:
緩存指將數據存儲在相對較高訪問速度的存儲介質中,以供系統處理。一方面緩存訪問速度快,能夠減小數據訪問的時間,另外一方面若是緩存的數據是通過計算處理獲得的,那麼被緩存的數據無需重複計算便可直接使用,所以緩存還起到減小計算時間的做用。
不合理使用緩存的例子:
1.頻繁修改的數據
通常來講,數據的讀寫比在2:1以上,即寫入一次緩存,在數據更新前至少讀取兩次,緩存纔有意義。在實踐中,這個比例一般很是高,例如新浪熱門微博,緩存之後可能會被讀取數百萬次。
2.沒有熱點的訪問
3.數據不一致與髒讀
通常會對緩存的數據設置失效時間,一旦超過失效時間,就要從數據庫中從新加載。所以應用要容忍必定時間的數據不一致,如賣家已經編輯了商品屬性,可是須要過一段時間才能被買家看到。在互聯網應用中,這種延遲一般是能夠接受的,可是具體應用仍需慎重對待。還有一種策略是數據更新時當即更新緩存,不過這也會帶來更多系統開銷和事務一致性的問題。
4.緩存可用性
經過分佈式緩存服務器集羣,將緩存數據分佈到集羣多臺服務器上可在必定程度上改善緩存的可用性。當一臺緩存服務器宕機的時候,只有部分緩存數據丟失,從新從數據庫加載這部分數據不會對數據庫產生很大影響。
5.緩存預熱
緩存中存放的是熱點數據,熱點數據又是緩存系統利用LRU(最近最久未用算法)對不斷訪問的數據篩選淘汰出來的,這個過程須要花費較長的時間。新啓動的緩存系統若是沒有任何數據,在重建緩存數據的過程當中,系統的性能和數據庫負載都不太好,那麼最好在緩存系統啓動時就把熱點數據加載好,這個緩存預加載手段叫做緩存預熱(warm up)。對於一些元數據如城市地名列表、類目信息,能夠在啓動時加載數據庫中所有數據到緩存進行預熱。
6.緩存穿透
若是由於不恰當的業務、或者惡意攻擊持續高併發地請求某個不存在的數據,因爲緩存沒有保存該數據,全部的請求都會落到數據庫上,會對數據庫形成很大壓力,甚至崩潰。一個簡單的對策是將不存在的數據也緩存起來(其value值爲null)。
分佈式緩存架構
分佈式緩存指緩存部署在多個服務器組成的集羣中,以集羣方式提供緩存服務,其架構方式有兩種,一種是以JBoss C ache爲表明的須要更新同步的分佈式緩存,一種是以Memcached爲表明的不互相通訊的分佈式緩存。
Memcached
2.異步操做
須要注意的是,因爲數據寫入消息隊列後當即返回給用戶,數據在後續的業務校驗、寫數據庫等操做可能失敗,所以在使用消息隊列進行業務異步處理後,須要適當修改業務流程進行配合,如訂單提交後,訂單數據寫入消息隊列,不能當即返回用戶訂單提交成功,須要在消息隊列的訂單消費者進程真正處理完該訂單,甚至商品出庫後,再經過電子郵件或SM S消息通知用戶訂單成功,以避免交易糾紛。
任何能夠晚點作的事情都應該晚點再作。保證數據的正確性
3.使用集羣
4.代碼優化
1.多線程
從資源利用的角度看,使用多線程的緣由主要有兩個:IO阻塞與多CPU。
網站的應用程序通常都被Web服務器容器管理,用戶請求的多線程也一般被Web服務器容器管理,但無論是Web容器管理的線程,仍是應用程序本身建立的線程,一臺服務器上啓動多少線程合適呢?
假設服務器上執行的都是相同類型任務,針對該類任務啓動的線程數有個簡化的估算公式可供參考:
啓動線程數=[任務執行時間/(任務執行時間×IO等待時間)]×CPU內核數
最佳啓動線程數和CPU內核數量成正比,和IO阻塞時間成反比。若是任務都是CPU計算型任務,那麼線程數最多不超過CPU內核數,由於啓動再多線程,CPU也來不及調度;相反若是是任務須要等待磁盤操做,網絡響應,那麼多啓動線程有助於提升任務併發度,提升系統吞吐能力,改善系統性能。(看是CPU計算型仍是磁盤操做!)
多線程須要注意線程安全的問題,這也是缺少經驗的網站工程師最容易犯錯的地方,而線程安全B ug又難以測試和重現,網站故障中,許多所謂偶然發生的「靈異事件」都和多線程併發問題有關。對網站而言,無論有沒有進行多線程編程,工程師寫的每一行代碼都會被多線程執行,由於用戶請求是併發提交的,也就是說,全部的資源——對象、內存、文件、數據庫,乃至另外一個線程均可能被多線程併發訪問。
2.資源複用
系統運行時,要儘可能減小那些開銷很大的系統資源的建立和銷燬,好比數據庫鏈接、網絡通訊鏈接、線程、複雜對象等。從編程角度,資源複用主要有兩種模式:單例(Singleton)和對象池(Object Pool)。
單例雖然是GoF經典設計模式中較多被詬病的一個模式,但因爲目前Web開發中主要使用貧血模式,從Service到D ao都是些無狀態對象,無需重複建立,使用單例模式也就天然而然了。事實上,Java開發經常使用的對象容器Spring默認構造的對象都是單例(須要注意的是Spring的單例是Spring容器管理的單例,而不是用單例模式構造的單例)。
前面說過,對於每一個Web請求(HTTP Request), Web應用服務器都須要建立一個獨立的線程去處理,這方面,應用服務器也採用線程池(Thread Pool)的方式。這些所謂的鏈接池、線程池,本質上都是對象池,即鏈接、線程都是對象,池管理方式也基本相同。
1.機械硬盤VS固態硬盤
機械硬盤是目前最經常使用的一種硬盤,經過馬達驅動磁頭臂,帶動磁頭到指定的磁盤位置訪問數據,因爲每次訪問數據都須要移動磁頭臂,所以機械硬盤在數據連續訪問(要訪問的數據存儲在連續的磁盤空間上)和隨機訪問(要訪問的數據存儲在不連續的磁盤空間)時,因爲移動磁頭臂的次數相差巨大,性能表現差異也很是大。
2.B+樹.VS.LSM樹
本書前面提到,因爲傳統的機械磁盤具備快速順序讀寫、慢速隨機讀寫的訪問特性,這個特性對磁盤存儲結構和算法的選擇影響甚大。
一般會對數據排序後存儲,加快數據檢索速度,這就須要保證數據在不斷更新、插入、刪除後依然有序,傳統關係數據庫的作法是使用B+樹。
目前許多NoSQL產品採用LSM樹做爲主要數據結構。
3.RAID.VS.HDFS
RAID技術能夠經過硬件實現,好比專用的RAID卡或者主板直接支持,也能夠經過軟件實現。RAID技術在傳統關係數據庫及文件系統中應用比較普遍,可是在大型網站比較喜歡使用的NoSQL,以及分佈式文件系統中,RAID技術卻遭到冷落。
如今通常用HDFS,HDFS配合M apR educe等並行計算框架進行大數據處理時,能夠在整個集羣上併發讀寫訪問全部的磁盤,無需RAID支持。
網站的頁面能完整呈如今最終用戶面前,須要通過不少個環節,任何一個環節出了問題,均可能致使網站頁面不可訪問。DNS會被劫持、CDN服務可能會掛掉、網站服務器可能會宕機、網絡交換機可能會失效、硬盤會損壞、網卡會鬆掉、甚至機房會停電、空調會失靈、程序會有B ug、黑客會攻擊、促銷會引來大量訪問、第三方合做夥伴的服務會不可用……要保證一個網站永遠徹底可用幾乎是一件不可能完成的使命。
一個典型的網站設計一般遵循如圖所示的基本分層架構模型。
典型的分層模型是三層,即應用層、服務層、數據層;各層之間具備相對獨立性,應用層主要負責具體業務邏輯處理;服務層負責提供可複用的服務;數據層負責數據的存儲與訪問。中小型網站在具體部署時,一般將應用層和服務層部署在一塊兒,而數據層則另外部署,如圖5.3所示(事實上,這也是網站架構演化的第一步)。
在複雜的大型網站架構中,劃分的粒度會更小,更詳細,結構更加複雜,但一般仍是能夠將服務器劃分到這三層中。
應用層:
位於應用層的服務器一般爲了應對高併發的訪問請求,會經過負載均衡設備將一組服務器組成一個集羣共同對外提供服務,當負載均衡設備經過心跳檢測等手段監控到某臺應用服務器不可用時,就將其從集羣列表中剔除,並將請求分發到集羣中其餘可用的服務器上,使整個集羣保持可用,從而實現應用高可用。
服務層:
位於服務層的服務器狀況和應用層的服務器相似,也是經過集羣方式實現高可用,只是這些服務器被應用層經過分佈式服務調用框架訪問,分佈式服務調用框架會在應用層客戶端程序中實現軟件負載均衡,並經過服務註冊中心對提供服務的服務器進行心跳檢測,發現有服務不可用,當即通知客戶端程序修改服務訪問列表,剔除不可用的服務器。
數據層:
位於數據層的服務器狀況比較特殊,數據服務器上存儲着數據,爲了保證服務器宕機時數據不丟失,數據訪問服務不中斷,須要在數據寫入時進行數據同步複製,將數據寫入多臺服務器上,實現數據冗餘備份。當數據服務器宕機時,應用程序將訪問切換到有備份數據的服務器上。
應用層主要處理網站應用的業務邏輯,所以有時也稱做業務邏輯層,應用的一個顯著特色是應用的無狀態性。
所謂無狀態的應用是指應用服務器不保存業務的上下文信息,而僅根據每次請求提交的數據進行相應的業務邏輯處理,多個服務實例(服務器)之間徹底對等,請求提交到任意服務器,處理結果都是徹底同樣的。
1.經過負載均衡進行無狀態服務的失效轉移
2.應用服務器集羣的Session管理
應用服務器的高可用架構設計主要基於服務無狀態這一特性,可是事實上,業務老是有狀態的,在交易類的電子商務網站,須要有購物車記錄用戶的購買信息,用戶每次購買請求都是向購物車中增長商品;在社交類的網站中,須要記錄用戶的當前登陸狀態、最新發布的消息及好友狀態等,用戶每次刷新頁面都須要更新這些信息。
Web應用中將這些屢次請求修改使用的上下文對象稱做會話(Session),單機狀況下,Session可由部署在服務器上的Web容器(如JBoss)管理。在使用負載均衡的集羣環境中,因爲負載均衡服務器可能會將請求分發到集羣任何一臺應用服務器上,因此保證每次請求依然可以得到正確的Session比單機時要複雜不少。
集羣環境下,Session管理主要有如下幾種手段。
1.Session複製
原理很簡單,在集羣中的幾臺服務器之間同步Session對象,使得每臺服務器上都保存有用戶的Session信息,這樣任何一臺服務器宕機,均可以在其餘服務器上找到Session。
缺點是,大量用戶訪問的狀況下,會出現服務器內存不夠Session使用的狀況。
而大型網站的核心應用集羣就是數千臺服務器,同時在線用戶可達千萬,所以並不適用這種方案。
2.Session綁定
Session綁定能夠利用負載均衡的源地址Hash算法實現,負載均衡服務器老是未來自同一IP的請求分發到同一臺服務器上,這種方法又被稱做爲會話粘滯。
但Session綁定的方案不符合咱們的要求,若是一臺服務器宕機,那麼該服務器上的Session將不存在,用戶請求切換後沒法完成業務。
所以雖然大部分負載均衡服務器都提供源地址負載均衡算法,但不多有網站利用這個算法進行Session管理。
3.利用Cookie記錄Session
利用Cookie記錄Session也有缺點,好比受Cookie大小限制,能記錄的信息有限,每次請求響應都須要傳輸Cookie,影響性能;若是用戶關閉C ookie,訪問就會不正常。可是因爲C ookie的簡單易用,可用性高,支持應用服務器的線性伸縮,而大部分應用須要記錄的Session信息又比較小。所以事實上,許多網站都或多或少地使用C ookie記錄Session。
4.Session服務器
那麼有沒有可用性高、伸縮性好、性能也不錯,對信息大小又沒有限制的服務器集羣Session管理方案呢?
答案就是Session服務器。利用獨立部署的Session服務器(集羣)統一管理S ession,應用服務器每次讀寫Session時,都訪問Session服務器,如圖所示。
這種解決方案事實上是將應用服務器的狀態分離,分爲無狀態的應用服務器和有狀態的Session服務器,而後針對這兩種服務器的不一樣特性分別設計其架構。
對於有狀態的Session服務器,一種比較簡單的方法是利用分佈式緩存、數據庫等,在這些產品的基礎上進行包裝,使其符合Session的存儲和訪問要求。若是業務場景對Session管理有比較高的要求,好比利用Session服務集成單點登陸(SSO)、用戶服務等功能,則須要開發專門的Session服務管理平臺。
保證數據存儲高可用的手段主要是1.數據備份和2.失效轉移機制。數據備份是保證數據有多個副本,任意副本的失效都不會致使數據的永久丟失,從而實現數據徹底的持久化。而失效轉移機制則保證當一個數據副本不可訪問時,能夠快速切換訪問數據的其餘副本,保證系統可用。
關於緩存服務的高可用,在實踐中爭議很大,一種觀點認爲緩存已經成爲網站數據服務的重要組成部分,事實上承擔了業務中絕大多數的數據讀取訪問服務,緩存服務失效可能會致使數據庫負載太高而宕機,進而影響整個網站的可用性,所以緩存服務須要實現和數據存儲服務一樣的高可用。
另外一種觀點認爲,緩存服務不是數據存儲服務,緩存服務器宕機引發緩存數據丟失致使服務器負載壓力太高應該經過其餘手段解決,而不是提升緩存服務自己的高可用。
筆者持後一種觀點,對於緩存服務器集羣中的單機宕機,若是緩存服務器集羣規模較大,那麼單機宕機引發的緩存數據丟失比例和數據庫負載壓力變化都較小,對整個系統影響也較小。擴大緩存服務器集羣規模的一個簡單手段就是整個網站共享同一個分佈式緩存集羣,單獨的應用和產品不須要部署本身的緩存服務器,只須要向共享緩存集羣申請緩存資源便可。而且經過邏輯或物理分區的方式將每一個應用的緩存部署在多臺服務器上,任何一臺服務器宕機引發的緩存失效都隻影響應用緩存數據的一小部分,不會對應用性能和數據庫負載形成太大影響。
C AP原理:
在討論高可用數據服務架構以前,必須先討論的一個話題是,爲了保證數據的高可用,網站一般會犧牲另外一個也很重要的指標:數據一致性。也就是說,數據的高可用性跟數據的一致性不可兼得。
高可用的數據有以下幾個層面的含義。
1.數據持久性
2.數據的可訪問性
3.數據一致性
CAP原理認爲,一個提供數據服務的存儲系統沒法同時知足數據一致性(C onsistency)、數據可用性(A vailib ility)、分區耐受性(Patition Tolerance,系統具備跨網絡分區的伸縮性)這三個條件,如圖。
在大型網站中,一般會選擇強化分佈式存儲系統的可用性(A)和伸縮性(P),而在某種程度上放棄一致性(C)。
數據一致性能夠分爲以下幾點:
1.數據強一致
各個副本的數據在物理存儲中老是一致的,數據更新操做結果和操做響應老是一致的,即操做響應通知更新失敗,那麼數據必定沒有被更新,而不是處於不肯定狀態。
2.數據用戶一致
數據在物理存儲中的各個副本的數據多是不一致的,可是終端用戶訪問時,經過糾錯和校驗機制,能夠肯定一個一致的且正確的數據返回給用戶。
3.數據最終一致
這是數據一致性中較弱的一種,即物理存儲的數據多是不一致的,終端用戶訪問到的數據可能也是不一致的(同一用戶連續訪問,結果不一樣;或者不一樣用戶同時訪問,結果不一樣),但系統通過一段時間(一般是一個比較短的時間段)的自我恢復和修正,數據最終會達到一致。
關係數據庫熱備機制就是一般所說的M aster-S lave同步機制。M aster-S lave機制不但解決了數據備份問題,還改善了數據庫系統的性能,實踐中,一般使用讀寫分離的方法訪問S lave和M aster數據庫,寫操做只訪問M aster數據庫,讀操做只訪問S lave數據庫。
關於數據的失效轉移:
失效轉移操做主要由三部分組成:1.失效確認,2.失效轉移,3.數據恢復
1.失效確認
判斷服務器宕機是系統進行失效轉移的第一步,系統確認一臺服務器是否宕機的手段有兩種:1.心跳檢測和2.應用程序訪問失敗報告,如圖。
2.訪問轉移
3.數據恢復
網站發佈的流程:
網站發佈畢竟是一次提早預知的服務器宕機,因此過程能夠更柔和,對用戶影響更小。一般使用發佈腳原本完成發佈,其流程如圖。
目前大部分網站都採用Web自動化測試技術,使用自動測試工具或腳本完成測試。比較流行的Web自動化測試工具是ThoughtW orks開發的Selenium。Selenium運行在瀏覽器中,模擬用戶操做進行測試,所以Selenium能夠同時完成Web功能測試和瀏覽器兼容測試。
在網站發佈時,並非把測試經過的代碼包直接發佈到線上服務器,而是先發布到預發佈機器上,開發工程師和測試工程師在預發佈服務器上進行預發佈驗證,執行一些典型的業務流程,確認系統沒有問題後才正式發佈。
所謂網站的伸縮性是指不須要改變網站的軟硬件設計,僅僅經過改變部署服務器數量就能夠擴大或者縮小網站的服務處理能力。
回顧網站架構發展歷程, 網站架構發展史就是一部不斷向網站添加服務器的歷史。只要工程師能向網站的服務器集羣中添加新的機器,只要新添加的服務器能線性提升網站的總體服務處理能力,網站就無需爲不斷增加的用戶和訪問而焦慮。
實現負載均衡的主要算法:
1.HTTP重定向負載均衡
這種負載均衡方案的優勢是比較簡單。缺點是瀏覽器須要兩次請求服務器才能完成一次訪問,性能較差;重定向服務器自身的處理能力有可能成爲瓶頸,整個集羣的伸縮性規模有限;使用HTTP302響應碼重定向,有可能使搜索引擎判斷爲SEO做弊,下降搜索排名。所以實踐中使用這種方案進行負載均衡的案例並很少見。
2.DNS域名解析負載均衡
在DNS服務器中配置多個A記錄,如:www.m ysite.com IN A 114.100.80.一、www.m ysite.com IN A 114.100.80.二、www.m ysite.com IN A 114.100.80.3。
每次域名解析請求都會根據負載均衡算法計算一個不一樣的IP地址返回,這樣A記錄中配置的多個服務器就構成一個集羣,並能夠實現負載均衡。
DNS域名解析負載均衡的優勢是將負載均衡的工做轉交給DNS,省掉了網站管理維護負載均衡服務器的麻煩,同時許多DNS還支持基於地理位置的域名解析,即會將域名解析成距離用戶地理最近的一個服務器地址,這樣可加快用戶訪問速度,改善性能。可是DNS域名解析負載均衡也有缺點,就是1.目前的DNS是多級解析,每一級DNS均可能緩存A記錄,當下線某臺服務器後,即便修改了DNS的A記錄,要使其生效也須要較長時間,這段時間,DNS依然會將域名解析到已經下線的服務器,致使用戶訪問失敗;並且2.DNS負載均衡的控制權在域名服務商那裏,網站沒法對其作更多改善和更強大的管理。
事實上,大型網站老是部分使用DNS域名解析,利用域名解析做爲第一級負載均衡手段,即域名解析獲得的一組服務器並非實際提供Web服務的物理服務器,而是一樣提供負載均衡服務的內部服務器,這組內部負載均衡服務器再進行負載均衡,將請求分發到真實的Web服務器上。
大型網站利用DNS域名解析做爲第一級的負載均衡手段。
3.反向代理負載均衡
前面咱們提到利用反向代理緩存資源,以改善網站性能。實際上,在部署位置上,反向代理服務器處於Web服務器前面(這樣纔可能緩存Web響應,加速訪問),這個位置也正好是負載均衡服務器的位置,因此大多數反向代理服務器同時提供負載均衡的功能,管理一組Web服務器,將請求根據負載均衡算法轉發到不一樣Web服務器上。Web服務器處理完成的響應也須要經過反向代理服務器返回給用戶。因爲Web服務器不直接對外提供訪問,所以Web服務器不須要使用外部IP地址,而反向代理服務器則須要配置雙網卡和內部外部兩套IP地址。
因爲反向代理服務器轉發請求在HTTP協議層面,所以也叫應用層負載均衡。其優勢是和反向代理服務器功能集成在一塊兒,部署簡單。缺點是反向代理服務器是全部請求和響應的中轉站,其性能可能會成爲瓶頸。
4.IP負載均衡
在網絡層經過修改目標地址進行負載均衡。
5.數據鏈路層負載均衡
顧名思義,數據鏈路層負載均衡是指在通訊協議的數據鏈路層修改mac地址進行負載均衡。
這種數據傳輸方式又稱做三角傳輸模式,負載均衡數據分發過程當中不修改IP地址,只修改目的m ac地址,經過配置真實物理服務器集羣全部機器虛擬IP和負載均衡服務器IP地址一致,從而達到不修改數據包的源地址和目的地址就能夠進行數據分發的目的,因爲實際處理請求的真實物理服務器IP和數據請求目的IP一致,不須要經過負載均衡服務器進行地址轉換,可將響應數據包直接返回給用戶瀏覽器,避免負載均衡服務器網卡帶寬成爲瓶頸。這種負載均衡方式又稱做直接路由方式(DR)。
使用三角傳輸模式的鏈路層負載均衡是目前大型網站使用最廣的一種負載均衡手段。在Linux平臺上最好的鏈路層負載均衡開源產品是LVS(Linux V irtual Server)。
6.負載均衡算法
負載均衡服務器的實現分紅兩個部分:
1.根據負載均衡算法和Web服務器列表計算獲得集羣中一臺Web服務器的地址。
2.將請求數據發送到該地址對應的Web服務器上。
前面描述瞭如何將請求數據發送到Web服務器上,而具體的負載均衡算法一般有以下幾種:
1.輪詢(RR)
2.加權輪詢(WRR)
3.隨機(Random)
4.最少鏈接(Least Connections)
記錄每一個應用服務器正在處理的鏈接數(請求數),將新到的請求分發到最少鏈接的服務器上,應該說,這是最符合負載均衡定義的算法。一樣,最小鏈接算法也能夠實現加權最少鏈接。
5.源地址散列(Source Hashing)
咱們在本書第4章討論過度布式緩存,不一樣於應用服務器集羣的伸縮性設計,分佈式緩存集羣的伸縮性不能使用簡單的負載均衡手段來實現。
必須讓新上線的緩存服務器對整個分佈式緩存集羣影響最小,也就是說新加入緩存服務器後應使整個緩存服務器集羣中已經緩存的數據儘量還被訪問到,這是分佈式緩存集羣伸縮性設計的最主要目標。
1.Memcached分佈式緩存集羣的訪問模型
若是使用樸素的Hash路由算法,將會出現問題。原本加入新的緩存服務器是爲了下降數據庫的負載壓力,可是操做不當卻致使了數據庫的崩潰。若是不對問題和解決方案有透徹瞭解,網站技術總有想不到的陷阱讓架構師一腳踩空。遇到這種狀況,用某網站一位資深架構師的話說,就是「一股寒氣從腳底板竄到了腦門心」。
能不能經過改進路由算法,使得新加入的服務器不影響大部分緩存數據的正確命中呢?目前比較流行的算法是一致性Hash算法。
一致性Hash算法也有小問題。
計算機領域有句話:計算機的任何問題均可以經過增長一個虛擬層來解決。計算機硬件、計算機網絡、計算機軟件都莫不如此。計算機網絡的7層協議,每一層均可以看做是下一層的虛擬層;計算機操做系統能夠看做是計算機硬件的虛擬層;Java虛擬機能夠看做是操做系統的虛擬層;分層的計算機軟件架構事實上也是利用虛擬層的概念。
解決上述一致性Hash算法帶來的負載不均衡問題,也能夠經過使用虛擬層的手段:將每臺物理緩存服務器虛擬爲一組虛擬緩存服務器,將虛擬服務器的Hash值放置在Hash環上,KEY在環上先找到虛擬服務器節點,再獲得物理服務器的信息。
1.關係性數據庫集羣的伸縮性設計
目前網站在線業務應用中比較成熟的支持數據分片的分佈式關係數據庫產品主要有Cobar。其架構圖以下。
Cobar系統組件模型如圖。
前端通訊模塊負責和應用程序通訊,接收到SQL請求(select * from users where userid in (12,22,23))後轉交給SQL解析模塊,SQL解析模塊解析得到SQL中的路由規則查詢條件(userid in(12,22,23))再轉交給SQL路由模塊,SQL路由模塊根據路由規則配置(userid爲偶數路由至數據庫A, userid爲奇數路由至數據庫B)將應用程序提交的SQL分解成兩條SQ L(select * from users w here userid in (12,22);select * from users w here userid in (23);)轉交給SQL執行代理模塊,發送至數據庫A和數據庫B分別執行。
數據庫A和數據庫B的執行結果返回至SQL執行模塊,經過結果合併模塊將兩個返回結果集合併成一個結果集,最終返回給應用程序,完成在分佈式數據庫中的一次訪問請求。
那麼Cobar如何作集羣的伸縮呢?
Cobar的伸縮有兩種:1.Cobar服務器集羣的伸縮和2.MySQL服務器集羣的伸縮。
2.NoSQL數據庫的伸縮性設計
大型網站遇到了關係數據庫難以克服的缺陷——糟糕的海量數據處理能力及僵硬的設計約束,局面纔有所改善。爲了解決上述問題,NoSQL這一律念被提了出來,以彌補關係數據庫的不足。
NoSQL,主要指非關係的、分佈式的數據庫設計模式。也有許多專家將NoSQL解讀爲N ot O nly SQ L,表示NoSQL只是關係數據庫的補充,而不是替代方案。通常而言,NoSQL數據庫產品都放棄了關係數據庫的兩大重要基礎:以關係代數爲基礎的結構化查詢語言(SQL)和事務一致性保證(ACID)。而強化其餘一些大型網站更關注的特性:高可用性和可伸縮性。
開源社區有各類N oSQL產品,其支持的數據結構和伸縮特性也各不相同,目前看來,應用最普遍的是Apache HBase。
高手定律:
這個世界只有遇不到的問題,沒有解決不了的問題,高手之因此成爲高手,是由於他們遇到了常人很難遇到的問題,並解決了。因此百度有不少廣告搜索的高手,淘寶有不少海量數據的高手,Q Q有不少高併發業務的高手,緣由大抵如此。一個100萬用戶的網站,不會遇到1億用戶同時在線的問題;一個擁有100萬件商品網站的工程師,可能沒法理解一個擁有10億件商品網站的架構。
救世主定律:
遇到問題,分析問題,最後總能解決問題。若是遇到問題就急匆匆地從外面挖一個高手,而後期望高手如探囊取物般輕鬆搞定,最後怕是隻有彼此抱怨和傷害。許多問題只是看起來同樣,具體問題老是要具體對待的,沒有銀彈,沒有救世主。因此這個定律準確地說應該是「沒有救世主定律」。
網站擴展性架構設計:對現有系統影響最小的狀況下,系統功能可持續擴展及提高的能力。
首先釐清容易混淆的兩個概念:
1.擴展性(Extensibility):
指對現有系統影響最小的狀況下,系統功能可持續擴展或提高的能力。表如今系統基礎設施穩定不須要常常變動,應用之間較少依賴和耦合,對需求變動能夠敏捷響應。它是系統架構設計層面的開閉原則(對擴展開放,對修改關閉),架構設計考慮將來功能擴展,當系統增長新功能時,不須要對現有系統的結構和代碼進行修改。
2.伸縮性(Scalability):
指系統可以經過增長(減小)自身資源規模的方式加強(減小)本身計算處理事務的能力。若是這種增減是成比例的,就被稱做線性伸縮性。在網站架構中,一般指利用集羣的方式增長服務器數量、提升系統的總體事務吞吐能力。
若是模塊之間不存在直接調用,那麼新增模塊或者修改模塊就對其餘模塊影響最小,這樣系統的可擴展性無疑更好一些。
1.事件驅動架構:
事件驅動架構(Event Driven Architecture):經過在低耦合的模塊之間傳輸事件消息,以保持模塊的鬆散耦合,並藉助事件消息的通訊完成模塊間合做,典型的EDA架構就是操做系統中常見的生產者消費者模式。在大型網站架構中,具體實現手段有不少,最經常使用的是分佈式消息隊列,如圖所示。
2.分佈式消息隊列:
目前開源的和商業的分佈式消息隊列產品有不少,比較著名的如Apache ActiveMQ等,這些產品除了實現分佈式消息隊列的通常功能,在可用性、伸縮性、數據一致性、性能和可管理性方面也作了不少改善。
巨無霸的應用系統會帶來不少問題:
1.編譯,部署困難
2.代碼分支管理困難
3.數據庫鏈接耗盡
4.新增業務困難
解決方案就是拆分,將模塊獨立部署,下降系統耦合性。拆分能夠分爲縱向拆分和橫向拆分兩種。
縱向拆分:將一個大應用拆分爲多個小應用,若是新增業務較爲獨立,那麼就直接將其設計部署爲一個獨立的Web應用系統。
橫向拆分:將複用的業務拆分出來,獨立部署爲分佈式服務,新增業務只須要調用這些分佈式服務,不須要依賴具體的模塊代碼,便可快速搭建一個應用系統,而模塊內業務邏輯變化的時候,只要接口保持一致就不會影響業務程序和其餘模塊。
1.Web Service與企業級分佈式服務
2.大型網站分佈式服務的需求和特色
對於大型網站,除了Web Services所提供的服務註冊與發現,服務調用等標準功能,還須要分佈式服務框架可以支持以下功能。
1.負載均衡
2.失效轉移
3.高效的遠程通訊
4.整合異構系統
5.對應用最少侵入
6.版本管理
7.實時監控
3.分佈式服務框架設計
例如Facebook的Thrift。
服務消費者程序經過服務接口使用服務,而服務接口經過代理加載具體服務,具體服務能夠是本地的代碼模塊,也能夠是遠程的服務,所以對應用較少侵入:應用程序只須要調用服務接口,服務框架根據配置自動調用本地或遠程實現。
服務框架客戶端模塊經過服務註冊中心加載服務提供者列表(服務提供者啓動後自動向服務註冊中心註冊本身可提供的服務接口列表),查找須要的服務接口,並根據配置的負載均衡策略將服務調用請求發送到某臺服務提供者服務器。若是服務調用失敗,客戶端模塊會自動從服務提供者列表選擇一個可提供一樣服務的另外一臺服務器從新請求服務,實現服務的自動失效轉移,保證服務高可用。
開放平臺是網站內部和外部交互的接口,外部須要面對衆多的第三方開發者,內部須要面對網站內諸多的業務服務。雖然每一個網站的業務場景和需求都各不相同,可是開放平臺的架構設計卻大同小異,如圖所示。
API接口:是開放平臺暴露給開發者使用的一組API,其形式能夠是RESTful、WebService、RPC等各類形式。
協議轉換:將各類API輸入轉換成內部服務能夠識別的形式,並將內部服務的返回封裝成API的格式。
安全:除了通常應用須要的身份識別、權限控制等安全手段,開放平臺還須要分級的訪問帶寬限制,保證平臺資源被第三方應用公平合理使用,也保護網站內部服務不會被外部應用拖垮。
審計:記錄第三方應用的訪問狀況,並進行監控、計費等。
路由:將開放平臺的各類訪問路由映射到具體的內部服務。
流程:將一組離散的服務組織成一個上下文相關的新服務,隱藏服務細節,提供統一接口供開發者調用。
既然咱們知道網站不停上新產品是其生存的本能,誰能更快更好地推出更多的新產品,誰就活得更滋潤,那麼工程師就要作好準備應付這種局面。馬克思的勞動價值理論告訴咱們,產品的內在價值在於勞動的時間,勞動的時間不在於個體付出的勞動時間,而在於行業通常勞動時間,資本家只會爲行業通常勞動時間買單,若是你的效率低於行業通常勞動時間,對不起,請你自願加班。反之,若是你有一個更具備擴展性的網站架構,能夠更快速地開發新產品,也許你也享受不了只上半天班的福利,可是至少在這個全行業加班的互聯網領域,你可以按時下班,陪陪家人,看看星星。
架構如圖。
Wikipedia架構的主要組成部分以下。
GeoDNS:基於開源域名服務器軟件BIND(Berkeley Internet Name Domain)的加強版本,可將域名解析到離用戶最近的服務器。
LVS:基於Linux的開源負載均衡服務器。
Squid:基於Linux的開源反向代理服務器。
Lighttpd:開源的應用服務器,較主流的Apache服務器更輕量、更快速。實踐中,有許多網站使用L ighttpd做爲圖片服務器。
PHP:免費的Web應用程序開發語言,最流行的網站建站語言。
Memcached:無中心高性能的開源分佈式緩存系統,穩定、可靠、歷久彌新,是網站分佈式緩存服務必備的。
Lucene:由Apache出品,Java開發的開源全文搜索引擎。
MySQL:開源的關係數據庫管理系統,雖被Oracle收購,但開源社區將其繼續開源發展的決心不動搖。
關於故障:
在討論解決方案以前,咱們先對故障進行分類,針對不一樣故障狀況分別對待。對於一個分佈式存儲系統而言,影響系統總體可用性的故障能夠分紅如下三類。
× 瞬時故障:引發這類故障的主要緣由是網絡通訊瞬時中斷、服務器內存垃圾回收或後臺線程繁忙中止數據訪問操做響應。其特色是故障時間短,在秒級甚至毫秒級系統便可自行恢復正常響應。
× 臨時故障:引發這類故障的主要緣由是交換機宕機、網卡鬆動等致使的網絡通訊中斷;系統升級、停機維護等通常運維活動引發的服務關閉;內存損壞、CPU過熱等硬件緣由致使的服務器宕機;這類故障的主要特色是須要人工干預(更換硬件、重啓機器等)才能恢復正常。一般持續時間須要幾十分鐘甚至幾小時。故障時間可分爲兩個階段:臨時故障期間,臨時故障恢復期間。
× 永久故障:引發這類故障的主要緣由只有一個:硬盤損壞,數據丟失。雖然損壞硬盤和損壞內存同樣,能夠經過更換硬盤來從新啓動機器,可是丟失的數據卻永遠找不回來了,所以其處理策略也和前面兩種故障徹底不一樣,恢復系統到正常狀態也須要更長的時間。故障時間可分爲兩個階段:永久故障期間和永久故障恢復期間。
1.對現有網站業務形成衝擊
2.高併發下的應用,數據庫負載
3.忽然增長的網絡及服務器帶寬
4.直接下單
1.秒殺系統獨立部署
2.秒殺商品頁面靜態化
3.租借秒殺活動網絡帶寬
4.動態生成隨機下單頁面URL
故障現象:某應用服務器不定時地由於響應超時而報警,可是很快又超時解除,恢復正常,如此反覆,讓運維人員很是苦惱。
緣由分析:程序中某個單例對象(singleton object)中多處使用了synchronized(this),因爲this對象只有一個,全部的併發請求都要排隊得到這惟一的一把鎖。通常狀況下,都是一些簡單操做,得到鎖,迅速完成操做,釋放鎖,不會引發線程排隊。可是某個須要遠程調用的操做也被加了synchronized(this),這個操做只是偶爾會被執行,可是每次執行都須要較長的時間才能完成,這段時間鎖被佔用,全部的用戶線程都要等待,響應超時,這個操做執行完後釋放鎖,其餘線程迅速執行,超時解除。
經驗教訓:
× 使用鎖操做要謹慎。