首頁 > web前端 > js教程 > 主體

淺談node.js中高並發與分散式叢集的內容

不言
發布: 2018-08-01 15:54:46
原創
2835 人瀏覽過

這篇文章要跟大家介紹的內容是關於淺談node.js中高並發與分散式集群的內容,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

Node特性:高並發

在解釋node為什麼能夠做到高並發之前,不妨先了解node的其他幾個特性:

單執行緒

我們先來明確一個概念,即:node是單執行緒的,這一點與JavaScript在瀏覽器中的特性相同,並且在node中JavaScript主執行緒與其他執行緒(例如I/O執行緒)是無法共享狀態的。

單一執行緒的好處就是:

  • #不需要像多執行緒一樣去關注執行緒之間的狀態同步問題

  • 沒有執行緒切換所帶來的開銷

  • 沒有死鎖存在

當然單執行緒也有許多壞處:

  • 無法充分利用多核心CPU

  • 大量運算佔用CPU會導致應用程式阻塞(即不適用CPU密集型)

  • 錯誤會引起整個應用的退出

不過在今天看來,這些壞處都已經不再是問題或得到了適當的解決:

(1) 創建進程or 細分實例

關於第一個問題,最直白解決方案就是使用child_process核心模組或cluster:child_process 和net 組合應用程式。我們可以透過在一台多核心伺服器上建立多個進程(通常使用fork操作)來充分利用每個核心,不過要處理好進程間通訊問題。

另一個方案是,我們可以將實體機器分割成多台單核心的虛擬機,並透過pm2等工具,管理多台虛擬機形成一個叢集架構,高效運作所需服務,至於每台機器間的通訊(狀態同步)我這裡先按下不表,在下文的Node分散式架構中再做詳細說明。

(2) 時間片輪轉

關於第二點,我跟小夥伴討論過後認為可以透過時間片輪轉方式,在單線程上模擬多線程,適當減少應用阻塞的感覺(雖然這種方法不會真的像多執行緒那樣節約時間)

(3) 負載平衡、壞點監控/隔離

至於第三點,我跟小夥伴們也討論過,認為主要的痛點就在於node不同於JAVA,它所實現的邏輯是以非同步為主的。

這就導致了node無法像JAVA一樣方便地使用 try/catch 來捕獲並繞過錯誤,因為無法確定非同步任務會何時傳回異常。而在單線程環境下,繞不過錯誤意味著導致應用程式退出,重啟恢復的間隙會導致服務中斷,這是我們不願意看到的。

當然,在伺服器資源豐富的當下,我們可以透過 pm2 或 nginx 這些工具,動態的判斷服務狀態。在服務出錯時隔離壞點伺服器,將請求轉送到正常伺服器上,並重新啟動壞點伺服器以繼續提供服務。這也是Node分散式架構的一部分。

非同步I/O

你可能會問,既然node是單執行緒的,事件全部在一個執行緒上處理,那不是應該效率很低、與高並發相悖嗎?

恰恰相反,node的效能很高。原因之一是node具有非同步I/O特性,每當有I/O請求發生時,node會提供給該請求一個I/O執行緒。然後node就不管這個I/O的操作過程了,而是繼續執行主執行緒上的事件,只需要在該請求返回回呼時在處理即可。也就是node省去了許多等待請求的時間。

這也是node支援高並發的重要原因之一

實際上不光是I/O操作,node的絕大多數操作都是以這種非同步的方式進行的。它就像是組織者,無需事必躬親,只需要告訴成員們如何正確的進行操作並接受反饋、處理關鍵步驟,就能使得整個團隊高效運作。

事務驅動

你可能又要問了,node怎麼知道請求回傳了回調,又應該何時去處理這些回調呢?

答案是node的另一個特性:事務驅動,也就是主執行緒透過event loop事件循環觸發的方式來執行程式

##這是node支持高並發的另一個重要原因

圖解node環境下的Event loop:

   ┌───────────────────────┐
┌─>│        timers         │<p>poll階段:<strong></strong></p>當進入poll階段,並且沒有timers被呼叫的時候,會發生下面的情況:<p></p>(1)如果poll隊列不為空:<p></p>
登入後複製
  • Event Loop 將同步的執行poll queue裡的callback(新的I/O事件),直到queue為空或執行的callback到達上線。

(2)如果poll隊列為空:

  • #如果腳本呼叫了setImmediate(), Event Loop將會結束poll階段並且進入到check階段執行setImmediate()的回呼。

  • 如果腳本沒有被setImmediate()調用,Event Loop將會等待回呼(新的I/O事件)被加入到佇列中,然後立即執行它們。

