👜

Node-REDでworker_threadsを使用する

2023/11/07に公開

はじめに

Node-REDでworker_threadsが利用できるか試した際の記録です。
(Docker上のNode-REDで検証)

Node-REDでworker_threadsが必要になった際にご活用ください。

検証環境

  • Node.js: 18.18.1
  • Node-RED: 3.1.0

Node-REDからworker_threadsを使ってみる

1. workerの処理を作成する

はじめにNode-REDから呼び出すworkerの処理を作成しておきます。
下記のようなスクリプトを作成し、Node-REDから読込み可能なディレクトリに配置します。
(今回はNode-REDのルートディレクトリ上に配置しています。)

worker.js
const { parentPort } = require("worker_threads");

// Node-REDからのメッセージを取得
parentPort.on("message", async msg =>{
	
	// Node-REDからのメッセージを表示
	console.log(msg.payload);
	
	// msg.payloadに値を設定
        msg.payload = "I am worker!!!";

        // Node-REDへmsgオブジェクトを返却
        parentPort.postMessage(msg);
   
});

2. Node-RED上でfunctionノードを配置

続いて、Node-RED上にfunctionノードを配置し、worker_threadsの設定を行っていきます。

functionノードを配置

3. worker_threadsモジュールの読込み

functionノードの設定タブにてworker_threadsモジュールを設定します。(インポート名は任意)

worker_threadsモジュールの読込み

4. workerからデータを受信する

functionノードの初期化処理タブにて下記のようにworkerからmsgオブジェクトを受け、msgオブジェクトを後続のノードへ送出する処理を記載します。

読込みを行うjsファイル(workerでの処理を記載したファイル)はNode-REDのルートディレクトリからの相対パスか絶対パスで指定します。

また、生成したworkerオブジェクトはコードタブや終了処理タブでも扱えるようにコンテキストへ保持します。

workerからデータを受信する

初期化処理
const { Worker } = workerThreads;
const worker = new Worker("./workers.js");

// workerからのメッセージを待機
worker.on("message", workerMsg => {
    // workerから送信されたmsgオブジェクトを送出
    node.send(workerMsg);
});

// コンテキストにworkerを保持
context.set("worker", worker);

5. workerへデータを送信する

functionノードのコードタブを下記のように記載し、workermsgオブジェクトを送信します。

workerへデータを送信する

コード
// コンテキストからworkerを取得
const worker = context.get("worker");

// workerへmsgオブジェクトを送出
worker.postMessage(msg);

// workerからの返却値を送出するためmsgの返却を抑止
return null;

6. 動作確認

下記のようにinjectノードとdebugノードを繋げて、動作確認します。

injectノードではpayloadに適当な文字列を設定し、debugノードではpayloadを表示させています。

実行するとworkerで処理されたメッセージが表示されていることが確認できます。

node-red

また、コンソールでは下記のようにworker.jsに記載した値が出力されていることが確認できます。

console

おわりに

勉強も兼ねてNode-REDでworker_threadsが利用できないかと思い実装してみましたが、
ちょっとでもworker側でエラーが発生するとNode-REDもまるごと落ちてしまうので、
使い所が難しいかなと感じました。

Discussion