1. 程式人生 > >高併發的大型網站架構設計

高併發的大型網站架構設計

最近在學習大型網站的架構設計,便想把學習過程中的一些東西總結記錄下來,以便複習和鞏固提高。先來看看大型網站架構圖:

大型網站架構圖

從左邊開始,先是CDN伺服器和反向代理伺服器,都用於快取一些使用者需要請求的資源。兩者的區別在於CDN部署在網路提供商的機房,使用者可以就近獲取;反向代理則部署在網站中心機房。使用CDN和反向代理的目的都是儘快返回資料給使用者。這樣可以加快返回使用者資源的速度,也減輕了後端伺服器的負載壓力。
往下走,是一臺負載均衡排程伺服器,用於將使用者的請求傳送到伺服器叢集上。這裡面A,B應用伺服器可以是Tomcat伺服器叢集,只不過它上面只部署了Action,也就是我們平時寫的controller層的程式碼。在這裡面去呼叫被分別部署在不同伺服器上的業務層程式碼(大型網站會進行業務拆分,將不同的應用獨立部署)。如果某些業務請求量較大,業務處理時間較長,可以根據實際情況來將其加入訊息佇列,以達到快速返回的目的。最後,由分散式的業務伺服器去呼叫分散式的資料庫系統實現資料的儲存。右邊,檔案這些東西可以部署在分散式的檔案伺服器上。右上,使用分散式快取伺服器將平時最常訪問的20%資料(二八定律:80%的業務訪問集中在20%的資料上)快取起來。最下面兩個,由於網站業務相當複雜,採用一些非關係資料庫如nosql和非資料庫查詢技術如搜尋引擎進行進行資料的儲存和檢索。
以上,就是一個大型網站的大體架構。
總體架構講完了,接下來講一點具體的東西。大型網站核心架構要素:效能,可用性,伸縮性,擴充套件性,安全性。
先來講效能:

web前端效能優化:

一般來講,web前端主要優化手段有優化瀏覽器訪問,使用反向代理,CDN等。

瀏覽器訪問優化:

1 減少http請求
http請求的開銷都很昂貴,應該儘量減少http請求次數。主要手段是將javascrit,css,圖片合併成一個檔案,這樣瀏覽器只需一次請求。
2 使用瀏覽器快取
對網站而言,css,javascript,logo,圖示這些資源更新頻率低,可以設定http頭中的Cache-Control和Expires屬性將其快取在瀏覽器中。
3 啟用壓縮
可以在伺服器端對檔案進行壓縮,文字檔案的壓縮效率可達80%以上,因此HTML,CSS,Javascript檔案啟用GZip壓縮可以達到較好的效果
4 css檔案放在頁面最上面,javascript放在頁面最下面
瀏覽器在css全部下載完之後才進行頁面渲染,而javascript則是載入後就立即執行。因此先進行css檔案的下載,javascript放在最後即可。

cdn加速

CDN(內容分發網路)本質仍是一個快取,而且將資料快取在離使用者最近的地方,使使用者以最快速度獲取資料。一般快取靜態資源。

反向代理

反向代理伺服器可以保護伺服器的安全,來自網際網路的請求必需經過代理伺服器。所以也可以在代理伺服器放一些靜態資料,當用戶第一次訪問靜態內容時,靜態內容就被快取在方向代理伺服器上,其他使用者請求進來時,就可以直接返回,減輕web伺服器負載壓力。

應用伺服器效能優化

伺服器的優化手段主要有快取,叢集,非同步等。

非同步操作:

在高併發情況下,若不使用訊息佇列,使用者請求直接寫入資料庫會對資料庫造成巨大的壓力,同時使響應延遲加劇。使用訊息佇列,非同步寫入資料庫,可以起到很好的削峰作用,改善網站的擴充套件性,提升網站效能。

使用叢集:

在網站高併發訪問的場景下,使用負載均衡技術為應用構建一個墮胎伺服器組成的叢集,將併發訪問請求分發到多臺伺服器上處理,避免單一伺服器因負載壓力過大而響應緩慢。

程式碼優化:

1 多執行緒
從資源利用的角度來看,使用多執行緒的原因主要有兩個:
  • io阻塞:當執行緒進行io處理時,會阻塞cpu以等待io。利用多執行緒io阻塞與執行交替進行,可以最大限度利用cpu。

  • 多cpu:一個伺服器有多個cpu,在這個手機都有四核cpu的時代要想做大限度使用這些cpu,必需啟用多執行緒。

2 資源複用
資源複用主要有兩種模式:單例和物件池。
  • 單例:由於web開發中主要使用貧血模式,使用很多無狀態物件,無需重複建立,因此使用單例模式自然而然的事。

  • 執行緒池:物件池通過複用物件例項,減少物件建立和資源消耗。

3 資料結構
在不同的場景中使用適當的資料結構,改寫資料和計算特性可以極大優化程式的效能。
4 垃圾回收
如果web應用執行在JVM等具有垃圾回收功能的環境中,理解垃圾回收機制有助於程式優化和引數調優,以及編寫記憶體安全的程式碼。

