微博伺服器又炸了,快來看看如何一步步構建高併發的網站

窗邊的扁豆發表於2017-10-09

如何構建高併發的網站

  • 昨天的微博伺服器又炸了,心疼微博三秒鐘 。雖然網上各種嘲諷謾罵渣浪的,不過作為程式設計師細細想想感覺新浪還是很不容易的,畢竟它也沒法知道哪個明星突然就出啥事了,面對突如其來的多出好幾倍的訪問量感覺無論是哪家公司也是沒法馬上應對的吧。
  • 通過這件事,也讓筆者認識到了構建一個在高併發環境下依舊高可用的系統是多麼的重要,恰好最近一直在看這方面的東西,所以就蹭蹭熱度和大家一起分享下。

初級階段的架構

  • 最簡單的架構莫過於就只有一臺伺服器,無論是web程式,資料庫還是檔案都放在一起,就像下面的結構一樣:

    這裡寫圖片描述
    這裡寫圖片描述

    筆者在大二的時候做wakeup校園平臺的時候就是採用的這種架構,用的阿里雲最便宜的10塊錢雲伺服器,20G儲存+1G記憶體+1M的頻寬。因為用的人比較少,總的註冊使用者也就幾百人,每天籤簽到,發發分享基本也不會出什麼問題。

  • 但是隨著網站使用者的逐漸增加,使用者量肯定也會越來越多,這時候如果把壓力都交給同一臺伺服器,那也太殘忍了,這時候就需要將壓力分散開來。也就形成了下面這種架構:

    這裡寫圖片描述
    這裡寫圖片描述

    應用程式,檔案伺服器,資料庫伺服器分別部署到不同的伺服器上,應用伺服器與檔案伺服器,資料庫伺服器之間通過網路傳輸進行通訊。

  • 漸漸的,隨著時間的推移,資料庫裡面的資料越來越多,導致的直接結果就是查詢資料會變得越來越慢,因為每次查詢資料我們都是直接從磁碟中讀取的,眾所周知,磁碟的訪問速度是很慢的,所以這個時候我們就需要用到快取了。(劃重點,網站優化的第一定律:優先使用快取提升網站的效能)。所以我們就需用使用快取伺服器了:

    這裡寫圖片描述
    這裡寫圖片描述

    在這裡,應用伺服器優先先向快取伺服器請求資料,如果沒有獲取到再請求資料庫。由於網際網路訪問的資料基本是遵守二八定律的(即:80%的請求中訪問的往往是20%的熱門資料,就像微博中最多人看的往往都是一些大V的微博,像我們這些小菜鳥發的微博基本都沒人看>_<)。

    雖然使用快取可以極大提升網站的效能,不過也會帶來一些問題的,例如加入資料庫中的資料已經更新了,但是快取中的資料還是之前的舊的那麼使用者不就會獲取到不正確的資料了嗎?對於這個問題,一般有這麼兩種解決方案:

    1. 對於快取中的資料設定一個過期時間,資料過期之後就要從資料庫中拉取最新資料,如果對資料一致性要求不是特別高的場景可以採用這種方案。
    2. 當資料庫中的資料更新之後,重新整理快取中的資料。對於一致性要求高的場景可以採用這種方案。

