ZeroMQ PUSH/PULL 通信不能通过 IPC 工作,但可以通过 TCP 工作
ZeroMQ PUSH/PULL communication doesn't work via IPC, but it works via TCP
这是一本名为“Node.js 8 the Right Way”的书中的一个任务。
您可以在下面看到它:
这是我的解决方案:
'use strict';
const zmq = require('zeromq');
const cluster = require('cluster');
const push = zmq.socket('push');
const pull = zmq.socket('pull');
const cores_num = require('os').cpus().length;
let workers_num = 0;
push.bind('tcp://127.0.0.1:9998');
pull.bind('tcp://127.0.0.1:9999');
// push.bind('ipc://push.ipc');
// pull.bind('ipc://pull.ipc');
if (cluster.isMaster) {
for (let j = 0; j < cores_num; j++) {
cluster.fork();
}
cluster.on('online', (worker) => {
console.log(`Worker with pid ${worker.process.pid} is created!`);
});
pull.on('message', (data) => {
const response = JSON.parse(data.toString());
if (response.type === 'ready') {
if (workers_num >= 0 && workers_num < 3) {
workers_num++;
if (workers_num == 3) {
console.log('Ready!');
for (let i = 0; i < 10; i++) {
push.send(JSON.stringify({
type: 'job',
data: `This message has id ${i}`
}));
}
}
}
} else if (response.type === 'result') {
console.log(data.toString());
}
});
} else {
const worker_push = zmq.socket('push');
const worker_pull = zmq.socket('pull');
worker_pull.connect('tcp://127.0.0.1:9998');
worker_push.connect('tcp://127.0.0.1:9999');
// worker_pull.connect('ipc://push.ipc');
// worker_push.connect('ipc://pull.ipc');
worker_push.send(JSON.stringify({
type: 'ready'
}));
worker_pull.on('message', data => {
const request = JSON.parse(data);
if (request.type === 'job') {
console.log(`Process ${process.pid} got message ${request.data}`);
worker_push.send(JSON.stringify({
type: 'result',
data: `This message is a response from process ${process.pid}`,
time: Date.now()
}));
}
});
}
正如你所看到的,它只在PUSH/PULL套接字和工人通过TCP通信时有效,但我想知道它不能通过IPC工作的原因。
更新(参考:下面的条件 4 "pathname must be writeable"):
希望大家帮我解决问题
I want to know the reason why it doesn't work via IPC.
使用 ipc://
transport-class 使用 ZeroMQ 可扩展正式通信原型并获得 .bind()/.connect()
-ed
1) inter-process 传输使用 system-dependent IPC 机制在本地进程之间传递消息。 inter-process 传输目前 仅在提供 UNIX 域套接字的操作系统上实现。
2) .bind()
端和.connect()
端都需要在某个可行的地址:
相遇
push.bind( 'ipc://push.sock' ); // will never meet its counterparty
// ------------------(--|||://^v^v^v^v^v^v^v )
worker_pull.connect( 'ipc:///tmp/push.sock'); // if used other ipc://-address
3) 如果任何第二个进程绑定到一个已被进程绑定的端点,这将成功并且第一个进程将失去其绑定。在此行为中,ipc://
transport-class 与 tcp://
或 inproc://
transport-class 不一致。
4) endpoint-address 路径名 必须 可由进程写入。当端点以 / 开头时,例如 ipc:///pathname,这将是一个绝对路径名。如果端点指定的目录不存在,则绑定失败。
5) 当endpoint-address路径名以@
开头时,应使用抽象命名空间。抽象命名空间独立于文件系统,如果一个进程试图绑定一个已经被进程绑定的端点,它将失败。有关详细信息,请参阅 unix(7)。
6) ipc://
transport-class 路径名的最大大小取决于操作系统。在 Linux 上,包括“ipc://
”前缀在内的最大值为 113 个字符(实际路径名为 107 个字符)。
7) 当在 zmq_bind()
中使用了 wild-card * 端点规范时,调用者 应该 使用从 [=41= 获得的真实端点]ZMQ_LAST_ENDPOINT
套接字选项,使用 zmq_unbind()
.
将此端点与套接字解除绑定
几件事:
您的 IPC 路径不正确:
您有 ipc://push.ipc
(2 个斜杠),您确实需要 ipc:///push.ipc
协议是 ipc://
然后你需要文件路径 /push.ipc
文件权限:
你的进程是否有写入根目录的权限?除非你是运行宁作为根我认为不会。
我会将路径更改为类似 /tmp/push.ipc
的路径,在大多数系统中所有用户都可以写入该路径。
在这种情况下,您的 url 应该是:
ipc:///tmp/push.ipc
分叉
我根本不使用节点,但根据我对其他语言的了解,我认为整个程序在不同的 process/thread.
中再次 运行
在这种情况下,不是每个工作人员都试图再次 bind()
,因为套接字 creation/bind 代码在 if (cluster.isMaster) {
之外
我觉得应该是这样的
if (cluster.isMaster) {
const push = zmq.socket('push');
const pull = zmq.socket('pull');
push.bind('ipc://push.ipc');
pull.bind('ipc://pull.ipc');
....
}
这是一本名为“Node.js 8 the Right Way”的书中的一个任务。 您可以在下面看到它:
这是我的解决方案:
'use strict';
const zmq = require('zeromq');
const cluster = require('cluster');
const push = zmq.socket('push');
const pull = zmq.socket('pull');
const cores_num = require('os').cpus().length;
let workers_num = 0;
push.bind('tcp://127.0.0.1:9998');
pull.bind('tcp://127.0.0.1:9999');
// push.bind('ipc://push.ipc');
// pull.bind('ipc://pull.ipc');
if (cluster.isMaster) {
for (let j = 0; j < cores_num; j++) {
cluster.fork();
}
cluster.on('online', (worker) => {
console.log(`Worker with pid ${worker.process.pid} is created!`);
});
pull.on('message', (data) => {
const response = JSON.parse(data.toString());
if (response.type === 'ready') {
if (workers_num >= 0 && workers_num < 3) {
workers_num++;
if (workers_num == 3) {
console.log('Ready!');
for (let i = 0; i < 10; i++) {
push.send(JSON.stringify({
type: 'job',
data: `This message has id ${i}`
}));
}
}
}
} else if (response.type === 'result') {
console.log(data.toString());
}
});
} else {
const worker_push = zmq.socket('push');
const worker_pull = zmq.socket('pull');
worker_pull.connect('tcp://127.0.0.1:9998');
worker_push.connect('tcp://127.0.0.1:9999');
// worker_pull.connect('ipc://push.ipc');
// worker_push.connect('ipc://pull.ipc');
worker_push.send(JSON.stringify({
type: 'ready'
}));
worker_pull.on('message', data => {
const request = JSON.parse(data);
if (request.type === 'job') {
console.log(`Process ${process.pid} got message ${request.data}`);
worker_push.send(JSON.stringify({
type: 'result',
data: `This message is a response from process ${process.pid}`,
time: Date.now()
}));
}
});
}
正如你所看到的,它只在PUSH/PULL套接字和工人通过TCP通信时有效,但我想知道它不能通过IPC工作的原因。
更新(参考:下面的条件 4 "pathname must be writeable"):
I want to know the reason why it doesn't work via IPC.
使用 ipc://
transport-class 使用 ZeroMQ 可扩展正式通信原型并获得 .bind()/.connect()
-ed
1) inter-process 传输使用 system-dependent IPC 机制在本地进程之间传递消息。 inter-process 传输目前 仅在提供 UNIX 域套接字的操作系统上实现。
2) .bind()
端和.connect()
端都需要在某个可行的地址:
push.bind( 'ipc://push.sock' ); // will never meet its counterparty
// ------------------(--|||://^v^v^v^v^v^v^v )
worker_pull.connect( 'ipc:///tmp/push.sock'); // if used other ipc://-address
3) 如果任何第二个进程绑定到一个已被进程绑定的端点,这将成功并且第一个进程将失去其绑定。在此行为中,ipc://
transport-class 与 tcp://
或 inproc://
transport-class 不一致。
4) endpoint-address 路径名 必须 可由进程写入。当端点以 / 开头时,例如 ipc:///pathname,这将是一个绝对路径名。如果端点指定的目录不存在,则绑定失败。
5) 当endpoint-address路径名以@
开头时,应使用抽象命名空间。抽象命名空间独立于文件系统,如果一个进程试图绑定一个已经被进程绑定的端点,它将失败。有关详细信息,请参阅 unix(7)。
6) ipc://
transport-class 路径名的最大大小取决于操作系统。在 Linux 上,包括“ipc://
”前缀在内的最大值为 113 个字符(实际路径名为 107 个字符)。
7) 当在 zmq_bind()
中使用了 wild-card * 端点规范时,调用者 应该 使用从 [=41= 获得的真实端点]ZMQ_LAST_ENDPOINT
套接字选项,使用 zmq_unbind()
.
几件事:
您的 IPC 路径不正确:
您有 ipc://push.ipc
(2 个斜杠),您确实需要 ipc:///push.ipc
协议是 ipc://
然后你需要文件路径 /push.ipc
文件权限:
你的进程是否有写入根目录的权限?除非你是运行宁作为根我认为不会。
我会将路径更改为类似 /tmp/push.ipc
的路径,在大多数系统中所有用户都可以写入该路径。
在这种情况下,您的 url 应该是:
ipc:///tmp/push.ipc
分叉
我根本不使用节点,但根据我对其他语言的了解,我认为整个程序在不同的 process/thread.
中再次 运行在这种情况下,不是每个工作人员都试图再次 bind()
,因为套接字 creation/bind 代码在 if (cluster.isMaster) {
我觉得应该是这样的
if (cluster.isMaster) {
const push = zmq.socket('push');
const pull = zmq.socket('pull');
push.bind('ipc://push.ipc');
pull.bind('ipc://pull.ipc');
....
}