使用Socket.io Redis服务器

时间:2017-06-16 17:32:11

标签: angularjs node.js sockets redis socket.io

目标:将帖子添加到特定频道时,向该频道的所有已连接订阅用户发送通知。

视图上的关系数据库表:Post,Channels,Users,Channels_Users

  • 发布:id,title,content,channel_id(表示帖子与哪个频道相关)
  • 频道:id,名称(频道列表)
  • 用户:id,用户名(用户表)
  • Channels_Users:id,channel_id,user_id(此表指示用户订阅的频道。)

目标:创建帖子后,向特定用户组发送通知。

我已经尝试了几种方式,它正如预期的那样工作。但我正在寻找正确的方法。

服务器端:socket.js

Naming conventions:

Channel name: 
   channel-1, channel-2, channel-3, ....
Namespace name('namespace-'+[channelName]) : 
   namespace-channel-1, namespace-channel-2, ...
var app = require('express')();
var request = require('request');
var http = require('http').Server(app);
var io = require('socket.io').listen(http);
var Redis = require('ioredis');
var redis = new Redis(####, 'localhost');

// Get all channels from Database and loop through it
// subscribe to redis channel 
// initialize namespace inorder to send message to it

for(var i=1; i=<50; i++) { 
    redis.subscribe('channel-'+i);
    io.of('/namespace-channel-'+i).on('connection', function(socket){
        console.log('user connected');
    });

}

// We have been subscribed to redis channel so 
// this block will hear if there is any new message from redis server

redis.on('message', function(channel, message) {

    message = JSON.parse(message);

    // send message to specific namespace, with event = newPost 

   io.of('/namespace-'+channel).emit('newPost', message.data);

});

//Listen
http.listen(3000, function(){
    console.log('Listening on Port 3000');
});

客户端:Angularjs Socket工厂代码:(提及主套接字代码)

// userChannels: user subscribed channels array
// Loop through all channel and hear for new Post and 
// display notification if there is newPost event

    userChannels.forEach(function (c) {
        let socket = {};
        console.info('Attempting to connect to namespace'+c);
        socket = io.connect(SOCKET_URL + ':3000/namespace-'+c, {query: "Authorization=token"});

        socket.on('connect',function(){
            if(socket.connected){
                console.info("namespace-" + c + " Connected!");
                // On New post event for this name space 
                socket.on('newPost', function(data) {
                    /* DISPLAY DESKTOP NOTIFICATION */
                });
            }
        });

    });

在创建新帖子时将数据发布到Redis服务器

 $data = [
        'event' => 'newPost',
        'data'  => [
            'title'      => $postTitle,
            'content'    => $postContent
        ]
    ];

    $redisChannel = "channel-" . $channelId;  // As per our naming conventions
    Redis::publish($redisChannel, json_encode($data));

用户正在为他们订阅的频道正确收到通知。

问题1:我不确定这是实现此通知事项的最佳解决方案。

问题2:当用户在多个浏览器选项卡中打开相同的应用程序时,它会收到所有这些选项卡的通知。它应该只发送一个通知。这与redis端服务器端的用户管理有关。我也不确定这一部分。

我非常感谢您对此的建议/帮助。先感谢您。

0 个答案:

没有答案