![](/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.