中級階段的架構

  • 如果小夥伴們的網站通過以上的架構還是頂不住了,說明這時候小夥伴網站的使用者已經比較可觀了,這時候就要考慮應付以下兩個問題了:

    1. 使用者高併發的訪問了。我們知道,現代的web伺服器很多都是通過多執行緒的技術實現的高併發,然而一個程式能夠建立的執行緒是有限的,所以如果突然很多使用者同時訪問,我們的應用伺服器就頂不住了。
    2. 由於高併發的問題,資料庫的讀寫壓力特別大,這時候我們就要考慮能否將資料庫的讀寫分離,讓讀寫操作分別在不同的伺服器上。
  • 我們首先來解決問題1,如何應對高併發的問題,這裡我們就可以通過反向代理的技術,將使用者的請求通過反向代理伺服器分散不同的伺服器中,讓每臺伺服器的負載得到均衡,從而達到高併發的目的。那麼問題來了,什麼是反向代理呢?這裡我們舉兩個栗子來形容下:

    這裡寫圖片描述
    這裡寫圖片描述

    • 要想搞明白什麼是反向代理,首先我們必須清楚的是什麼叫做正向代理,也就是普通的代理模式,這裡我們通過一個場景切入:

      假如小明這時候正在創業,需要300萬的創業資金,於是想去找馬雲爸爸幫幫忙。可是馬雲爸爸日理萬機哪有空見你呀,於是就失敗了。恰好這時候你無意中知道了自己的好哥們其實是馬雲爸爸失散多年的兒子,於是就通過他去向馬雲爸爸請求投資的事,然後就成功得到了300萬。但其實馬雲爸爸並不知道這錢是投資給你的,這裡你的好哥們就是代理,通過他你達到了目的。

      在現實中,正向代理的栗子是很常見的,最常見的莫過於我們通過VPN進行科學上網了,我們就是通過一臺可以訪問到外網的伺服器讓它幫我們請求資源然後再將獲得的資源返回給我們。

    • 既然瞭解了什麼是正向代理,我們也就很好解釋什麼是反向代理了,還是舉一個栗子吧:

      假如有一天你在二手東買到假貨了,這時候你想打電話去投訴。京東的客服是有很多的,但是京東的投訴電話卻只有一個,當我們打通這個電話之後。京東的系統會根據當前哪位客服是空閒的把你的電話轉接到空閒的客服那去。這裡的轉接系統就是一個反向代理,因為它是幫伺服器做代理的而不是幫客戶端做代理的。

      所以正向代理和反向代理最大的區別就是:正向代理是服務於客戶端的,它使服務端不知道到底是誰才是真正的請求者。反向代理是服務於伺服器端的,它使客戶端不知道到底哪臺伺服器真正處理了自己的請求。

  • 解決了第一個問題,我們再來看看第二個問題,第二個問題就很好解決了。要做到資料庫的讀寫分離,對於使用者的每次更新操作都將資料寫到寫資料庫中去,對於所有的讀操作都直接去讀資料庫中去,所以這裡可以有很多的讀資料庫。(但也不能太多,否則些資料庫的同步壓力會比較大。)

    這裡寫圖片描述
    這裡寫圖片描述

    大體的實現架構如上:主要通過讀寫分離與反向代理提高了網站的併發能力。筆者暑假去實習的那家公司基本就是用的上面這種架構,通過nignx做反向代理實現負載均衡,並對mysql資料庫進行讀寫分離。

  • 除此之外,我們還可以使用cdn加速網站的響應速度。這裡的cdn其實原理就是一種快取技術,使得使用者在請求網站的時候可以從距離自己最近的網路提供商機房獲取資料。

高階階段的架構

  • 如果小夥伴們的網站即使通過以上架構還是頂不住的話,那麼使用者量肯定已經達到一個比較可怕的數字了。這個時候就需要進行更深層次的改造了。不過筆者到目前剛剛大四,還沒有接觸過這麼牛逼的系統。只能根據所學習到的分享一下了。

  • 到這個階段,由於資料量太過龐大,傳統的單機式伺服器已經不能滿足需求了,這時候我們就需要用到分散式資料庫(筆者接觸過的是hbase)與分散式檔案系統(例如hadoop的hdfs以及fastDfs)了。他們基本都是主從協調,網路通訊以及資料冗餘的方式達到資料分散式存放的目的的,從外界看來其和普通的資料庫/檔案系統並沒有什麼區別。有興趣的小夥伴可以去深入瞭解下(這個圖就比較複雜了,就盜用網上的圖了)。

    這裡寫圖片描述
    這裡寫圖片描述

  • 除了使用分散式系統之外,由於大型網站的業務邏輯一般比較複雜,所以常常需要進行業務劃分,不同的部門負責不同的模組,但是不同的模組之間又會有很多公有的服務,例如百度的所有產品都可以通過百度賬號進行登陸,所以這裡的登陸模組就可以做成一個公共的服務供不同的業務模組呼叫。

    這裡寫圖片描述
    這裡寫圖片描述

    就像上圖一樣不同的業務有自己獨立的業務系統,對於公有的服務可以進行復用。對於每一個服務又都可以單獨通過負載均衡以及分散式叢集實現高可用。

總結

  • 無論多麼龐大的系統都是一點一點不斷的改進優化而來的,在當系統效能達到瓶頸的時候,我們首先想到的絕對不應該是增加伺服器的效能,而是如何通過增加伺服器的數量從而降低伺服器的平均負載(昨天微博不就緊急購買了1000臺伺服器降低壓力嘛)。同時為了資料的安全,我們也不得不對資料進行冗餘備份防止意外事件的發生。筆者能力有限,講到的也只是網站架構的冰山一角,其實內部還有很多細節的問題,例如如何釋出共有的服務,客戶端如何呼叫到釋出的服務等待很多問題。如果發現文章有任何問題,歡迎私信或者留言交流,也可以關注筆者的微信公眾號,一起學習交流一起進步。

    img
    img

相關文章