![](/img/trans.png)
[英]Node.js|Worker Processes: How to verify two-way communication between a master and worker process
[英]In node.js, how to declare a shared variable that can be initialized by master process and accessed by worker processes?
我想要以下
這是我的代碼,顯然沒有達到我的目標。
var my_shared_var;
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Load a large table from file and save it into my_shared_var,
// hoping the worker processes can access to this shared variable,
// so that the worker processes do not need to reload the table from file.
// The loading typically takes 15 seconds.
my_shared_var = load('path_to_my_large_table');
// Fork worker processes
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
// The following line of code actually outputs "undefined".
// It seems each process has its own copy of my_shared_var.
console.log(my_shared_var);
// Then perform query against my_shared_var.
// The query should be performed by worker processes,
// otherwise the master process will become bottleneck
var result = query(my_shared_var);
}
我嘗試將大表保存到 MongoDB 中,以便每個進程都可以輕松訪問數據。 但是表太大了,即使有索引,MongoDB 也需要大約 10 秒才能完成我的查詢。 這太慢了,對於我的實時應用程序來說是不可接受的。 我也嘗試過 Redis,它將數據保存在內存中。 但是 Redis 是一個鍵值存儲,我的數據是一個表。 我還寫了一個 C++ 程序將數據加載到內存中,查詢時間不到 1 秒,所以我想在 node.js 中進行模擬。
如果我用幾句話翻譯您的問題,您需要與WORKER實體共享MASTER實體的數據。 使用事件可以非常輕松地完成:
從師父到工人:
worker.send({json data}); // In Master part
process.on('message', yourCallbackFunc(jsonData)); // In Worker part
從工人到大師:
process.send({json data}); // In Worker part
worker.on('message', yourCallbackFunc(jsonData)); // In Master part
我希望通過這種方式可以雙向發送和接收數據。 如果您發現它有用,請將其標記為答案,以便其他用戶也可以找到答案。 謝謝
您正在尋找共享內存, node.js不支持 。 您應該尋找替代方案,例如查詢數據庫或使用memcached 。
如果只讀訪問適用於您的應用程序,請嘗試使用我自己的共享內存模塊 。 它使用了mmap
,因此數據在訪問時加載,而不是一次性加載。 內存在機器上的所有進程之間共享。 使用它非常簡單:
const Shared = require('mmap-object')
const shared_object = new Shared.Open('table_file')
console.log(shared_object.property)
它為您提供了一個到字符串或數字的鍵值存儲的常規對象接口。 它在我的應用程序中超級快。
在node.js中,fork的工作方式與C ++不同。 它不是復制當前的進程狀態,而是運行新進程。 因此,在這種情況下,不共享變量。 每行代碼都適用於每個進程,但主進程將cluster.isMaster標志設置為true。 您需要為每個工作進程加載數據。 如果您的數據非常龐大,請小心,因為每個進程都有自己的副本。 我認為您需要在需要時立即查詢部分數據,或者如果您真的需要在內存中使用它,請等待。
你可以使用Redis。
Redis是一個開源的,BSD許可的,高級鍵值緩存和存儲。 它通常被稱為數據結構服務器,因為密鑰可以包含字符串,散列,列表,集,排序集,位圖和超級日志。
redis.io
這種方式可以“共享變量”; 它比@Shivam 呈現的方式更花哨。 但是,該模塊在內部使用相同的 API。 因此“共享內存”有點誤導,因為在集群中每個進程都是父進程的一個分支。 在 fork 時,進程內存在 OS 內存中復制。 因此,除了像 shm 設備或虛擬共享內存頁面(Windows)這樣的低級共享內存之外,沒有真正的共享內存。 我確實為 Node.js 實現了一個本機模塊,它使用本機共享內存(這是真正的共享內存),因為使用這種技術,兩個進程都直接從操作系統共享內存部分讀取。 但是,此解決方案在這里並不適用,因為它僅限於標量值。 您當然可以 JSON.stringify 並共享 JSON 序列化數據字符串,但解析/字符串化所消耗的時間對於大多數用例來說完全不理想。 (特別是對於較大的對象,使用標准庫實現對 JSON 的解析/字符串化變得非線性)。
因此,這個解決方案目前似乎是最有前途的:
const cluster = require('cluster');
require('cluster-shared-memory');
if (cluster.isMaster) {
for (let i = 0; i < 2; i++) {
cluster.fork();
}
} else {
const sharedMemoryController = require('cluster-shared-memory');
// Note: it must be a serializable object
const obj = {
name: 'Tom',
age: 10,
};
// Set an object
await sharedMemoryController.set('myObj', obj);
// Get an object
const myObj = await sharedMemoryController.get('myObj');
// Mutually exclusive access
await sharedMemoryController.mutex('myObj', async () => {
const newObj = await sharedMemoryController.get('myObj');
newObj.age = newObj.age + 1;
await sharedMemoryController.set('myObj', newObj);
});
}
這個問題是在 2012 年發布的,正好是 10 年前。 由於沒有其他答案提到它,Node.js 現在支持支持共享內存的工作線程<\/a>。
直接來自文檔:
工作者(線程)對於執行 CPU 密集型 JavaScript 操作很有用。 與 child_process 或 cluster 不同,worker_threads 可以共享內存。 他們通過傳輸 ArrayBuffer 實例或共享 SharedArrayBuffer 實例來做到這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.