Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung verschiedener Implementierungsmethoden der Prozesskommunikation im Knoten

Detaillierte Erläuterung verschiedener Implementierungsmethoden der Prozesskommunikation im Knoten

青灯夜游
青灯夜游nach vorne
2021-12-14 19:04:514816Durchsuche

KnotenWie kommuniziere ich zwischen Prozessen? Der folgende Artikel wird Ihnen helfen, die Kommunikationsmethoden von Node-Prozessen zu verstehen und diese Kommunikationsmethoden in Node zu implementieren. Ich hoffe, er wird Ihnen hilfreich sein!

Detaillierte Erläuterung verschiedener Implementierungsmethoden der Prozesskommunikation im Knoten

Die Kommunikation umfasst tatsächlich alle Entwicklungsebenen, darunter die Kommunikation zwischen Client und Server, die RPC-Kommunikation, die gegenseitige Kommunikation zwischen verschiedenen Modulen während des Entwicklungsprozesses und die Kommunikation zwischen dem Hauptelektronenprozess und dem Rendering-Prozess zwischen Knoten usw.;

Dieser Artikel versucht hauptsächlich, die Kommunikationsmethoden, Verwendungsszenarien, Implementierung usw. von nodejs (Single-Threaded, Multi-Threaded, Multi-Process) zusammenzufassen.

So implementieren Sie die Kommunikation:

1. Socket (Socket);

3.

4. Nachrichtenwarteschlange (Nachrichtenwarteschlange);

Schauen wir uns an, wie diese Kommunikationsmethoden im Knoten implementiert werden )

Unter einer einzelnen Maschine (einzelner Thread im Client, mehrere Threads in einem einzelnen Prozess, mehrere Prozesse auf einem einzelnen Server) ist die Kommunikation über Speicherfreigabe die gebräuchlichste Methode.

Shared Memory (Speicherfreigabe) – einzelner Thread

Auf Betriebssystemebene wird der gesamte Thread-Speicher im Prozess gemeinsam genutzt, Voraussetzung ist jedoch, dass die Zugriffsadresse des Speichers bekannt sein muss.

Aber auf der Sprachebene (Knoten- oder v8-Implementierungsebene) berühren wir die Speicherverwaltung nicht direkt, sondern führen indirekt Speicheroperationen über die von v8 bereitgestellte Syntax/API aus. v8 bietet uns drei Möglichkeiten, den Speicher zu teilen (vielleicht sollte man ihn besser als gemeinsam genutzte Variablen bezeichnen):

globale Variablen

,

lokale Variablen, gemeinsam genutzte Parameter

(Aufruf durch Teilen);

v8 überträgt zuerst den Code, bevor er ausgeführt wird Nachdem es durch die Estree-Spezifikation in einen abstrakten Syntaxbaum konvertiert wurde, wird es dann interpretiert, kompiliert und ausgeführt. Es gibt einen Bereich im abstrakten Syntaxbaum (siehe meinen anderen Artikel über den abstrakten Syntaxbaum), und das Lesen des Speichers erfolgt über Bezeichner (Variablenbenennung) Suche Ebene für Ebene zurück. Wenn Sie also etwas Speicher zwischen zwei Methoden teilen müssen, können Sie ihn in ihrem gemeinsamen Bereich erstellen.

Gemeinsamer Speicher (Speicherfreigabe) – Multithreading In entweder der Client-Umgebung oder der Knotenumgebung können wir Multithreading implementieren, und die beiden Methoden sind ähnlich (Knoten wird über worker_threads implementiert und die Browser wird durch Worker implementiert). Die gemeinsame Nutzung des Speichers wird hier hauptsächlich mit Hilfe der Speicheroperations-API (SharedArrayBuffer) erreicht. Schauen wir uns zunächst ein Beispiel für die Browser-Implementierung an:

// 主线程
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

Gemeinsamer Speicher (Speicherfreigabe) – Multiprozess

