淺談node.js中高並發與分散式叢集的內容
這篇文章要跟大家介紹的內容是關於淺談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:1 2 |
|
- Event Loop 將同步的執行poll queue裡的callback(新的I/O事件),直到queue為空或執行的callback到達上線。
- #如果腳本呼叫了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
#由於timer需要從紅黑樹中取出定時器來判斷時間是否到了,時間複雜度為O(lg(n)),故如果想立即非同步執行一個事件,最好不要用setTimeout(func, 0) 。而是使用 process.nextTick() 來完成。
- 分散式Node架構
- 我所了解的Node叢集架構主要分為以下幾個模組:
按我的理解整理了一副圖:
- ##當然,這應該是比較理想狀態下的架構方式。因為雖然 Redis 的讀/寫相當快,但這是因為將資料儲存在記憶體池裡,並在記憶體上進行相關操作。
這對伺服器的記憶體負荷是相當高的,所以通常我們還是會在架構中加入Mysql,如下圖:
- 先解釋一下這張圖:
當用戶資料到來時,先將資料寫入Mysql,Node 需要資料時再去Redis 讀取,若沒有找到再去Mysql 裡面查詢想要的數據,並寫入Redis,下次使用時就可以直接去Redis 裡面查詢了。
加入Mysql 相較於只在Redis 裡讀/寫的好處有: (1)避免了短期內無用的資料寫入Redis,佔用內存,減輕Redis 負擔
(2)在後期需要對資料進行特定查詢、分析的時候(例如分析營運活動用戶漲幅),SQL關係查詢能提供很大的幫助- 當然在應對短時間大流量寫入的時候,我們也可以直接將資料寫入Redis,以達到快速儲存資料、增加伺服器應對流量能力的目的,等流量下去了再單獨將資料寫入Mysql。 簡單介紹完了大體的架構組成,接下來我們來細看每個部分的細節:
流量接入層所做的就是對所有接受的流量進行處理,提供了以下服務:
- 流量緩衝
- #超時偵測
- #與使用者建立連線逾時
- 讀取使用者body逾時
- Nginx(負載平衡、調度) -> Node集群-> Redis(同步狀態)
- 流量接入層
- 分流與轉送
讀取後端回應頭逾時
寫入回應逾時
與使用者長連線逾時
##叢集健康檢查/隔離壞點伺服器
- 隔離壞點伺服器並嘗試修復/重啟,直到該伺服器恢復正常
- 失敗重試機制
- 在請求轉送到某叢集某機器上,返回失敗後,將該請求轉送到該叢集的別的機器,或是跨叢集的機器上進行重試
連線池/會話保持機制
(2)編寫高效能查詢語句,與Redis、Mysql 交互,提高查詢效率
(3)透過Redis 同步叢集裡各個Node 服務的狀態
(4)透過硬體管理平台,管理/監控實體機器的狀態、管理IP位址等(其實這部分工作放在這一層感覺不妥,但我也不知道應該放在哪一層。。。)
(當然這部分我只是粗淺地列列條目,還是需要時間來累積、深入理解)
資料庫層
這一層主要的工作是:
# (1)建立Mysql 並設計相關頁、表格;建立必要的索引、外鍵,提升查詢便利性
(2)部署redis 並向Node 層提供對應介面
相關推薦:
以上是淺談node.js中高並發與分散式叢集的內容的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

由於最近剛開始負責物件儲存相關係統的建置與穩定性維運,作為一個「物件儲存」的新手,需要加強這塊的學習。由於公司目前採用MinIO來建構公司的對象儲存體系,後續我會逐步將自己關於MinIO的學習經驗分享出來,歡迎大家持續關注。本文主要是介紹如何在測試環境中建構MinIO,這也是建構MinIO學習環境最基本的步驟。 1.準備實驗環境使用OracleVMVirtualBox虛擬機,安裝一個最小版本的Linux,然後添加4塊虛擬盤,用於充當MinIO的虛擬盤。實驗環境如下:接下來跟大家簡單介紹一下

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。
