Node.js學習筆記-04

這第九章也是個大重點

九、玩轉進程

Node在選型時決定在V8引擎之上構建,也就意味著它的模型與瀏覽器類似。
本章關于進程的介紹和討論將會解決如下兩個問題:

  1. 單進程單線程并非完美,如今CPU基本均是多核的,真正的服務器(非VPS)往往還有多個CPU。——如何充分利用多核CPU服務器?
  2. 由于Node執行在單線程上,一旦單線程上拋出的異常沒有捕獲,將會引起整個進程的崩潰。——如何保證進程的健壯性和穩定性?

9.1 服務模型的變遷

9.1.1 石器時代:同步

9.1.2 青銅時代:復制進程

9.1.3 白銀時代:多進程

9.1.4 黃金時代:事件驅動

9.2 多進程架構

面對單進程單線程對多核使用不足的問題,前人的經驗是啟動多進程即可。理想狀態下每個進程各自利用一個CPU,以此實現多核CPU的利用。
Node提供了 child_process 模塊,并且也提供了 child_process.fork()函數實現進程復制。

9.2.1 創建子進程

child_process 模塊提供了4個方法用于創建子進程。

spawn(); // 啟動一個子進程來執行命令。
exec(); // 啟動一個子進程來執行命令,與spawn()不同的是其接口不同,它有一個回調函數獲知子進程的狀況。
execFile(); // 啟動一個子進程來執行可執行文件。
fork(); // 與spawn()類似,不同點在于它創建的Node的子進程只需指定要執行的JavaScript文件模塊即可。
  • spawn()、exec()、execFile()不同點:后兩者創建時可以指定timeout屬性設置超時時間,一旦創建的進程超過設定的時間將會被殺死。
    這里的可執行文件是指可以直接執行的文件,如果是JavaScript文件通過execFile()運行,它的首行內容必須添加如下代碼:
#!/usr/bin/env node

盡管4種創建子進程的方式有些差別,但事實上后面三種方法都是spawn()的延伸應用。

9.2.2 進程間的通信

  • 創建子進程后為了實現父子進程之間的通信,父與子之間會創建IPC通道,通過IPC通道父子進程之間才能通過messagesend()傳遞消息。

  • IPC(Inter-Process Communication)進程間的通信。實現進程間通信的技術也有很多,如:命名管道、匿名管道、socket、信號量、共享內存、消息隊列、Domain Socket等。Node中實現IPC通道的是管道(pipe)技術。在Node中管道只是個抽象層面的稱呼,具體實現由 libuv 提供,在Windows下有命名管道(named pipe)實現,*nix系統則采用Unix Domain Socket實現,表現在應用層上的進程間通信只有簡單的 message 事件和 send() 方法。

  • 與網絡socket的行為比較類似,屬于雙向通信。不同的是他們在系統內核中就完成了進程間的通信,而不用經過實際的網絡層,非常高效。

  • 注意:只有啟動的子進程是Node進程時,子進程才會根據環境變量去連接IPC通道,對于其他類型的子進程無法實現進程間的通信,除非其他進程也按約定去連接這個已經創建好的IPC通道。

9.2.3 句柄傳遞

send(message, [sendHandle])方法除了能通過IPC發送數據外,還能發送句柄,第二個可選參數就是句柄。
什么是句柄?一種可以用來標識資源的引用,它的內部包含了指向對象的文件描述符。比如句柄可以用來標識一個服務器端socket對象、一個客戶端socket對象、一個UDP套接字、一個管道等。P252

發送句柄意味著什么?在前一個問題中,我們可以去掉代理這種方案,使主進程接收到 socket 請求后,將這個socket直接發送給工作進程,而不是重新與工作進程之間建立新的socket連接來轉發數據。文件描述符浪費的問題可以通過這樣的方式輕松解決。P253

1、句柄發送與還原
2、端口共同監聽

9.2.4 小結

至此,我們介紹了創建子進程、進程間通信的IPC通道實現、句柄在進程間的發送和還原、端口共用等細節。通過這些基礎技術,用child_process模塊在單機上搭建Node集群是件相當容易的事情。因此在多核CPU的環境下讓Node進程能夠充分利用資源不再是難題。

9.3 集群穩定之路

  • 性能問題。
  • 多個工作進程的存活狀態管理。
  • 工作進程的平滑重啟。
  • 配置或者靜態數據的動態重新載入。
  • 其他細節。

9.3.1 進程事件 P258

9.3.2 自動重啟 P259

9.3.3 負載均衡 P264

9.3.4 狀態共享 P265

9.4 Cluster 模塊

前文介紹了child process模塊中的大多數細節,以及如何通過這個模塊構建強大的單機集群。如果熟知Node,也許你會驚訝為何遲遲不談cluster模塊。上述提及的問題,Node在v0.8版本時新增的cluster模塊就能解決。在v0.8版本之前,實現多進程架構必須通過child process來實現,要創建單機Node集群,由于有這么多細節需要處理,對普通工程師而言是一件相對較難的工作,于是v0.8時直接引入了cluter模塊,用以解決多核CPU的利用率問題,同時也提供了較完善的API,用以處理進程的健壯性問題。
P267

