成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

node中創(chuàng)建服務進程

Apollo / 2274人閱讀

摘要:在模塊中有個函數(shù),通過可以執(zhí)行命令及其相關選項,同時提供了創(chuàng)建子進程的一些選項,其中選項則與我們的需求密切相關。在文件中設置了函數(shù),目的是避免父進程等待子進程退出。不同會話的進程無法通過通信,因此父子進程相隔離。

背景

在node工程部署中,常常涉及到三方:本地客戶端、跳板機和服務器(集群)。在通過git觸發(fā)gitlab hook腳本后,需要在跳板機中執(zhí)行相應的ssh命令執(zhí)行shell文件啟動node服務器,這需要使用一個常用的命令setsid,這樣當ssh命令執(zhí)行完畢shell退出后,node服務器仍正常運行,此時node服務進程就是一個最典型的daemon進程(后臺服務進程)。

那么,在node項目中,如何創(chuàng)建一個daemon進程呢?最簡單的方式,其實就是采用類似上文中介紹的方式:

require("child_process").exec("setsid node app.js >/dev/null 2>&1 &");

這樣可以通過執(zhí)行shell的方式實現(xiàn)daemon進程。不過本文的重點并不是介紹這種“命令行”的方式實現(xiàn)daemon進程,而且本文會詳細講述daemon進程的創(chuàng)建原理,且看下文。

目標

在當前業(yè)務中,之所以需要創(chuàng)建daemon進程就是為了保證中斷創(chuàng)建該進程的父進程(ctrl+c)或者父進程執(zhí)行完畢后并不影響daemon進程的執(zhí)行。下文介紹兩種實現(xiàn)方式,實現(xiàn)原理細節(jié)上有些出入。

下文中的所有討論都是在linux環(huán)境下進行。

實現(xiàn)一

在linux系統(tǒng)中,父進程創(chuàng)建出子進程,此時父進程若退出,此時子進程則變?yōu)楣聝哼M程,其ppid變?yōu)?,即成為init進程的子進程。在node環(huán)境下,如果不針對子進程的stdio做一些特殊處理父進程其實不會真正退出,而是直到子進程執(zhí)行完畢后再退出。之所以出現(xiàn)這種情況是由于node創(chuàng)建子進程時默認會通過pipe方式將子進程的輸出導流到父進程的stream中(childProcess.stdout、childProcess.stderr),提供在父進程中輸出子進程消息的能力。

因此,解決此種問題可給子進程的stdio重新賦值:

file: parent.js

let cp = require("child_process");
const sp = cp.spawn("node",["./c.js"],{
    stdio: [process.stdin,process.stdout,process.stderr]
});

setTimeout(()=>{console.log("parent out")},5000);

--------------
file: c.js

setTimeout(()=>{
    console.log("children exit");
},10000)

通過在parent.js中設置子進程的stdio為當前終端(其實繼承了父進程的stdio),這樣父進程在5s后退出,此時子進程的ppid變?yōu)?,10s后子進程退出。

上述實現(xiàn)只滿足“父進程正常退出,子進程成為守護進程”的情況,一旦通過“ctrl+c”的方式終端父進程,子進程仍會退出,這還是與node底層實現(xiàn)有關。默認“ctrl+c”觸發(fā)SIGINT信號,父進程接受信號后發(fā)送給子進程,如果子進程存在SIGINT偵聽函數(shù),則會執(zhí)行該函數(shù),否則執(zhí)行exit系統(tǒng)調用子進程退出。因此,如果要讓子進程在接收到SIGINT信號不退出,只需要不作處理即可:

file: c.js

process.on("SIGINT",function(){
    console.log("child sigint");
});

setTimeout(()=>{
    console.log("children exit");
},10000)

以上實現(xiàn),可以滿足我們最初指定的目標:“父進程退出或者中斷,子進程仍正常運行”。

實現(xiàn)二