當進入到poll階段,並且呼叫了timers的話,會發生下面的情況:

  • 一旦poll queue是空的話,Event Loop會檢查是否timers, 如果有1個或多個timers時間已經到達,Event Loop將會回到timer階段並執行那些timer的callback(即進入到下一次tick)。

優先:

Next Tick Queue > MicroTask Queue

setTimeout、setInterval > setImmediate

淺談node.js中高並發與分散式叢集的內容

淺談node.js中高並發與分散式叢集的內容


淺談node.js中高並發與分散式叢集的內容#由於timer需要從紅黑樹中取出定時器來判斷時間是否到了,時間複雜度為O(lg(n)),故如果想立即非同步執行一個事件,最好不要用setTimeout(func, 0) 。而是使用 process.nextTick() 來完成。

    分散式Node架構
  • 我所了解的Node叢集架構主要分為以下幾個模組:
    • Nginx(負載平衡、調度) -> Node集群-> Redis(同步狀態)
    • 按我的理解整理了一副圖:

    • ##當然,這應該是比較理想狀態下的架構方式。因為雖然 Redis 的讀/寫相當快,但這是因為將資料儲存在記憶體池裡,並在記憶體上進行相關操作。
    • 這對伺服器的記憶體負荷是相當高的,所以通常我們還是會在架構中加入Mysql,如下圖:

    • 先解釋一下這張圖:

      當用戶資料到來時,先將資料寫入Mysql,Node 需要資料時再去Redis 讀取,若沒有找到再去Mysql 裡面查詢想要的數據,並寫入Redis,下次使用時就可以直接去Redis 裡面查詢了。

    • 加入Mysql 相較於只在Redis 裡讀/寫的好處有:
    • (1)避免了短期內無用的資料寫入Redis,佔用內存,減輕Redis 負擔

    • (2)在後期需要對資料進行特定查詢、分析的時候(例如分析營運活動用戶漲幅),SQL關係查詢能提供很大的幫助
  • 當然在應對短時間大流量寫入的時候,我們也可以直接將資料寫入Redis,以達到快速儲存資料、增加伺服器應對流量能力的目的,等流量下去了再單獨將資料寫入Mysql。

    簡單介紹完了大體的架構組成,接下來我們來細看每個部分的細節:
    • 流量接入層
    • 流量接入層所做的就是對所有接受的流量進行處理,提供了以下服務:

  • 流量緩衝

    • 分流與轉送
    • #超時偵測

  • #與使用者建立連線逾時

  • 讀取使用者body逾時

連線後端逾時

讀取後端回應頭逾時淺談node.js中高並發與分散式叢集的內容

寫入回應逾時

  • 與使用者長連線逾時

  • ##叢集健康檢查/隔離壞點伺服器

  • 隔離壞點伺服器並嘗試修復/重啟,直到該伺服器恢復正常
  • 失敗重試機制
  • 在請求轉送到某叢集某機器上,返回失敗後,將該請求轉送到該叢集的別的機器,或是跨叢集的機器上進行重試

  • 連線池/會話保持機制

#對於延遲敏感使用者使用連線池機制,減少建立連接的時間

###安全防護#############資料分析############當轉送到各個產品線後就到了負載層工作的時候了:將請求根據情況轉發到各地機房######################當然,這個平台並不止轉發這一個功能,你可以把它理解為一個大型的私有雲系統,提供以下服務:############文件上傳/服務線上部署############線上配置修改############設定定時任務#############線上系統監控/日誌列印服務############線上實例管理############鏡像中心#############等等...############Node叢集層######這一層主要的工作是:######(1)編寫可靠的Node 程式碼,為需求提供後端服務###

(2)編寫高效能查詢語句,與Redis、Mysql 交互,提高查詢效率

(3)透過Redis 同步叢集裡各個Node 服務的狀態

(4)透過硬體管理平台,管理/監控實體機器的狀態、管理IP位址等(其實這部分工作放在這一層感覺不妥,但我也不知道應該放在哪一層。。。)

(當然這部分我只是粗淺地列列條目,還是需要時間來累積、深入理解)

資料庫層

這一層主要的工作是:

# (1)建立Mysql 並設計相關頁、表格;建立必要的索引、外鍵,提升查詢便利性

(2)部署redis 並向Node 層提供對應介面

相關推薦:

vue如何使用axios請求後端資料

#對Vue中表單輸入綁定和元件基礎的分析

以上是淺談node.js中高並發與分散式叢集的內容的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!