回覆列表
  • 1 # IT實戰聯盟

    高併發伺服器邏輯處理瓶頸,如何解決?首先我們先了解什麼是併發!

    顧名思義,高併發就是在指定時間內,系統同時能夠處理大量的請求(連線數)。

    那麼如何衡量高併發呢?

    高併發衡量指標

    響應時間:系統對請求做出響應的時間,即一個http請求返回所用的時間;

    吞吐量:單位時間內處理的請求數量;

    QPS(TPS):每秒可以處理的請求數或事務數;

    併發使用者數:同時承載正常使用系統功能的使用者數量,即多少人同時使用,系統還能正常執行的使用者數量;

    根據上面衡量指標可以看到,提高併發能力必須解決如下幾個問題:

    如何提高併發連線數?

    那麼多的連線數怎麼進行業務處理?

    應用伺服器的處理水平又該怎麼提高?

    如何使用微服務架構提升高併發邏輯?

    彆著急,這麼多問題我們一個一個來分析解決!

    1)、如何提高併發連線數?

    如下圖所示,常規的單一網路連線模型只能1個連線對應1個執行緒,壓力都集中在記憶體,導致記憶體開銷非常大,肯定支撐的連線數有限!(直接掛掉)

    單一網路連線模型

    有道是業務寫的再好不如一臺高效能伺服器,這個鍋不一定要開發人員背的哦!!!伺服器的連線入口就那麼大(比如tomcat只有幾千的連線數),那麼處理的能力也只侷限於幾千。

    怎麼解決呢?選用合適的網路IO模型或者selector,透過使用一個執行緒輪詢或者事件觸發的方式,能支援幾萬甚至更多的連線數,再配合上nginx做負載就更完美了。

    2)那麼多的連線數怎麼進行業務處理?

    大家都知道nginx只是具有反向代理和負載均衡的功能,並不能處理具體的業務邏輯,不能擔當應用伺服器來使用。例如webSphere 、tomcat和jetty等,但是我們可以利用nginx將接受到的大量連線透過均衡的方式(輪詢,權重,hash)分配到不同的應用伺服器中進行業務處理!

    nginx負載

    3)應用伺服器的處理水平又該怎麼提高?

    要提高應用伺服器的處理水平就要了解自己的應用伺服器的瓶頸在哪裡,一般有兩個:

    資料庫本身:建立有效索引、讀寫分離、雙主互備、分庫分表(sharding-jdbc等實現)等策略,提高資料庫處理能力,減少壓力!

    結合記憶體資料庫:例如redid、memcached等,根據業務需要快取一些資料字典、列舉變數和頻繁使用資料等減少資料庫訪問次數,提升資料庫處理能力。

    web叢集架構圖

    如上圖web叢集架構圖所示:

    用nginx負載多臺應用伺服器;

    使用redid/memcached做業務快取;

    再加上資料庫叢集;

    組成了經典的web高併發叢集架構。

    程式碼中的業務邏輯:

    大家可以 參考阿里巴巴java開發手冊 中的開發規範來做就好了,總代來說少建立執行緒、少建立物件、少加鎖、防止死鎖、少建立執行緒、注意記憶體回收等策略,來提升程式碼效能。

    開發中可以採用前後端分離的架構模式,動靜分離、松耦合等提升前後端處理能力。

    4)如何使用微服務架構提升高併發邏輯?

    先看一下非常火的這張微服務架構圖:

    微服務架構圖

    主要包含11大核心元件,分別是:

    核心支撐元件

    服務閘道器Zuul

    服務註冊發現Eureka+Ribbon

    服務配置中心Apollo

    認證授權中心Spring Security OAuth

    服務框架Spring MVC/Boot

    監控反饋元件

    資料匯流排Kafka

    日誌監控ELK

    呼叫鏈監控CAT

    Metrics監控KairosDB

    健康檢查和告警ZMon

    限流熔斷和流聚合Hystrix/Turbine

    總結

    出來上述幾點解決高併發伺服器邏輯處理瓶頸外,還要考慮網路因素,例如採用CDN加速,將不同地點的請求分發到不同的服務叢集上,避免網路對速度的影響!

    總之,根據自身實際業務在合理範圍內儘可能的拆分,拆分以後同類服務可以透過水平擴充套件達到整體的高效能高併發,同時將越脆弱的資源放置在鏈路的越末端,訪問的時候儘量將訪問連結縮短,降低每次訪問的資源消耗。服務之間直接restful模型使用http呼叫,或者redis,kafka類的訊息中介軟體通訊。單個服務直接使用nginx做負載叢集,同時前後端分離,資料庫分庫分表等一整套分散式服務系統!

  • 2 # 會點程式碼的大叔

    下面就用我有限的知識和經驗,講一講高併發下的系統處理方案。

    1、大部分的系統應用,在建設初期都是單機應用,也就是一個應用伺服器加一個數據庫。

    2、當訪問量增多、併發量增加的時候,很多時候應用伺服器會先扛不住,通常我們解決這個問題的方法是:把應用伺服器做叢集部署,在前面搭建負載均衡,例如硬體負載F5、軟體負載Nginx。

    3、應用伺服器的壓力暫時解決,但是資料庫畢竟還是單臺,這時候我們可以在整體的架構中增加快取,已減少資料庫的壓力,最常見的是引入Redis,做叢集化的部署。

    4、業務繼續發展,併發量持續增多,單庫已經到了極限;這時候可以考慮分庫,常見的做法是對分庫欄位進行hash()%N,按照結果將資料路由到某一個分庫(分表)上。

    5、系統繼續發展,雖然應用是叢集化部署,但是畢竟是單個應用,並且隨著專案功能的增加,應用包也會越來越大,程式碼改動起來非常痛苦;這時候需要把應用拆分成多個應用,庫也各自獨立出來(說的很簡單,過程非常之痛苦,所以很多公司在初期,就是按照這個架構搭建):

    應用拆分成多個應用;

    應用之間的服務發現和呼叫,都需要服務註冊中心和閘道器的幫助;

    6、雖然應用和庫都拆開了,但是應用和應用質檢的耦合度依然非常高,所以通常會引入訊息佇列,例如各種MQ、Kafka,把一些實時性要求不是那麼高的服務解耦,比如交易完成時候給客戶發一條簡訊,那麼可以把待發送的簡訊放到訊息佇列中,簡訊平臺從訊息佇列中獲得訊息傳送簡訊。

    7、這時候應用的體量已經比較大了,部署、運維、查錯的難度加大,這時候需要引入很多元件,來幫助整個系統的穩定執行:

    認證中心:安全性的問題要注意,一個介面不是隨隨便便都能訪問的;

    限流:當併發量突增的時候,系統肯定會扛不住,這時候限制一部分流量的進入;

    監控中心:包括日誌監控、服務鏈路監控、流量監控等等;

    告警平臺:系統發生異常時,需要及時通知運維人員;

  • 中秋節和大豐收的關聯?
  • 如果趙匡胤死後傳位給兒子趙德芳,宋朝還會繼續“重文抑武”嗎?