9.4.1 Cluster 工作原理

事實上cluster模塊就是child process和net模塊的組合應用。cluster啟動時,如同我們在9.2.3節里的代碼一樣,它會在內部啟動TCP服務器,在cluster.fork()子進程時,將這個TCP服務器端socket的文件描述符發送給工作進程。如果進程是通過cluster.fork()復制出來的,那么它的環境變量里就存在NODE_UNIOUE_ID如果作進中存在listen()偵聽網絡端口的調用,它將拿到該文件描述符,通過SO_REUSEADDR端口重用,從而實現多個子進程共享端口。對于普通方式啟動的進程,則不存在文件描述符傳遞共享等事情。
在cluster內部隱式創建TCP服務器的方式對使用者來說十分透明,但也正是這種方式使得它無法如直接使用child_process那樣靈活。在cluster模塊應用中,一個主進程只能管理一組工作進程,如下圖所示。( 書中P268)
在cluster模塊應用中,一個主進程只能管理一組工作進程
對于自行通過child process來操作時,則可以更靈活地控制工作進程,甚至控制多組工作進程。其原因在于自行通過child process操作子進程時,可以隱式地創建多個TCP服務器使得子進程可以共享多個的服務器端socket。

9.4.2 Cluster 事件

對于健壯性處理,cluster模塊也暴露了相當多的事件。

  • fork:復制一個工作進程后觸發該事件。
  • online:復制好一個工作進程后,工作進程主動發送一條nline消息給主進程,主進程收到消息后,觸發該事件。
  • listening:工作進程中調用listen()(共享了服務器端Socket)后,發送一條listening消息給主進程,主進程收到消息后,觸發該事件。
  • disconnect:主進程和工作進程之間IPC通道斷開后會觸發該事件。
  • exit:有工作進程退出時觸發該事件。
  • setup:cluster.setupMaster()執行后觸發該事件。

這些事件大多跟child process模塊的事件相關,在進程間消息傳遞的基礎上完成的封裝這些事件對于增強應用的健壯性已經足夠了。

9.5 總結

盡管Node從單線程的角度來講它有夠脆弱的:既不能充分利用多核CPU資源,穩定性也無法得到保障。但是群體的力量是強大的,通過簡單的主從模式,就可以將應用的質量提升一個檔次。在實際的復雜業務中,我們可能要啟動很多子進程來處理任務,結構甚至遠比主從模式復雜,但是每個子進程應當是簡單到只做好一件事,然后通過進程間通信技術將它們連接起來即可。這符合Unix的設計理念,每個進程只做一件事,并做好一件事,將復雜分解為簡單,將簡單組合成強大。
盡管通過child_process模塊可以大幅提升Node的穩定性,但是一旦主進程出現問題所有子進程將會失去管理。在Node的進程管理之外,還需要用監聽進程數量或監聽日志的方式確保整個系統的穩定性,即使主進程出錯退出,也能及時得到監控警報,使得開發者可以及時處理故障。

個人心得:這章學得我腦殼痛,下次再重新學一遍然。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/37675.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/37675.shtml
英文地址,請注明出處:http://en.pswp.cn/news/37675.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

背上小書包準備面試之TypeScript篇

目錄 typescript是啥?與javascript的區別? typescript數據類型? typescript中枚舉類型?應用場景? typescript中接口的理解?應用場景? typescript中泛型的理解?應用場景&#xf…

輕薄的ESL電子標簽有哪些特性?

在智慧物聯逐漸走進千萬家的當下,技術變革更加日新月異。ESL電子標簽作為科技物聯的重要組成部分,是推動千行百業數字化轉型的重要技術,促進物聯網產業的蓬勃發展。在智慧零售、智慧辦公、智慧倉儲等領域,ESL電子標簽在未來是不可…

win11右下角圖標(網絡,音量,電量)點擊無反應問題,兩分鐘解決!

win11系統用的好好的,突然有一天任務欄右下角的常用三件套(網絡,音量,電量)左鍵單擊沒反應,無法方便的調節音量和連接wifi,如下圖所示,但是右鍵好用,不過不方便。網上查了…

嵌入式 C 語言程序數據基本存儲結構

一、5大內存分區 內存分成5個區,它們分別是堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區。 1、棧區(stack):FIFO就是那些由編譯器在需要的時候分配,在不需要的時候自動清除的變量的存儲區。里面的變量通常是局部變量、函數參數等。 ?…

【Windows API】獲取卷標、卷名