網站架構的伸縮性設計

一般來說。網站的伸縮性設計可分為兩類:一類是根據功能進行物理分離實現伸縮,一類是單一功能通過叢集實現伸縮。前者是不同的伺服器部署不同的服務,提供不同的功能;後者是叢集內的伺服器部署相同的服務實現相同的功能。

應用伺服器叢集的伸縮性設計

負載均衡是實現伸縮性設計的關鍵技術。因為它能將使用者的請求按照某種規則分發到叢集不同的伺服器上,且能感知或配置叢集的伺服器數量,及時發現新上線或下線的伺服器,以此來實現應用伺服器叢集的可伸縮性。實現負載均衡的技術有以下幾種:
  • http重定向負載均衡

       http伺服器就是一臺普通的應用伺服器,唯一功能就是根據根據使用者的http請求計算一臺真實的web伺服器地址。這種方案的優點是比較簡單。缺點是瀏覽器需要兩次請求伺服器才能完成一次訪問,效能較差;實踐中不常採用。
    
  • dns域名解析負載均衡

     每次域名解析請求都會根據負載均衡演算法計算一個不同的ip地址返回。優點是將負載均衡工作交給dns,省掉了網站管理維護負載均衡伺服器的麻煩。缺點是dns負載均衡的控制權在域名服務商那裡,網站無法對其做更多的改善和更強大的管理。
    
  • 反向代理負載均衡

    反向代理伺服器需要雙網絡卡及內部外部兩套ip地址。其優點是和反向代理伺服器功能整合在一起,部署簡單。缺點是所有請求均經過此,其效能可能成為瓶頸。
    
    • ip負載均衡

      在網路層通過修改請求目標地址進行負載均衡。ip負載均衡在核心程序完成資料分發,有更好的處理效能。但對需要提供下載服務或視訊服務的大型網站而言,難以滿足需求。

    • 資料鏈路層負載均衡

      在通訊協議的資料鏈路層修改mac地址進行負載均衡。此模式是目前大型網站採用最廣的一中負載均衡手段。

資料庫儲存伺服器叢集的伸縮

這裡主要將關係型資料庫的伸縮設計。對於進行了水平分庫分表的資料庫,可以用一些分散式資料庫產品例如Mycat,Cobar.

利用分散式訊息佇列降低降低系統耦合性

如果模組間不存在直接呼叫,那麼新增或修改對其他模組的影響就最小。通過在低耦合的模組間傳輸事件訊息,來保持模組的鬆散耦合。最常用的是分散式訊息佇列。在伸縮性方面,由於訊息佇列上的伺服器上的資料是即時被處理的,可以看作無狀態的伺服器,伸縮性比較簡單,將新伺服器加入分散式訊息佇列叢集中,通知生產者伺服器更改訊息佇列伺服器列表即可。在可用性方面,為避免記憶體空間不足的問題,會將訊息寫入磁碟。

網站應用攻擊與防禦:

從網際網路誕生之日起,各種web攻擊和資訊洩漏也從未停止。在此講一下主要的攻擊手段及防禦措施。

  • xss攻擊

    xss即跨站點指令碼攻擊,致黑客通過篡改網頁,注入惡意html指令碼。主要防禦手段有兩種:
    
    1 消毒
    
    對某些html危險字元轉義,如“>”轉義為“&gt”。
    
    2 HttpOnly
    
    即瀏覽器禁止頁面javascript訪問帶有HttpOnly屬性的cookie。
    
    • sql注入

    sql注入,攻擊者在http請求中注入惡意sql命令。防禦方法,還是消毒,過濾請求資料中可能注入的sql。或者引數繫結,如mybatis的#{},將攻擊者的sql視為引數,而不是可執行sql。

    • csrf攻擊

    跨站點請求偽造,攻擊者通過跨站請求,以合法使用者身份進行非法操作。其核心是利用伺服器session或瀏覽器cookie策略。盜取使用者身份。防禦方法
    1 表單token。在頁面表單加入一個隨機數作為token值,提交到伺服器進行檢查。
    2 驗證碼
    3 Refer Check
    http請求頭的請求域中記錄著請求來源,可檢查請求來源驗證其是否合法。

web應用防火牆
ModSecurity,一種開源的web應用防火牆,探測攻擊並保護web程式。
網站安全漏洞掃描
指根據一定規則構造攻擊性url模擬黑客行為的工具。

由於本部落格只是對大型網站的架構及其用到的技術做一個大致的描述(不太好做詳細的講解,因為這裡牽扯的知識點實在太多,而每個知識點又是可以單獨提出來寫成一片或幾篇部落格的那種),所以對大多數知識點的講解只是淺嘗輒止,如果想了解更多細節的同學,可以自行百度或者閱讀本文的主要參考文獻:

大型網站技術架構核心原理與案列分析