這篇文章要跟大家介紹的內容是關於淺談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到達上線。
- #如果腳本呼叫了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中文網其他相關文章!

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

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

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具