1、卷->卷標 使用FindFirstVolume()和FindNextVolume()函數體系,枚舉系統所有卷(Volume)的例子,然后獲取卷標、卷類型。這個方式可以枚舉出沒有驅動器號(卷標)的卷。 int TestMode1() {HANDLE hVolume…

Failed to connect to bitbucket.org port 443

瀏覽器可以訪問bitbucket,但是在終端或者sourcetree上死活無法進行pull, push等操作。 Root Cause:“【翻】【墻】軟件”使用了http proxy,所以也得為git設置相同的http proxy。 所以,解決方法是: 1,查看“…

網絡系統架構演變

1.系統架構演變 隨著互聯網的發展,網站應用的規模不斷擴大。需求的激增,帶來的是技術上的壓力。系統架構也因此不斷的演進、升級、迭代。從單一應用,到垂直拆分,到分布式服務,到SOA,以及現在火熱的微服務架…

【Django】無法從“django.utils.encoding”導入名稱“force_text”

整晚處理 Django 的導入錯誤。 我將把它作為提醒,希望處于相同情況的人數會減少。 原因 某些軟件包版本不支持Django 4 請看下表并決定Django和Python的版本 方案 如果出現難以響應,或者更改環境麻煩,請嘗試以下操作 例如出現以下錯誤 …

云計算的發展前景怎么樣

云計算是當前科技領域中最受關注的領域之一,它的出現改變了傳統的計算模式,使得企業和個人能夠更加便捷地訪問和使用計算資源。隨著云計算技術的不斷發展,它的前景也變得更加光明。 以下是云計算的發展前景: 云計算的市場份額將繼續增長:根據市場研究機構的報告,云計算的市場份…

vfuhyuuy

Sublime Text is an awesome text editor. If you’ve never heard of it, you shouldcheck it out right now. I’ve made this tutorial because there’s no installer for the Linux versions of Sublime Text. While that’s not a real problem, I feel there is a clean…

通過版本號控制強制刷新瀏覽器或清空瀏覽器緩存

背景介紹 在我們做 web 項目時,經常會遇到一個問題就是,需要 通知業務人員(系統用戶)刷新瀏覽器或者清空瀏覽器 cookie 緩存的情況。 而對于用戶而言,很多人一方面不懂如何操作,另一方面由于執行力問題&am…

Android descendantFocusability 屬性

view 焦點問題處理 作用 通過該屬性可以指定viewGroup和其子View到底誰獲取焦點, 直接在viewGroup上使用就行。 屬性值 屬性值含義beforeDescendantsviewgroup會優先其子類控件而獲取到焦點afterDescendantsviewgroup只有當其子類控件不需要獲取焦點時才獲取焦點…

MFC創建和使用OCX控件

文章目錄 MFC建立OCX控件注冊OCX控件與反注冊使用Internet Explorer測試ocx控件OCX控件添加方法OCX控件添加事件Web使用OCX控件MFC使用OCX控件使用OCX控件調用ocx的功能函數對ocx的事件響應OCX控件調試工具tstcon32.exe加載ocx控件使用tstcon32.exe調試ocxMFC建立OCX控件 新建…

【ChatGPT 指令大全】怎么使用ChatGPT來輔助知識學習

目錄 概念解說 簡易教學 深度教學 教學與測驗 解釋一個主題的背后原理 總結 在當今信息時代,互聯網的快速發展為我們獲取知識提供了前所未有的便利。而其中,人工智能技術的應用也為我們的學習和交流帶來了新的可能性。作為一種基于自然語言處理的人…

ORA-01704: string literal too long

這是在做數據遷移的時候,將mysql庫中的數據整理成Oracle腳本,接著在客戶端運行sql腳本插入數據時碰到的問題。明顯就是文本太長了導致的報錯,但是實際上設置的字段是可以支持這么長的文本數據的。 解決方案 直接寫程序導出導入數據&#xff0…

Postgresql 基礎使用語法

1.數據類型 1.數字類型 類型 長度 說明 范圍 與其他db比較 Smallint 2字節 小范圍整數類型 32768到32767 integer 4字節 整數類型 2147483648到2147483647 bigint 8字節 大范圍整數類型 -9233203685477808到9223203685477807 decimal 可變 用戶指定 精度小…

rust學習-tokio::time

示例 use std::time::Duration; use tokio::{task, time::interval};#[tokio::main] async fn main() {let mut interval interval(Duration::from_secs(1));let handle task::spawn(async move {loop {interval.tick().await;println!("tick");}});handle.await.…

【大數據】一些基本概念

一、數據庫、數據倉庫、數據湖 1.什么是數據庫 (Database, DB) 數據庫是指長期儲存在計算機中的有組織的, 可共享的數據集合 就是存儲數據的倉庫 數據庫有三個特點: 永久存儲, 有組織, 可共享 數據庫是一種結構化數據存儲技術,用于存儲和管理有組織的數據。數據庫…

微信小程序云開發快速入門(2/4)

前言 我們對《微信小程序云開發快速入門(1/4)》的知識進行回顧一下。在上章節我們知道了云開發的優勢以及能力,并且我們還完成了碼仔備忘錄的本地版到網絡版的改造,主要學習了云數據庫同時還通過在小程序使用云API直接操作了云數…

SciencePub學術| 智能計量類重點SCIE征稿中

SciencePub學術 刊源推薦: 智能計量類重點SCIE征稿中!信息如下,錄滿為止: 一、期刊概況: 智能計量類重點SCIE 【期刊簡介】IF:2.0-2.5,JCR3區,中科院4區; 【版面類型】正刊&#…