我使用RabbitMQ在Node.js中实现RPC。
我遵循教程,我为每个客户端声明了相同的队列名称'rpc_client'以获得高权限,这里是调用服务器中的函数的client.js
:
const amqp = require('amqplib');
async function client(){
let args = process.argv.slice(2);
let corr = generateUuid();
let num = parseInt(args[0]);
try {
let conn = await amqp.connect('amqp://127.0.0.1');
let ch = await conn.createChannel();
let q = await ch.assertQueue('rpc_client');
console.log(' [x] Requesting fib(%d)', num);
console.log(q.queue)
await ch.consume(q.queue,msg=>{
if (msg.properties.correlationId == corr) {
console.log(' [.] Got %s', msg.content.toString());
ch.ack(msg)
setTimeout(function() { conn.close(); process.exit(0) }, 5500);
}
},{noAck:false});
ch.sendToQueue('rpc_server',
new Buffer(num.toString()),
{ correlationId: corr, replyTo: q.queue });
} catch(err){
console.error(err);
}
}
function generateUuid() {
return Math.random().toString() +
Math.random().toString() +
Math.random().toString();
}
client();
但是我发现当我一次运行多个客户端时,后一个客户端将不会运行消耗回调(从服务器获取答案并打印它),直到前一个客户端的连接关闭为止。例如第二个客户端将得到答案并打印出来,其连接将在5500毫秒内关闭,第二个客户端必须等待第一个关闭,它将打印答案然后再等待5500毫秒关闭。
那么为什么要这样呢?因为队列可以平行消耗两个工人的两个按摩。
这是server.js
:
async function server(){
try {
let conn = await amqp.connect('amqp://127.0.0.1');
let ch = await conn.createChannel();
process.once('SIGINT',()=>conn.close());
let q = await ch.assertQueue('rpc_server');
ch.prefetch(1);
console.log(' [x] Awaiting RPC requests');
await ch.consume(q.queue,msg=>{
let n = parseInt(msg.content.toString());
console.log(" [.] fib(%d)", n);
let r = fibonacci(n);
ch.sendToQueue(msg.properties.replyTo,
new Buffer(r.toString()),
{correlationId: msg.properties.correlationId});
ch.ack(msg);
},{noAck:false});
} catch(err) {
console.error(err);
}
}
server();
function fibonacci (n , ac1 = 1 , ac2 = 1) {
if( n <= 1 ) {return ac2};
return fibonacci (n - 1, ac2, ac1 + ac2);
}
答案 0 :(得分:0)
如果队列名称相同,则它是相同的队列。不是两个具有相同名称的队列。在这种情况下,客户端按顺序而不是平行地获取消息是有意义的。
因此尝试使用不同的队列名称,它应该可以工作。
答案 1 :(得分:0)
据我所知,您必须将预取更改为大于1的数字。
basic.qos(预取)方法可让您限制未确认的数量 消费时在频道(或连接)上显示消息。
所以问题出在这个参数上。您的频道将等待,直到您的第一个请求得到处理并得到确认。