我使用 PUB/SUB
ZeroMQ
模式。
系统包括Web服务器( Pub lisher),集群TCP服务器( Sub scribers)和外部应用程序(客户端,连接到TCP服务器)。
大量外部客户端连接到每个TCP服务器。每个外部客户端都有唯一的peerId
我在 Pub lisher中用作主题。出于某些管理目的,我将消息发送到TCP服务器(如删除对等,更改等)。但我还需要从TCP服务器向Web服务器发送消息(连接,断开连接,错误)。我没找到正确的方法怎么做。任何人都可以建议如何正确地做到这一点?
更新1
看起来使用 ROUTER
/ DEALER
模式是最方便的。
关于脚本的一些评论。
外部客户端连接到tcp服务器(集群)并在由唯一peerId
缓存的tcp服务器端tcp套接字上发送唯一peerId
。然后tcp服务器通过ZeroMQ套接字向Web服务器发送peerId
消息。 Web服务器通过envelope
缓存peerId
。每隔n
毫秒Web服务器将消息发送到随机对等方(生成'peerId')。 TCP Server收到这些消息,从缓存中获取正确的tcp套接字并将其发送给客户端。客户端计算消息计数,每n
毫秒将其发送到TCP服务器,TCP服务器通过ZeroMQ套接字将计数发送到WEB服务器。在Web服务器上,每个n
毫秒的已发送和已接收消息的数量都会打印在控制台上。
测试服务器部分的js脚本:
var cluster = require('cluster'),
zmq = require('zmq'),
net = require('net'),
zmqport = 'tcp://127.0.0.1:12345';
var count = 10;
var countPeers = 10000;
var interval = 1;
if (cluster.isMaster) {
for (var i = 0; i < count; i++) cluster.fork({
TCP_SERVER: 1
});
cluster.fork({
WEB_SERVER: 1
});
cluster.on('death', function (worker) {
console.log('worker ' + worker.pid + ' died');
});
} else {
if (process.env.TCP_SERVER) {
var sockets = Object.create(null);
var socket = zmq.socket('dealer');
socket.identity = 'process-' + process.pid;
socket.connect(zmqport);
socket.on('message', function (peerIdBuffer) {
var peerId = peerIdBuffer.toString();
if (typeof sockets[peerId] !== 'undefined') {
var buffer = new Buffer(4);
buffer.writeUInt32BE(1, 0);
sockets[peerId].write(buffer);
}
});
var server = net.createServer(function (tcpsocket) {
tcpsocket.on('data', function (data) {
if (!tcpsocket.peerId) {
var peerId = data.toString();
sockets[peerId] = tcpsocket;
tcpsocket.peerId = peerId;
return socket.send(['id', data]);
}
return socket.send(['count', data]);
});
});
server.listen('13333', '0.0.0.0');
} else {
var countMessagesSended = 0;
var countMessagesReceived = 0;
var socket = zmq.socket('router');
var clients = Object.create(null);
socket.bind(zmqport, function (err) {
if (err) throw err;
setInterval(function () {
for (var i = 0; i < countPeers; i++) {
var topic = Math.floor(Math.random() * countPeers) + '-peer';
if (typeof clients[topic] !== 'undefined') {
countMessagesSended++;
socket.send([clients[topic], topic]);
}
}
}, interval);
});
socket.on('message', function (envelope, messageId, data) {
switch (messageId.toString()) {
case "id":
clients[data.toString()] = envelope.toString();
break;
case "count":
countMessagesReceived += data.readUInt32BE(0);
break;
}
});
setInterval(function () {
console.log('%s messages have been sended, %s - received', countMessagesSended, countMessagesReceived);
countMessagesSended = 0;
countMessagesReceived = 0;
}, 5000);
}
}
为客户测试js脚本:
var cluster = require('cluster'),
net = require('net');
var count = 10;
if (cluster.isMaster) {
for (var i = 0; i < count; i++) cluster.fork({
CLUSTER: i
});
cluster.on('death', function (worker) {
console.log('worker ' + worker.pid + ' died');
});
} else {
var clientspernode = 1000;
var offset = parseInt(process.env.CLUSTER, 10);
for (var j = (offset) * clientspernode; j < (offset + 1) * clientspernode; j++) {
(function (j) {
var countMessages = 0;
var client = net.connect({
port: 13333,
host: '127.0.0.1'
}, function () {
client.write(j + '-peer');
});
client.on('data', function (buffer) {
countMessages += Math.ceil(buffer.length / 8);
});
client.on('error', function () {
});
setInterval(function () {
var buf = new Buffer(4);
buf.writeUInt32BE(countMessages, 0);
client.write(buf);
countMessages = 0;
}, 5000);
})(j);
}
}