Javascript Amqp、rabbit mq和socket.io重新连接到队列,即使客户端已关闭

Javascript Amqp、rabbit mq和socket.io重新连接到队列,即使客户端已关闭,javascript,socket.io,rabbitmq,node-amqplib,Javascript,Socket.io,Rabbitmq,Node Amqplib,我正在使用rabbitMQ和socket.io编写浏览器通知。我的配置工作正常,只有一个例外 当我和一个用户一起登录到我的系统时,它会创建一个通知UID userid队列,因为现在queueName由query oaraeter发送,一旦我解决了这个问题,我就会实现更多的模拟方法 如果我在另一个浏览器上与另一个用户登录,它将创建另一个队列通知UID seconduserid 如果我注销其中一个用户,队列将消失,因为它不持久 问题是,当我在另一个会话上刷新或加载另一个页面时,它会重新创建第二个队列

我正在使用rabbitMQ和socket.io编写浏览器通知。我的配置工作正常,只有一个例外

当我和一个用户一起登录到我的系统时,它会创建一个通知UID userid队列,因为现在queueName由query oaraeter发送,一旦我解决了这个问题,我就会实现更多的模拟方法

如果我在另一个浏览器上与另一个用户登录,它将创建另一个队列通知UID seconduserid

如果我注销其中一个用户,队列将消失,因为它不持久

问题是,当我在另一个会话上刷新或加载另一个页面时,它会重新创建第二个队列,即使没有发送参数queuename

server.js

client.js


有什么想法吗?

所以我解决了我的问题,这是一个范围可变的问题,把事情搞砸了。 让我解释一下我在做什么,也许这对某人有用

基本上,我正在尝试创建一个浏览器通知系统,这意味着我的应用程序向exchange发布一个包含主题、链接和消息等信息的通知对象

该交换是一个扇出users.notification.fanout,具有两个绑定的交换:users.direct类型和users.notification.store扇出类型

当生产者发布通知时,它会使用路由密钥通知UID userid向users.notification.fanout发送通知,其中userid是真实的用户id

通知对象同时指向users.direct和users.notification.store 最后一个有一个使用者,该使用者将通知写入数据库。如果用户未登录,第一个使用者将通知发布到浏览器

那么浏览器消费者是如何工作的呢

我使用了socket.io、node server和amqplib的经典组合

每次用户登录时,socket.io都会创建一个带有名称和路由密钥通知UID userid的队列,并将其绑定到users.direct exchange

与此同时,我在我的服务器上添加了https,所以与第一个版本相比,情况有所改变

你可以阅读评论来了解它的作用

所以我的server.js是

然后是我的client.js

var io=require'socket.io client'

$(document).ready(function () {

    var socket = io('https://myserver.com:8080/', {
        secure: true, // for ssl connections
        query:  { queueName: 'notification-UID-' + UID, token: JWTToken}, // params sent to server, JWTToken for authentication
        'sync disconnect on unload': true // Every time the client unload, socket disconnects
    });

    socket.on('notification', function (data) {
        // Do what you want with your data
        console.log(data);
    });
})
var io = require('socket.io-client');

$(document).ready(function () {

    var socket = io('http://myserver.it:8080/', {
         query:  { queueName: 'notification-UID-' + UID},
        'sync disconnect on unload': true,
        });

    socket.on('notification', function (data) {
        console.log(data);
    });
})
var amqp = require('amqp');
var fs = require('fs');
var app = require('express')();
// Https server, certificates and private key added
var https = require('https').Server({
    key: fs.readFileSync('/home/www/site/privkey.pem'),
    cert: fs.readFileSync('/home/www/site/fullchain.pem')},app);
var io = require('socket.io')(https);

// Used to verify if token is valid
// If not it will discard connection
io.use(function (socket, next) {
    var handshakeData = socket.handshake;
    // Here i will implement token verification
    console.log("Check this token: " + handshakeData.query.token);
    next();
});
// Gets the connection event from client
io.sockets.on('connection', function (socket) {
    // Connection log
    console.log("Socket Connected with ID: " + socket.id);
    // THIS WAS THE PROBLEM
    // Local variables for connections
    // Former i've put these variables outside the connection so at 
    // every client they were "overridden". 
    // RabbitMq Connection (Just for current client)
    var _rabbitMqConnection = null;
    // Queue (just for current client)
    var _queue = null;
    // Consumer tag (just for current client)
    var _consumerTag = null;
    // Queue name and routing key for current user
    var queueName = socket.handshake.query.queueName;
    // Connects to rabbiMq with default data to localhost guest guest
    _rabbitMqConnection = amqp.createConnection();
    // Connection ready
    _rabbitMqConnection.on('ready', function () {
        // Connection log
        console.log('#' + socket.id + ' - Connected to RabbitMQ');
        // Creates the queue (default is transient and autodelete)
        // https://www.npmjs.com/package/amqp#connectionqueuename-options-opencallback
        _rabbitMqConnection.queue(queueName, function (queue) {
            // Connection log
            console.log('#' + socket.id + ' - Connected to ' + queue.name + ' queue');
            // Stores local queue
            _queue = queue;
            // Bind to the exchange (default)
            queue.bind('users.direct', queueName, function () {
                // Binding log
                console.log('#' + socket.id + ' - Binded to users.direct exchange');
                // Consumer definition
                queue.subscribe({ack: false}, function (message, headers, deliveryInfo, messageObject) {
                    // Message log
                    console.log('#' + socket.id + ' - Received a message from route ' + deliveryInfo.routingKey);
                    // Emit the message to the client
                    socket.emit('notification', message);
                }).addCallback(function (res) {
                    // Hold on to the consumer tag so we can unsubscribe later
                    _consumerTag = res.consumerTag;
                    // Consumer tag log
                    console.log('#' + socket.id + ' - Consumer ' + _consumerTag + ' created');
                })
            });

        });
    });
    // Update our stored tag when it changes
    _rabbitMqConnection.on('tag.change', function (event) {
        if (_consumerTag === event.oldConsumerTag) {
            _consumerTag = event.consumerTag;
            // Unsubscribe from the old tag just in case it lingers
            _queue.unsubscribe(event.oldConsumerTag);
        }
    });
    // Listen for disconnection
    socket.on('disconnect', function () {
        _queue.unsubscribe(_consumerTag);
        _rabbitMqConnection.disconnect();
        console.log('#' + socket.id + ' - Socket Disconnected');
    });
});

https.listen(8080);
$(document).ready(function () {

    var socket = io('https://myserver.com:8080/', {
        secure: true, // for ssl connections
        query:  { queueName: 'notification-UID-' + UID, token: JWTToken}, // params sent to server, JWTToken for authentication
        'sync disconnect on unload': true // Every time the client unload, socket disconnects
    });

    socket.on('notification', function (data) {
        // Do what you want with your data
        console.log(data);
    });
})