<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          高并發(fā)下的服務器架構(gòu)演變

          共 2872字,需瀏覽 6分鐘

           ·

          2021-04-12 20:49

          在如今的網(wǎng)絡環(huán)境下,高并發(fā)的場景無處不在,特別在面試如何解決高并發(fā)是一個躲不過的問題,即使生產(chǎn)環(huán)境達不到那么高的qps但是也應該給自己留條后路來應對日后可能發(fā)生的高并發(fā)場景,不用匆忙的加班加點的進行重構(gòu)。

          在應對日常高并發(fā)場景常常會有這么幾個方法:

          • 集群&負載均衡SLB

          • 讀寫分離&分庫分表

          • 緩存

          • 異步隊列(RabbitMQ)

          • 分布式系統(tǒng)、微服務    

            接下來就由淺入深分別來介紹下這幾個方法是怎么應用到服務器并且解決高并發(fā)的,首先我們先來看下最原始的也是最簡單的服務器與應用程序關(guān)系。

           圖1

            如圖1所示在一臺服務器上承載了數(shù)據(jù)庫、文件系統(tǒng)、應用程序的所有功能,這就導致即使低qps的情況下服務器的內(nèi)存或者cpu占比都非常高,用過sqlserver的同僚們都知道為了達到最高效快速的數(shù)據(jù)查詢、存儲及運算支持sql server默認會盡可能的占用內(nèi)存及CPU來達到自己的目的,從而導致我們的應用程序在處理一些運算或者請求量相對升高時應用程序就會變得非常慢,這時候我們就該考慮升級我們現(xiàn)有的服務器了,當然最高效也是最便捷的方式是升級硬件(cpu、內(nèi)存、硬盤),這也是最容易達到瓶頸的畢竟一臺服務的硬件也是有瓶頸的而且費用也是相當相當高昂的,一般情況下我們會選擇我們最開始提到解決高并發(fā)方法中分布式來升級我們圖1的單一服務器系統(tǒng)架構(gòu)。

           圖2

            如圖2所示我們由一臺服務器轉(zhuǎn)為三臺服務器互相協(xié)作的方式來處理每次請求,這也是簡單的分布式系統(tǒng)每臺服務器各司其職再也不會發(fā)生單一應用占用大量cpu或內(nèi)存的情況導致請求變得緩慢,但是就圖2而言的服務器架構(gòu)的承載能力也是非常有限的,當請求量上升后可能就扛不住宕機了。

            一般這時候我們就要分析發(fā)生宕機的原因,從圖2便知只有服務器A或者服務器B最有可能出現(xiàn)問題,根據(jù)以往的經(jīng)驗在請求量升高時數(shù)據(jù)庫會承載絕大部分的壓力,如果數(shù)據(jù)庫崩了那么整個應用就會處于不可用的狀態(tài),那么為了緩解數(shù)據(jù)庫的壓力,我們很自然的就會想到利用緩存,這也是高并發(fā)場景下最常用也是最有效最簡單的方案,利用好緩存能讓你的系統(tǒng)的承載能力提示幾倍甚至十幾倍幾十倍。熟悉二八原則的同僚們都知道80%請求的數(shù)據(jù)都集中在20%的數(shù)據(jù)上,雖然有些夸張但是意思就是這么個意思。緩存又分為本地緩存和分布式緩存,本著分布式的原則,我們一般都會選用分布式緩存同時也是為后期做分布式集群打下基礎(chǔ)。

          圖3

            如圖3所示在圖2的基礎(chǔ)上增加了一臺緩存服務器D來儲存我們的緩存數(shù)據(jù),一般我們會采用redis來存放緩存數(shù)據(jù),至于memcache現(xiàn)在應用的頻率是非常低的?,F(xiàn)在當請求到達應用程序時會優(yōu)先訪問緩存服務器D,若存在緩存數(shù)據(jù)就直接返回給客戶端如果不存在緩存數(shù)據(jù)才會去數(shù)據(jù)庫獲取數(shù)據(jù)返回給客戶端同時將數(shù)據(jù)保存到緩存服務器D設置緩存失效時間這樣下次請求時就不用到數(shù)據(jù)庫查詢數(shù)據(jù)了從而達到減輕數(shù)據(jù)庫壓力的目的。雖然緩存能抵擋大部分的請求,但是我們也要做好防止緩存擊穿、穿透和雪崩的問題來提升系統(tǒng)的穩(wěn)定性。

            隨著業(yè)務量的增多和繁多的業(yè)務種類圖3的系統(tǒng)架構(gòu)也會慢慢達到瓶頸支撐不住多樣化的業(yè)務需求,這時候我們就應該采用集群的方式來達到負載均衡的目的,將請求平均的分散到多臺服務器來拓展應用程序的承載能力。

           圖4

            如圖示4所示由服務器A-1、服務器A-2共同承載用戶的請求來提高系統(tǒng)的承載能力也就是我們最開始說到集群,出現(xiàn)集群的地方必然少不了負載均衡,圖4我們由nginx來實現(xiàn)請求的分發(fā)來達到負載均衡的目的。在設計圖3的架構(gòu)的時候我們有說到本地緩存,如果是采用本地緩存而不是分布式緩存那么系統(tǒng)架構(gòu)就存在一個比較大的缺陷,因為一個請求過來是由nginx區(qū)分發(fā)的如果我們再用本地緩存那么在在服務器A-1和服務器A-2上可能存在大量相同的本地緩存這樣就得不償失了容易造成服務器資源的浪費嚴重的還會拖累服務器的性能,利用分布式緩存的好處在于我們不管有多少個應用服務器所有的緩存都是共享的。

            圖4的服務器架構(gòu)應該是目前中小型應用中最常用的,而且系統(tǒng)的整體承載能力也相當不錯,不過隨著業(yè)務的發(fā)展流量與日俱增,圖3的服務器架構(gòu)也很難保證系統(tǒng)的穩(wěn)定,特別是日常流量峰值的一些時段圖3的系統(tǒng)可能時常會面臨奔潰的危險,這時候就要重新分析各服務器的壓力承載情況了,顯而易見最可能出現(xiàn)問題的就是數(shù)據(jù)庫服務器,終于要對數(shù)據(jù)庫下手了,當下最有效的方法就是就寫分離,還是遵循二八原則80%的數(shù)據(jù)操作都是查詢操作。

           

          圖5

            如圖5所示在圖4的基礎(chǔ)上由單一的數(shù)據(jù)庫變?yōu)橹鲝臄?shù)據(jù)庫從庫負責數(shù)據(jù)的查詢操作主庫負責數(shù)據(jù)增刪改操作,但請求操作主庫后主庫將操作日志執(zhí)行到從庫達到主從數(shù)據(jù)一致的目的,但是主從分離后不可能避免的一個問題就是主從數(shù)據(jù)一致性會有延遲,數(shù)據(jù)同步延遲的問題只能盡可能的減小數(shù)據(jù)延遲的時間,但對一些時效性非常高或者不能容忍數(shù)據(jù)延遲的請求只能做一些妥協(xié),這類操作的crud都在主庫上操作這樣就避免數(shù)據(jù)延遲的問題,對一些對于數(shù)據(jù)時效性不那么嚴格的請求可以將這部分的查詢操作由從庫去承載,對于主從數(shù)據(jù)庫個人以為和應用集群是一樣的可以理解為集群數(shù)據(jù)庫只不過在請求的分發(fā)上制定了規(guī)則(主庫處理更新、從庫處理查詢)。

          圖6

            如圖6將一些不屬于核心業(yè)務的功能模塊從應用服務中剝離出來降低服務的時延提高服務的吞吐量,這些類似日志、郵件/短信通知、監(jiān)控等等都丟到隊列中由單獨的服務從隊列中獲取數(shù)據(jù)進行處理??赡芤恍┩艂儠氲接卯惒降姆椒ㄈヌ幚磉@些方法,但是當有大量請求時這些異步處理會占用一部分服務器的性能同時異步也會增加程序的復雜度,所以用消息隊列的方式可能應該是比較優(yōu)的一種方法。

            當然隊列不僅僅是如圖6所示起到一種日志收集、通知、服務解耦的作用,很多時候會用隊列來應對一些特定場景(秒殺)來達到限流的防御性目的。

             如圖7,應對一些秒殺活動場景下,我們可以優(yōu)先預估服務的處理處理能力然后創(chuàng)建令牌隊列的容量同時開啟服務器J的創(chuàng)建令牌服務勻速的將令牌放入令牌隊列,如果隊列滿了就丟棄。當秒殺請求到達網(wǎng)關(guān)時由網(wǎng)關(guān)先到令牌隊列獲取令牌再請求分發(fā)到對應的服務,如果令牌沒有了說明已經(jīng)達到了服務的處理上限,可直接返回秒殺失敗防止服務被壓垮,達到限流的目的。

            圖8可能是和我一樣的菜鳥同僚們能馬上想到的一種隊列的服務架構(gòu),請求到達網(wǎng)關(guān)后直接丟到消息隊列中由對應的服務去消費,執(zhí)行完成后通過rpc通知網(wǎng)關(guān)將結(jié)果返回給前端,如果請求超時或者隊列滿了可以直接返回請求失敗,但是圖8這種方式請求鏈比較長影響響應的時間同時異步處理會增加服務的復雜度,所以圖7這種方式會更加合適一些。


          喜歡,在看



          瀏覽 107
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  超碰免费天天操天天干 | 色情视频在线观看免费 | 麻豆 天美 蜜桃 91 | 亚洲热情在线播放 | 成人一区二区三区四区五区91电影 |