• 用戶規模越來越大,系統不能承受的服務器之重

    0
    Lua HTML C/C++ Go 挨踢生涯 13672 次瀏覽

                                        用戶規模越來越大,系統不能承受的服務器之重

     有一家客戶,他在一周內流量暴漲,連自己都沒有想到在三天內從一個基本上沒有什么人用的應用,突然變成了全國人民都非常喜愛用的一個應用。然后一周內dau就突破了兩百萬。他們的服務器可能就幾臺,他們的程序員可能就幾個人。那么面對著突然到來的流量暴增,技術人員壓力非常大。加班加點的可能幾夜都合不上眼的,因為流量暴漲所帶來的各種各樣的技術問題,在一兩天里面集中地爆發出來,流量暴漲、程序的bug,被無數人使用之后各種程序bug也會出來。那么如果是短時間內訪問暴漲、技術架構彈性不足,導致服務器壓垮、性能問題、架構可擴展性問題等等都暴露出來了……

    作為企業老板,每個人都希望自己的產品做大、做好,那么問題就來了,當你的后臺系統遇到上述挑戰時,再去解決bug,那時候就火燒眉毛了,解決不及時的后果,大牛網小編就不去往下說了。為此,我們在開發我們的產品時,就應該未雨綢繆,做到多大的并發量訪問后臺負荷運轉沒問題。對此,大牛網從后臺服務器角度來給企業分析如何減輕服務器的壓力。

    一個運營的系統在正式上線后將會遇到各種層級的高并發請求,因此我們必須對此做出相應的策略和技術解決方案,首先我們需要認清系統的高并發由3個層面導致:

    1. 傳輸層
    大量用戶對系統請求后,將會造成網絡帶寬和Web服務器的I/O瓶頸。

    2. 計算層
    接收大量用戶請求進行計算,將會造成業務服務器和業務支撐服務器的瓶頸。

    3. 存儲層
    傳輸層和計算層將會產生大量的數據,數據量暴增,將會導致數據庫和儲存上的瓶頸。【】

          那我怎么樣才能建立一個可靠的服務器架構?來自知乎的作者牛浩帆根據自己的實際經驗給出了自己的見解:

    初級篇:(單機模式)


    假設配置:(Dual core 2.0GHz,4GB ram,SSD
    基礎框架:apache(PHP) + Mysql / IIS + MSSQL
    (最基礎框架,處理一般訪問請求)
    進階1:替換ApacheNginx,并在數據庫前加上cache層【數據庫的速度是最大的瓶頸】
    Nginx(PHP) + Memcache + Mysql(此時已經具備處理小型訪問量的能力)
    進階2:隨著訪問量的上漲,最先面臨的問題就來了:CGI無法匹配上Nginx的高IO性能,這時候可以通過寫擴展來替代腳本程序來提升性能,C擴展是個好辦法,但是大家更喜歡用簡單的腳本語言完成任務,Taobao團隊開源了一個Nginx_lua模塊,可以用luaNginx擴展,這時候可處理的并發已經超越進階一個檔次了。
    Nginx(nginx_lua or C) + Memcache + Mysql
    (此時處理個同時在線三四千人沒有問題了)
    進階3:隨著用戶的增多,Mysql的寫入速度成了又一大瓶頸,讀取有memcache做緩存,但寫入是直接面對Mysql,性能受到了很大阻礙,這時候,要在NginxMysql中間加入一層寫緩存,隊列系統就出場了,就以RabbitMQ為例,所有寫入操作全部丟到這只兔子的胃里面,然后屁股后面寫個接應程序,一條條的拉出來再寫入mysql。而RabbitMQ的寫入效率是MysqlN倍,此時架構的處理能力又上一階層。
    |----write------>RabbitMQ--------
    Nginxlua or c----- |--------->Mysql
    |----read------>Memcache--------
    (此時的并發吞吐能力已經可以處理萬人左右在線)
    中級篇:(分而治之)
    此時我們在單機優化上已經算是達到極限,接下來就要集群來顯示作用了。
    數據庫篇: 數據庫總是在整個環節中是吞吐能力最弱的,最常見的方法就是sharding
    sharding可以按多種方法來分,沒有定式,看情況。可以按用戶ID區段分,按讀寫分等等,可用參考軟件:mysql proxy(工作原理類似lvs
    緩存篇:memcache一般采用的是構建memcache pool,將緩存分散到多臺memcache節點上,如何將緩存數據均勻分散在各節點,一般采用將各節點順序編號,然后hash取余對應到各個節點上去。這樣可以做到比較均勻的分散,但是有一個致命點就是,如果節點數增加或減少,將會帶來幾乎80%的數據遷移,解決方案我們在高級篇再提。
    WEB服務器篇: web服務器集群的建設,最常見的就是lvs方式(memcache pool同樣可以如此組建)lvs的核心就是調度節點,調度節點負責將流量通過算法分散到各個節點上,因調度所耗資源很少,所以可以產生很高的吞吐率,后臺節點數量可以任意增刪,但此法弊病就是如果調度節點掛了,則整個集群都掛了,解決方案我們在高級篇提。
    方法2:參見 HAProxy - The Reliable, High Performance TCP/HTTP Load Balancer
    高級篇:(高可用性+高可擴展性的集群)
    單點調度故障解決:
    集群的好處顯而易見,但是有一個弊端就是單節點進行調度,如果節點出現故障,則整個集群全部都無法服務,對此的解決方案,我們使用keepalived來解決。Keepalived for Linux
    keepalived是基于VRRP協議(VRRP協議介紹)的,請一定先了解VRRP協議后再進行配置。
    keepalived可以把多臺設備虛擬出一個IP,并自動在故障節點與備用節點之間實現failover切換。這樣我們配置兩臺貨多臺lvs調度節點,然后配置好keepalived就可以做到lvs調度節點出現故障后,自動切換到備用調度節點。(同樣適用于mysql
    memcache集群擴展解決:
    memcache因為我們一般采用的都是hash后除以節點數取余,然后分配到對應節點上,如果節點數出現變化,以前的緩存數據將基本都不能命中。
    解決方法:consistent hashing 簡介:一致性哈希
    consistent hashing大概的思路就是,把hash后的值保證在 0 ~ (2^32)-1 的數值上,然后把這一連串數字對應映射到一個想象的圓上。 
    把要存儲的各個值hash后,放到圓上,如圖

    然后把cache節點也用同樣的hash方法,映射到圓上,然后每個剛才hash過的value順時針尋找離自己最近的節點,這個節點就是存儲它的節點。

    為了提高存儲的平衡性,算法還可以加入虛擬節點的概念,即每個實際cache節點,會在圓上對應N個虛擬的節點,這樣可以提高算法的命中率,更加平衡。


          假如現在已經遇到了服務器的瓶頸,那么有沒有具體的解決的策略呢?來自linux社區的作者lindianli給出了他的一些解決方案:

    1. 負載均衡

    負載均衡將是大型網站解決高負荷訪問和大量并發請求采用的終極解決辦法。

    1)單個重負載的運算分擔到多臺節點設備上做并行處理,每個節點設備處理結束后,將結果匯總,返回給用戶,系統處理能力得到大幅度提高.

    2)大量的并發訪問或數據流量分擔到多臺節點設備上分別處理,減少用戶等待響應的時間,這主要針對Web服務器、FTP服務器、企業關鍵應用服務器等網絡應用。

     

    2. 數據庫集群

    就是利用至少兩臺或者多臺數據庫服務器,構成一個虛擬單一數據庫邏輯映像,像單數據庫系統那樣,向客戶端提供透明的數據服務。

     

    3. 庫表散列

    采用Hash算法把數據分散到各個分表中這樣IO更加均衡。

    上面提到的數據庫集群由于在架構、成本、擴張性方面都會受到所采用DB類型的限制,于是我們需要從應用程序的角度來考慮改善系統架構,庫表散列是常用并且最有效的解決方案。我們在應用程序中安裝業務和應用或者功能模塊將數據庫進行分離,不同的模塊對應不同的數據庫或者表,再按照一定的策略對某個頁面或者功能進行更小的數據庫散列,比如用戶表,按照用戶ID進行表散列,這樣就能夠低成本的提升系統的性能并且有很好的擴展性。sohu的論壇就是采用了這樣的架構,將論壇的用戶、設置、帖子等信息進行數據庫分離,然后對帖子、用戶按照板塊和ID進行散列數據庫和表,最終可以在配置文件中進行簡單的配置便能讓系統隨時增加一臺低成本的數據庫進來補充系統性能。

     

    4. 圖片服務器分離

    大家知道,對于Web服務器來說,不管是ApacheIIS還是其他容器,圖片是最消耗資源的,于是我們有必要將圖片與頁面進行分離,這是基本上大型網站都會采用的策略,他們都有獨立的圖片服務器,甚至很多臺圖片服務器。這樣的架構可以降低提供頁面訪問請求的服務器系統壓力,并且可以保證系統不會因為圖片問題而崩潰,在應用服務器和圖片服務器上,可以進行不同的配置優化,比如apache在配置ContentType的時候可以盡量少支持,盡可能少的LoadModule,保證更高的系統消耗和執行效率。

     

    5. 鏡像

    鏡像是大型網站常采用的提高性能和數據安全性的方式,鏡像的技術可以解決不同網絡接入商和地域帶來的用戶訪問速度差異,比如ChinaNetEduNet之間的差異就促使了很多網站在教育網內搭建鏡像站點,數據進行定時更新或者實時更新。

    自動把整個數據庫或其中的關鍵數據復制到另一個磁盤上,每當主數據庫更新時,DBMS會自動把更新后的數據復制過去,即DBMS自動保證鏡像數據與主數據的一致性。

    出現介質故障時,可由鏡像磁盤繼續提供數據庫的可用性,同時DBMS自動利用鏡像磁盤進行數據庫的修復,不需要關閉系統和重裝數據庫副本。

    數據庫鏡像還可以用于并發操作。即當一個用戶對數據庫加排他鎖修改數據時,其他用戶可以讀鏡像數據庫,而不必等待該用戶釋放鎖。

    數據庫鏡像是通過復制數據實現的,頻繁地復制自然會降低系統運行效率,因此在實際應用中用戶往往只選擇對關鍵數據鏡像,如對日志文件鏡像,而不是對整個數據庫進行鏡像。

     

    6. 緩存

    Apache提供了自己的緩存模塊,也可以使用外加的Squid模塊進行緩存,這兩種方式均可以有效的提高Apache的訪問響應能力。在使用web語言開發的時候,各種語言基本都有自己的緩存模塊和方法。

     

    7. HTML靜態化

    靜態化的html頁面效率最高、消耗最小,所以我們可以盡可能使我們的網站上的頁面采用靜態頁面。但是對于大量內容并且頻繁更新的網站,我們無法全部手動去挨個實現,于是出現了我們常見的信息發布系統CMS,像我們常訪問的各個門戶站點的新聞頻道,甚至他們的其他頻道,都是通過信息發布系統來管理和實現的,信息發布系統可以實現最簡單的信息錄入自動生成靜態頁面,還能具備頻道管理、權限管理、自動抓取等功能。

    除了門戶和信息發布類型的網站,對于交互性要求很高的社區類型網站來說,盡可能的靜態化也是提高性能的必要手段,將社區內的帖子、文章進行實時的靜態化,有更新的時候再重新靜態化也是大量使用的策略,像Mop的大雜燴就是使用了這樣的策略,網易社區等也是如此。同時,html靜態化也是某些緩存策略使用的手段,對于系統中頻繁使用數據庫查詢但是內容更新很小的應用,可以考慮使用html靜態化來實現,比如論壇中論壇的公用設置信息,這些信息目前的主流論壇都可以進行后臺管理并且存儲再數據庫中,這些信息其實大量被前臺程序調用,但是更新頻率很小,可以考慮將這部分內容進行后臺更新的時候進行靜態化,這樣避免了大量的數據庫訪問請求。

     

    8. CDN加速技術

    CDN的全稱是內容分發網絡。其是通過在現有的Internet中增加一層新的網絡架構,將網站的內容發布到最接近用戶的網絡邊緣,使用戶可以就近取得所需的內容,提高用戶訪問網站的響應速度。CDN網絡是在用戶和服務器之間增加Cache層,主要是通過接管DNS實現,將用戶的請求引導到Cache上獲得源服務器的數據。緩存服務器從實際IP地址得得到內容以后,一方面在本地進行保存,以備以后使用,另一方面把獲取的數據返回給客戶端,完成數據服務過程。【3】

    大家都知道APP應用其實是客戶端和服務器端共同來完成的功能。那么對于客戶端來說,可能就是一些界面進行優化,然后功能有些疊加。但是在服務器端,那就真的是要做到性能、架構有質的提升,需要的不止是技術。

     

    【1】 大型互聯網站解決高并發的常見策略 作者 新鋒

    【2】 知乎 作者牛浩帆 

    鏈接http://www.zhihu.com/question/20657269/answer/15763722

    【3】 linux社區 作者lindianli 

    鏈接http://www.linuxidc.com/Linux/2014-09/106451.htm


     

    相似問題

    相關經驗

    相關資訊

    相關文檔

  • sesese色