RabbitMQ,在节点

时间:2019-02-21 07:05:06

标签: node.js rabbitmq message-queue

我正在创建一个简单的聊天应用程序

  1. 可以有多个用户和多个聊天室。
  2. 每个聊天室可以容纳多个用户。
  3. 服务器启动时将建立RabbitMQ连接。
  4. 当用户连接到服务器时,在RabbitMQ通道中打开套接字连接。
  5. 从客户端(用户)通过套接字发送消息时,rabbitmq通道使用特定的路由密钥将其推送到交换机。
  6. 使用时,如果套接字处于活动状态,则通过它发送并确认它。如果没有,请不要确认并重新排队。

{

//Creating a new connection
amqp.connect('amqp://localhost', (err, conn) => {

conn.createChannel(function(err, ch) {

ch.assertExchange(exchangeName, 'direct', { durable: false });
const routingKey = // some routing key;    

wss.on('connection', (ws, req) => {
  // Creating a new queue for the user
  ch.assertQueue('', { exclusive: true, persist: true, durable: true }, (err, q) => {
    // Binds with the routing key
    ch.bindQueue(q.queue, exchangeName, routingKey);

    ch.consume(q.queue, (msg) => {
      if (ws.readyState === 1) {
        ch.ack(msg);
        ws.send(` [-] Received ${msg.content.toString()}`);
      } else {
        // What will come here so that it will be requeued to a new queue with the same routing id?
      }
    }, { noAck: false });
  });

  ws.on('message', (message) => {
    ch.publish(exchangeName, routingKey, new Buffer(message));
    console.log(`[x] Sent ${message} to the exchange with routingKey ${routingKey}`);
  });
}) 

当所有用户都在与服务器连接的插槽中时,这可以正常工作。我要实现的是当套接字连接丢失给用户时,如果他错过了基于路由密钥(特定于用户)的消息,那么只要他重新连接到其他队列,他就应该能够再次接收到这些消息。我认为这是可能的,因为如果在任何队列中未确认消息,则可以交换消息。但不确定如何实现。

2 个答案:

答案 0 :(得分:1)

让我解决几个误解...

  

我要实现的是当套接字连接死于   用户以及他是否错过了基于路由密钥的消息(特定于   用户),那么他应该能够在任何时候再次收到这些消息   他重新连接到另一个队列

您正在使用互斥队列。 根据定义,当这些队列的关联连接和通道消失时,这些队列将被删除。删除队列后,这些队列中的消息就会丢失。

  

我认为这是可能的,因为如果   它不会在任何队列中得到确认。

RabbitMQ不是这样工作的。交换用于路由消息,而队列则是存储消息的地方。

以下评论不正确:

  

如果user1和user2在不同的主机上,则显然他们应该建立   不同的渠道。 “渠道”就像连接一样,如果   两个通道使用相同的队列,它们可以接收相同的消息。

user1user2位于不同的主机上,并且可能在不同的进程中运行,它们各自将建立自己的连接和通道。两个使用者将从不从同一队列中接收相同的消息。

回到最初的问题,您需要将队列声明为-排他性和持久性,并以这样的方式命名队列:当您的应用程序重新连接时,该应用程序将连接到同一队列队列。这样,应用程序可以使用队列中剩余的消息。

有多种方法让RabbitMQ为您删除documented的未使用队列。


注意: RabbitMQ团队监视rabbitmq-users mailing list,并且有时仅在StackOverflow上回答问题。

答案 1 :(得分:0)

消费者应该使用带有确认的消息来消费消息,如果消息传递给使用者并且在断开消费者连接之前未得到确认,那么RabbitMQ将重新传递它。您可以从RabbitMQ doc获取更多详细信息。

在您的情况下,当套接字连接断开时,您应强制关闭通道,然后RabbitMQ将知道这些消息应重新发送。

为确保消息在服务器重新启动后仍然存在,请将交换设置为“持久”:  ch.assertExchange(exchangeName, 'direct', { durable: false });