Da der Speicher nach dem Start der Prozesse nicht mehr voneinander gelesen werden kann (Einschränkungen auf Systemebene), Speicherfreigabe zwischen Prozessen ist tatsächlich Dies wird durch das Öffnen eines neuen Abschnitts des gemeinsam genutzten Speichers erreicht. Allerdings unterstützt Node derzeit keinen Shared Memory und kann nur über Low-Level-Sprachen implementiert werden, wie etwa das in C++ implementierte Shared-Memory-Disruptor-Add-on-Plug-in (beschrieben in einem anderen Artikel).

2. Socket (Socket)

Socket ist in zwei Implementierungen unterteilt:

1. TCP-Socket; Konzept: TCP Socket ist die Zwischenabstraktionsschicht für die Kommunikation zwischen der Anwendungsschicht und der TCP/IP-Protokollfamilie. Es handelt sich um einen vom Betriebssystem bereitgestellten prozessübergreifenden Kommunikationsmechanismus. TCP Socket-Kommunikation sollte die häufigste Kommunikation in unserem sein Tägliche Entwicklung (C/S-Architektur) Eine der in unserer täglichen Entwicklung am häufigsten verwendeten Methoden ist die Verwendung verschiedener Protokolle auf Anwendungsebene (http, websocket, rpc, ftp usw.). Das http-Modul wird ebenfalls im Knoten implementiert auf dem Netzmodul.

Hinweis: Tatsächlich gehört UDP auch zur TCP-Schicht (bezieht sich nicht ausschließlich auf die TCP-Kommunikation, sondern die TCP/IP-Schicht in der Netzwerkkommunikationsschicht stellt das Modul „dgram“ zur Verfügung, um es zu implementieren, aber es gibt keins). Kontakt in tatsächlichen Anwendungen bestanden, daher kein weiteres Verständnis.

net



Im Knoten wird TCP Socket durch das Netzmodul implementiert. Das Netzmodul bietet hauptsächlich die folgenden Funktionen:

1. IPC-Unterstützung der oberen Ebene (eigentlich die Implementierung der Pipeline-Kommunikation). später) Beschreibung);

2, net.Server-Klasse;
TCP Socket适用于单机,C/S架构等.但UNIX Domain Socket只适用于单机。  
UNIX Domain Socket不需要经过一系列的网络中转(协议,分包,校验等等),性能更高,稳定性更好。

3, net.Socket-Klasse;

// 服务端通过net.createServer创建服务,会返回net.Server对象,可以通过返回值进行各种事件监听,端口监听
const net = require('net')

net.createServer((server => {
  server.end(`hello world!\n`)
})).listen(3302, () => {
  console.log(`running ...`)
})

UNIX Domain Socket

UNIX Domain Socket erstellt einen Dateideskriptor, und die Kommunikation zwischen verschiedenen Prozessen erfolgt durch Lesen und Schreiben Sie diesen Dateideskriptor für die Kommunikation (kann in den Erstellungsprozess und andere Prozesse unterteilt werden, und die gegenseitige Kommunikation zwischen anderen Prozessen kann durch den Erstellungsprozess als Transit erfolgen). z.B.

const net = require('net')
const socket = net.createConnection({port: 3302})

socket.on('data', data => {
  console.log(data.toString())
})
3. Pipeline

Pipeline-Kommunikation wird in zwei Typen unterteilt: nicht benannte Pipes und benannte Pipes.

Unbenannte Pipes werden auf die gleiche Weise wie UNIX-Domänen-Sockets implementiert und kommunizieren durch die Erstellung von Dateideskriptoren.

Named Pipes kommunizieren über feste Dateideskriptoren:

"\\\\.\\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'是一般结束进程的信号,还有更多其他的信号参考 [标识](https://blog.csdn.net/houjixin/article/details/71430489)

但这里的前提是你需要获取到被终止的进程pid,更多pid的内容可阅读我之前关于进程的文章。

五、Message queue(消息队列)

一开始我以为是redis,各种MQ之类的基于TCP的消息队列。但其实是操作系统内的消息队列,node暂时没有提供相关的上层接口,需要更底层实现,e.g. svmq

更多node相关知识,请访问:nodejs 教程!!

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung verschiedener Implementierungsmethoden der Prozesskommunikation im Knoten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen