站長資訊網
        最全最豐富的資訊網站

        詳解node中進程通信的幾種實現方式

        node進程間如何通信?下面本篇文章帶大家了解node進程的通信方式,以及在node中如何實現這些方式的通信,希望對大家有所幫助!

        詳解node中進程通信的幾種實現方式

        通信其實涵蓋開發的各個層面,常見的有客戶端和服務端通過各種通信協議進行通信,RPC通信,開發過程中各個模塊之間的相互通信,electron主進程和渲染進程之間的通信等等;

        本文主要是嘗試總結下nodejs(單線程,多線程,多進程)通信的方式,使用場景,實現等。

        通信的實現方式

        一般進程通信的實現方式如下:

        1、Shared Memory(內存共享);

        2、Socket(套接字);

        3、管道(非命名管道Pipe, 命名管道FIFO);

        4、Signal(信號);

        5、Message queue(消息隊列);

        下面我們看下在node中如何實現這些方式的通信

        一、Shared Memory(內存共享)

        單機下(客戶端內單線程,單進程里多線程,單臺服務器內多進程),通過內存共享實現通信的方式最為常見。

        Shared Memory(內存共享)-單線程

        從操作系統層面來看,進程內所有線程內存都是共享的,但前提是需要知道內存的訪問地址。

        但從語言層面(node或者說是v8的實現層面),我們沒有直接接觸內存的管理,而是間接從v8提供的語法/api進行內存操作。v8提供三種方式給我們共享內存(也許叫共享變量更恰當):全局變量, 局部變量, 共享傳參(call by sharing);

        v8在執行代碼之前會先將代碼通過Estree規范轉化為抽象語法樹后再進行解釋編譯執行,在抽象語法樹中(關于抽象語法樹可查看我另外一篇文章)是有scope的,而內存讀取是通過標志符(變量命名)逐級往上回溯查找。所以如果你需要在兩個方法之間共享某個內存,可以在他們共同的作用域下進行創建。

        Shared Memory(內存共享)-多線程

        在客戶端環境或node環境,我們都可以實現多線程,兩者方式也類似(node通過worker_threads實現,瀏覽器通過Worker實現)。這里的內存共享主要是借助內存操作的api(SharedArrayBuffer)實現的。先看下瀏覽器實現的例子:

        // 主線程 const buffer = new SharedArrayBuffer(1024) const typedArr = new Int16Array(buffer) const newWorker = new Worker('./worker.js')  typedArr[0] = 20  newWorker.postMessage(buffer) newWorker.onmessage= (data) => {     console.group('[the main thread]');     console.log('Data received from the main thread: %i', typedArr[0]);     console.groupEnd(); } // 子線程 addEventListener('message', ({ data }) => {   const arr = new Int16Array(data)    console.group('[the worker thread]')   console.log('Data received from the main thread: %i', arr[0])   console.groupEnd()   arr[0] = 18      postMessage('Updated') }) // 結果 [the worker thread]   Data received from the main thread: 20 [the main thread]   Data received from the main thread: 18

        Shared Memory(內存共享)-多進程

        因為進程啟動后內存是無法相互讀取的(系統層面的限制),進程之間的內存共享實際是通過新開辟一段shared memory實現的。但node暫時沒有支持shared memory,只能通過低級語言來實現,例如: c++實現的 shared-memory-disruptor addon插件(另外文章介紹)。

        二、Socket(套接字)

        Socket 分兩種實現:
        1、TCP Socket;
        2、UNIX Domain Socket;
        兩者的主要區別如下:

        TCP Socket適用于單機,C/S架構等.但UNIX Domain Socket只適用于單機。   UNIX Domain Socket不需要經過一系列的網絡中轉(協議,分包,校驗等等),性能更高,穩定性更好。

        TCP Socket

        概念: TCP Socket是應用層與TCP/IP協議族通信的中間抽象層,是一種操作系統提供的進程間通信機制;

        TCP Socket通信應該是我們日常開發(C/S架構)中最常見的通信方式之一,在我們日常開發中最常見的就是各種應用層協議(http,websocket,rpc,ftp等)的使用,node中http模塊也是基于net模塊實現的。

        注:其實UDP也屬于TCP分層(并不是嚴格的指TCP通信,而是網絡通信層中的TCP/IP層),node有提供'dgram'模塊來實現,但在實際應用中沒有接觸過,所以不進行了解。

        net

        在node中,TCP Socket是由net模塊實現的,net模塊主要提供了以下功能:

        1、上層的IPC支持(實際上是管道通信的實現,后面管道通信再詳細說明);

        2、net.Server類;

        // 服務端通過net.createServer創建服務,會返回net.Server對象,可以通過返回值進行各種事件監聽,端口監聽 const net = require('net')  net.createServer((server => {   server.end(`hello world!n`) })).listen(3302, () => {   console.log(`running ...`) })

        3、net.Socket類;

        const net = require('net') const socket = net.createConnection({port: 3302})  socket.on('data', data => {   console.log(data.toString()) })

        UNIX Domain Socket

        UNIX Domain Socket是通過創建一個文件描述符,不同進程之間的通信通過讀寫這個文件描述符進行通信(可以分為創建進程和其他進程,其他進程之間的相互通信可以通過創建進程作為中轉)。e.g.

        // 創建進程 const net = require('net') const unixSocketServer = net.createServer(server => {   server.on('data', data => {     console.log(`receive data: ${data}`)   }) })  unixSocketServer.listen('/tmp/test', () => {   console.log('listening...') }) // 其他進程 const net = require('net') const socket = net.createConnection({path: '/tmp/test'})  socket.on('data', data => {   console.log(data.toString()) }) socket.write('my name is vb') // 輸出結果 listening... receive data: my name is vb

        三、管道

        管道通信分兩種,非命名管道和命名管道。
        非命名管道的實現方式和UNIX Domain Socket一樣,都是通過創建文件描述符進行通信。
        命名管道是通過固定的文件描述符進行通信:

        "\\.\pipe\" + PIPE_NAME;

        源碼可參考stackoverflow(https://stackoverflow.com/questions/11750041/how-to-create-a-named-pipe-in-node-js)
        目前理解的管道通信和UNIX Domain Socket實現基本一致,只是管道通信規范了讀寫權限,半雙工通信,UNIX Domain Socket更加自由一些。

        四、Signal(信號)

        Signal是操作系統在終止進程前給進程發送的信號。在node中可以通過process.kill(pid, signal)/child_process.kill(pid, signal)接口實現,e.g.

        // 要被終止的http守護進程 const Koa = require('koa') const app = new Koa()  app.listen(3004, () => {   console.log(`process pid is : ${process.pid}`) // process pid is : 75208 }) // 操作進程 process.kill(75208, 'SIGHUP') // 'SIGHUP'是一般結束進程的信號,還有

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 亚洲а∨天堂久久精品9966| 国产成人久久精品一区二区三区| 日韩精品久久久久久免费| 3级黄性日本午夜精品| 久久精品亚洲中文字幕无码麻豆 | 国产中文在线亚洲精品官网| 国产精品乱码高清在线观看 | 久久久无码精品午夜| 视频二区国产精品职场同事| 久久精品无码专区免费青青| 久久久久国产精品麻豆AR影院| 柠檬福利精品视频导航| 久久精品亚洲日本波多野结衣| 亚洲?V乱码久久精品蜜桃| 国产精品自在线拍国产手机版| 欧美精品免费在线| 久久99国产精品二区不卡| 国产精品人成在线播放新网站 | 久久精品人人做人人爽97| 亚洲精品成人久久久| 国产午夜亚洲精品国产成人小说| 久久se精品一区精品二区| 99精品视频在线观看re| 69久久精品无码一区二区| 999在线视频精品免费播放观看| 精品不卡一区二区| 国产精品美女久久久久| 精品熟女少妇av免费久久| 少妇人妻偷人精品无码视频| 无码国产精品一区二区免费模式 | 国产成人亚洲精品青草天美| 精品无码国产一区二区三区51安| 亚洲国产精品无码久久一区二区 | 久久九九精品99国产精品| 精品无人码麻豆乱码1区2区| 久久综合精品国产二区无码| 无码精品黑人一区二区三区 | 亚洲精品成人片在线播放| 中文字幕无码精品三级在线电影| 在线观看91精品国产网站| 亚洲麻豆精品国偷自产在线91|