node官方提供了創(chuàng)建daemon進程的相關API,如果不仔細閱讀文檔還真不容易發(fā)現(xiàn)該特性。在child_process模塊中有個spawn函數(shù),通過spawn可以執(zhí)行shell命令及其相關選項,同時spawn提供了創(chuàng)建子進程的一些選項,其中“detached”選項則與我們的需求密切相關。

detached選項可以讓node原生幫我們創(chuàng)建一個daemon進程,設置datached為true可以創(chuàng)建一個新的session和進程組,子進程的pid為新創(chuàng)建進程組的組pid,這與setsid起到相同的作用。此時的子進程已經(jīng)和其父進程屬于兩個session,因此父進程的退出和中斷信號不會傳遞給子進程,子進程不會接受到父進程的中斷信號自然也不會退出。當父進程結束之后,子進程變?yōu)楣聝哼M程從而被init進程接收,ppid設置為1。

file: parent.js

let cp = require("child_process");
const sp = cp.spawn("node",["./c.js"],{
    detached: true,
    stdio: [process.stdin,process.stdout,process.stdout]
});

sp.unref();
setTimeout(()=>{console.log("parent out")},5000);

----------------------
file: c.js

setTimeout(()=>{
    console.log("children exit");
},100000)

此時,c.js文件并未設置SIGINT事件偵聽函數(shù),在父進程中斷后仍會正常運行,正是由于其和父進程分屬于兩個session。

在parent.js文件中設置了sp.unref()函數(shù),目的是“避免父進程等待子進程退出”。那么為何會出現(xiàn)上述情況呢?這與node的事件循環(huán)有關,讓父進程的事件循環(huán)排除對ChildProcess子進程對象的引用,可以使父進程多帶帶退出。

總結

為什么上文介紹的兩個方法都可以實現(xiàn)daemon進程呢?這還得回到系統(tǒng)層面進行分析。在linux系統(tǒng)創(chuàng)建一個daemon進程需要幾個步驟:

父進程創(chuàng)建子進程,父進程退出,讓子進程成為孤兒進程,ppid=1

通過setsid命令或函數(shù)在子進程中創(chuàng)建新的會話和進程組

設置當前目錄

設置文件權限,并關閉父進程繼承打開的fd

所謂會話和進程組,則是在linux多任務多用戶下的概念。不同會話的進程無法通過通信,因此父子進程相隔離。而執(zhí)行setsid命令則讓子進程有了新的特性:

子進程脫離父進程所在的session控制,兩者獨立存在互不影響

子進程脫離父進程所在的進程組

子進程脫離原先的命令行終端,終端退出不影響子進程

下面再回顧方法一方法二的區(qū)別,發(fā)現(xiàn)方法一其實并不是真正的daemon進程,只是通過偵聽相關中斷信號并設置nop函數(shù)(不執(zhí)行默認的中斷行為)保證子進程繼續(xù)運行而已;而方法二則是標準的deamon進程創(chuàng)建方式,優(yōu)先使用!

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/91714.html

相關文章

  • 基于Dubbo+ZooKeeper的分布式服務的實現(xiàn)

    摘要:調用流程服務容器負責啟動,加載,運行服務提供者。服務提供者在啟動時,向注冊中心注冊自己提供的服務。注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者。這就是分布式服務注冊中心的由來。 Dubbo是什么 一款分布式服務框架 高性能和透明化的RPC遠程服務調用方案。這里簡單介紹一下RPC,所謂RPC就是遠程過程調用,全稱為Romate Proce...

    warkiz 評論0 收藏0
  • 基于Dubbo+ZooKeeper的分布式服務的實現(xiàn)

    摘要:調用流程服務容器負責啟動,加載,運行服務提供者。服務提供者在啟動時,向注冊中心注冊自己提供的服務。注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者。這就是分布式服務注冊中心的由來。 Dubbo是什么 一款分布式服務框架 高性能和透明化的RPC遠程服務調用方案。這里簡單介紹一下RPC,所謂RPC就是遠程過程調用,全稱為Romate Proce...

    enda 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<